Useruuu
Useruuu

Reputation: 145

Accessing elements from another view controller comes up nil

I have an alert view that i made using presentr from GitHub. I used a simple view controller that will overlay over the current view controller. Now i have elements such as a UIImage and a UIlabel from the first view controller that needs to be accessed by the alert view controller. But when I click a unbutton in the alert view controller to access the uiimage and text from uilabel from the firstviewcontroller. Here is the code. Can you show me how I can fix this. I can't segue the data because I'm presenting the view controller and the data I'm trying to access is too much too segue anyway. I keep getting this error "fatal error: unexpectedly found nil while unwrapping an Optional value" overtime i click the save button in alertviewcontroller.

class firstviewcontroller: UIViewController{
    var photos2: [ImageSource]?
    @IBOutlet weak var Label: UIlabel!
    @IBOutlet weak var Image: UIImage!
}

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
        let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

Upvotes: 0

Views: 845

Answers (2)

Zonily Jame
Zonily Jame

Reputation: 5349

The biggest mistake you're making is that you are creating a new instance of firstviewcontroller instead of just accessing the current one.

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)
        let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller // This is the mistake

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

What you should do instead is access the presentingViewController since you presented the alertviewcontroller using the present function

The code would look like this

class alertviewcontroller: UIViewController{
    @IBAction func Save(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        let storyboard: UIStoryboard = UIStoryboard.init(name: "Main", bundle: nil)

        // NOTE: only do implicit unwrapping `as!` if you're sure that the value you're unwrapping is not `nil` or it is of the correct `data type` cause it might cause your app to crash
        let firstViewController: firstviewcontroller = self.presentingViewController as! firstviewcontroller

        if let image = firstViewController.Image { 
            imageview.image = image
        }
        if let label = firstViewController.Label {
            label.text = Label.text
        }
    }
}

Tip: Please review Swift coding guidelines since there are some minor mistakes regarding your naming of methods, variables, and classes.

Upvotes: 1

Usman Javed
Usman Javed

Reputation: 2455

Might I am wrong but after review your code I have found this messing statement

let firstViewController: firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "firstviewcontroller") as! firstviewcontroller

In this statement you are creating a new instance of firstviewcontroller not accessing already created instance of firstviewcontroller.

Next, you said

I used a simple view controller that will overlay over the current view controller

So I have assumed you didn't present or push alertviewcontroller on current viewController, on that behave I suggest you the following solutions

  1. In alertviewcontroller get the instance of topViewController by using this method

    class func topViewController(base: UIViewController? = (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
    

then you can transfer your data from alertviewcontroller to topViewController.

  1. Next solution is that you can pass values from alertviewcontroller to firstviewcontroller by using delegates.

Upvotes: 0

Related Questions