Amen Parham
Amen Parham

Reputation: 73

Terminating app due to uncaught exception 'Attempt to call unavailable initializer

I have a view controller with a button. Once clicked, a new view controller is suppose to be presented.

CropperViewController

@IBAction func cropImageAction(_ sender: AnyObject) {
        
         guard let image = cropView.croppedImage else {
            return
         }
         
         let imageViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ImageViewController") as! ImageViewController
         imageViewController.image = image
         navigationController?.pushViewController(imageViewController, animated: true)
    }

Once it is called and a new controller is suppose to present, but instead I get an error:

Terminating app due to uncaught exception 'Attempt to call unavailable initializer.', reason: 'init unavailable, use designated initializer'
*** First throw call stack:
(0x1958e4f20 0x18d7872b8 0x1005ccf88 0x1004b2a7c 0x1004a8cac 0x1004b2798 0x1004b28a8 0x197e9d788 0x1a0c5c804 0x1a0c5c458 0x197e9a37c 0x1a0c5c804 0x1a0c5c98c 0x1a0c5c458 0x197e9d934 0x197f84f04 0x197fa4880 0x1003c58a4 0x1003c5a2c 0x197ede4f8 0x197ede3d0 0x197ede220 0x1983f5200 0x1983f6a14 0x197e1ef78 0x197e1ea20 0x197c9f924 0x197ca1118 0x197ca9e10 0x197b9c740 0x197b9a660 0x197b9a2a4 0x197b9b148 0x1958b7834 0x1958b77c8 0x1958b5298 0x1958b4484 0x1958b3cd8 0x1da3011a8 0x197eedae8 0x197fa1d98 0x100429bd0 0x1b908b154)
libc++abi: terminating due to uncaught exception of type NSException"

This is the view I'm trying to open.

ImageViewController.swift

import UIKit
import Firebase
import FirebaseDatabase

final class ImageViewController: UIViewController {
    
    var image: UIImage!
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet var cancelLabel: UIButton!
    @IBOutlet var backButton: UIButton!
    @IBOutlet var saveButton: UIButton!
    
    var ref: DatabaseReference!
    let userID = Auth.auth().currentUser?.uid
    let storage = Storage.storage()
    
    var currentUsersName = String()
    var frontorBack = String()
    var frontorBack2 = String()
    
    var fadeTimer:Timer?
    var canCancelUpload_Timer:Timer?
    var imageData = Data()
    var uploadTask = StorageUploadTask()
    var uploading : Bool = false
    @IBOutlet var cancelUploadBtn: UIButton!
    
    override func viewDidDisappear(_ animated: Bool) {
        canCancelUpload_Timer?.invalidate()
        fadeTimer?.invalidate()
        NotificationCenter.default.removeObserver(self)
    }
    
    func getUser() {
        ref = Database.database().reference()
        ref.child("Users").child(userID!).queryOrderedByKey().observeSingleEvent(of: DataEventType.value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            let currentUsersNameDB = value?["userName"] as? String ?? ""
            
            self.currentUsersName = currentUsersNameDB
            
            print(currentUsersNameDB)
        })
    }
    
    @IBAction func backAction(_ sender: UIButton) {
        
        _ = navigationController?.popViewController(animated: true)
    }
    
    @IBAction func showListAction(_ sender: UIButton) {
//        resize(image)
        
        backButton.isHidden = true
        saveButton.isHidden = true
        cancelLabel.isEnabled = false
        backButton.isEnabled = false
        saveButton.isEnabled = false
        cancelLabel.setTitleColor(UIColor(red: 0/255, green: 182/255, blue: 255/255, alpha: 1.0), for: .normal)
        cancelLabel.setTitle("Uploading Card...", for: .normal)
        
        fadeTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(ImageViewController.fadeTimerFunc), userInfo: nil, repeats: false)
        Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ImageViewController.uploadConfirmed), userInfo: nil, repeats: false)
    }
    
    @objc func uploadConfirmed() {
        uploadMedia() { url in
            if url != nil {
            }
        }
    }
    
    @objc func fadeTimerFunc() {
        UIView.animate(withDuration: 2.5, delay: 0, options: [.repeat,.autoreverse], animations: {
            self.cancelLabel.alpha = 0.0
        }, completion: nil)
    }
    
    // Without Compress
//    func uploadMedia(completion: @escaping (_ url: String?) -> Void) {
//        let storageRef = Storage.storage().reference().child("\(currentUsersName)/\(frontorBack).jpg")
//
//            let metadata = StorageMetadata()
//            metadata.contentType = "image/jpeg"
//
//            storageRef.putData(imageData, metadata: metadata) { (metadata, error) in
//                if error != nil {
//                    print("error")
//                    completion(nil)
//                } else {
//                    completion((metadata?.downloadURL()?.absoluteString)!)
//                    print((metadata?.downloadURL()?.absoluteString)!)
//                    self.ref.child("Users").child(self.userID!).updateChildValues(["\(self.frontorBack2)" : (metadata?.downloadURL()?.absoluteString)!])
//
//                    self.doneOrCancel()
//                }
//        }
//    }
    
