Reputation: 73
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