//     With Compress
    func uploadMedia(completion: @escaping (_ url: String?) -> Void) {
        uploading = true
        canCancelUpload_Timer = Timer.scheduledTimer(timeInterval: 20, target: self, selector: #selector(ImageViewController.canCancelUpload), userInfo: nil, repeats: false)
        let storageRef = Storage.storage().reference().child("\(currentUsersName)/\(frontorBack).png")

        if let uploadData = image.pngData() {

            let metadata = StorageMetadata()
            metadata.contentType = "image/png"

            uploadTask = storageRef.putData(uploadData, metadata: metadata) { (metadata, error) in
                if error != nil {
                    print("error")
                    completion(nil)
                } else {
//                    completion((metadata?.downloadURL()?.absoluteString)!)
//                    print((metadata?.downloadURL()?.absoluteString)!)
//                    self.ref.child("Users").child(self.userID!).updateChildValues(["\(self.frontorBack2)" : (metadata?.downloadURL()?.absoluteString)!])
//
//                    self.doneOrCancel()
                }
            }
        }
    }
    
    @objc func canCancelUpload() {
        cancelUploadBtn.alpha = 1
        cancelLabel.setTitle("Still Uploading...", for: .normal)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        if (editingCard == "front") {
            frontorBack = "frontCardImage"
            frontorBack2 = "frontCard"
        } else if (editingCard == "back") {
            frontorBack = "backCardImage"
            frontorBack2 = "backCard"
        }
    
        print("frontorBack: \(frontorBack)")
        print("frontorBack2: \(frontorBack2)")
        
        NotificationCenter.default.addObserver(self, selector: #selector(ImageViewController.cancelLabelAlphaTo1), name: NSNotification.Name(rawValue: "setAlphaTo1"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(ImageViewController.cancelStartFadeAgain), name: NSNotification.Name(rawValue: "startFadeAgain"), object: nil)
        
        getUser()
        Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ImageViewController.checkInternet), userInfo: nil, repeats: true)
    }
    
    @objc func cancelLabelAlphaTo1() {
        if (backButton.isHidden == true && saveButton.isHidden == true) {
            cancelLabel.layer.removeAllAnimations()
            fadeTimer?.invalidate()
            cancelLabel.alpha = 1
        }
    }
    
    @objc func cancelStartFadeAgain() {
        if (backButton.isHidden == true && saveButton.isHidden == true) {
            fadeTimerFunc()
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
//        AppUtility.lockOrientation(.landscapeLeft, andRotateTo: .landscapeLeft)
        if UIDevice().userInterfaceIdiom == .phone {
            switch UIScreen.main.nativeBounds.height {
            case 2436:
                print("iPhone X")
                let yPosition = self.view.frame.height/2 - (self.view.frame.height / 1.1)/2
                let xPosition = self.view.frame.width/2 - (self.view.frame.width / 1.5)/2
                imageView.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.5, height: self.view.frame.height / 1.3)
                imageView.dropShadow(color: .black, opacity: 1, offSet: CGSize(width: 1, height: 1), radius: 3, scale: true)
                imageView.image = image
            default:
                print("unknown")
                let yPosition = self.view.frame.height/2 - (self.view.frame.height / 1.1)/2
                let xPosition = self.view.frame.width/2 - (self.view.frame.width / 1.3)/2
                imageView.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.3, height: self.view.frame.height / 1.3)
                imageView.dropShadow(color: .black, opacity: 1, offSet: CGSize(width: 1, height: 1), radius: 3, scale: true)
                imageView.image = image
            }
        }
    }
    
    @IBAction func canceled(_ sender: Any) {
        doneOrCancel()
    }
    
    func doneOrCancel() {
        if let vc = self.storyboard?.instantiateViewController(withIdentifier: "yourCardVC") as? SWRevealViewController {
            let transition = CATransition()
            transition.duration = 0.5
            transition.type = CATransitionType.push
            transition.subtype = CATransitionSubtype.fromLeft
            view.window!.layer.add(transition, forKey: kCATransition)
            present(vc, animated: true, completion: nil)
            editingCard = ""
        }
    }
    
    func resize(_ image: UIImage) -> UIImage {
        var actualHeight = Float(image.size.height)
        var actualWidth = Float(image.size.width)
        let maxHeight: Float = 300.0
        let maxWidth: Float = 400.0
        var imgRatio: Float = actualWidth / actualHeight
        let maxRatio: Float = maxWidth / maxHeight
        let compressionQuality: Float = 1
        //50 percent compression
        if actualHeight > maxHeight || actualWidth > maxWidth {
            if imgRatio < maxRatio {
                //adjust width according to maxHeight
                imgRatio = maxHeight / actualHeight
                actualWidth = imgRatio * actualWidth
                actualHeight = maxHeight
            }
            else if imgRatio > maxRatio {
                //adjust height according to maxWidth
                imgRatio = maxWidth / actualWidth
                actualHeight = imgRatio * actualHeight
                actualWidth = maxWidth
            }
            else {
                actualHeight = maxHeight
                actualWidth = maxWidth
            }
        }
        let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(actualWidth), height: CGFloat(actualHeight))
        UIGraphicsBeginImageContext(rect.size)
        image.draw(in: rect)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        imageData = img!.jpegData(compressionQuality: CGFloat(compressionQuality))!
        UIGraphicsEndImageContext()
        
        uploadMedia() { url in
            if url != nil {
            }
        }
        
        return UIImage(data: imageData) ?? UIImage()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        // AutoLogout
        autoLogOut()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        self.ref.child("Users").child(self.userID!).removeAllObservers()
    }
    
    func autoLogOut() {
        // Notify When Changed Value
        self.ref.child("Users").child(self.userID!).queryOrderedByKey().observe(.value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            let autoLogNum_DBChanged = value?["autoLogNum"] as? String ?? ""
            
            print("\n\ncurrentDeviceLoginNum 2: \(currentDeviceLoginNum)")
            print("autoLogNum_DBChangedm 2: \(autoLogNum_DBChanged)\n\n")
            if (currentDeviceLoginNum == autoLogNum_DBChanged || currentDeviceLoginNum == "") {
                print("You are good, Stay Where you are!")
            } else {
                print("Auto Sign Out")
                let firebaseAuth = Auth.auth()
                do {
                    try firebaseAuth.signOut()
                } catch let signOutError as NSError {
                    print ("Error signing out: %@", signOutError)
                }
                
                // Don't forget to reset when view is being removed
                AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
                
                if let vc3 = self.storyboard?.instantiateViewController(withIdentifier: "loginSB") as? loginVC {
                    let transition = CATransition()
                    transition.duration = 0
                    transition.type = CATransitionType.push
                    transition.subtype = CATransitionSubtype.fromLeft
                    self.view.window!.layer.add(transition, forKey: kCATransition)
                    self.present(vc3, animated: true, completion: nil)
                }
            }
        })
    }
    
    @objc func checkInternet() {
        if (uploading == true) {
            if !(currentReachabilityStatus == .reachableViaWiFi || currentReachabilityStatus == .reachableViaWWAN) {
                // No Connection
                uploading = false
                cancelLabel.layer.removeAllAnimations()
                fadeTimer?.invalidate()
                cancelLabel.alpha = 1
                cancelUploadBtn.alpha = 0
                canCancelUpload_Timer?.invalidate()
                cancelLabel.setTitleColor(UIColor.red, for: .normal)
                cancelLabel.setTitle("No Internet Connection!", for: .normal)
                cancelLabel.shake(count: 3, for: 0.3, withTranslation: 10)
                uploadTask.cancel()
                Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(ImageViewController.CancelUpload), userInfo: nil, repeats: false)
            } else {
                // Connection
            }
        }
    }
    
    @objc func CancelUpload() {
        uploading = false
        uploadTask.cancel()
        cancelLabel.layer.removeAllAnimations()
        fadeTimer?.invalidate()
        cancelLabel.alpha = 1
        cancelUploadBtn.alpha = 0
        backButton.isHidden = false
        saveButton.isHidden = false
        cancelLabel.isEnabled = true
        backButton.isEnabled = true
        saveButton.isEnabled = true
        cancelLabel.setTitleColor(UIColor.red, for: .normal)
        cancelLabel.setTitle("EXIT", for: .normal)
    }
    
    @IBAction func cancelUpload_Action(_ sender: Any) {
        CancelUpload()
    }
}

It seems the bug is somewhere in my "ImageViewController". Because if I open ImageViewController off the bat, I get the error, but if I open another view controller instead of "ImageViewController", it works perfectly. Every other view I have works completely fine. I'm passing an image variable with this one, this used to work in the past but now in Swift 5 it doesn't. I'm not to educated in swift and trying my best. I hope someone can help.

Video - Video shows app. I first crop my image that I want to then display on the next view, but once I click "Done" it crashes

I tried to write code to open a new view controller. But when I go from imagePicker from camera roll selection, and choose a photo, the app crashes. I tried different ways to preview a new view, segue a new view, or even just opening the "ImageViewController" off the bat without sending any info through but it crashes every time.

If there is anything I’m missing that is needed please let me know I will do my best to provide what helps. I’m confused my self here I apologize in advance.

Upvotes: 0

Views: 58

Answers (0)

Related Questions