get Nil when calling for IBOutlet properties in function

Viewed 58

i’m working in swift and i’m trying to use the .frames to check if 2 objects of type CGRect intersect. i have my View Controller Class and a CircleClass, the CircleClass creates a circle that has gesture recognition so i can drag the circles that i create where i want to, now i want to add the option that if at the end of the drag the subview intersects my trashimageView (image view that will always be in the low-right corner of the view for all devices it's like a trashcan) it can delete the circle or subView.

the problem is that when i try to call trashImageView.frame in a function “deleteSubView” that i’ve created in the View Controller i get nil and my app crashes.

But if the IBOutlet is in the VC and my function is defined in my VC, also i can call the trashImageView.frame (CGRect Value) in the viewDidLoad and there is fine, but not in my function, why do i get nil for this value??

class ViewController: UIViewController {

@IBOutlet var trashImageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    //here i can print the CGRect value just fine
    print("my imageView init: \(trashImageView.frame)")

}

func deleteSubView(subView: UIView){

    // Here i get nil from the trashImageView.frame

    if (subView.frame.intersects(trashImageView.frame)) {
        print("intersection")
        subView.removeFromSuperview()
    }
}
}

i've checked that the Nil value is from the 'trashImageView.frame' and that the connection with the storyboard is good.

i call the function ‘delete subView’ from another class but should that matter? i don’t understand what is the error here, why do i get nil? help please.

1 Answers

Since your UIViewController is declared and instantiated using storyboard my guess is that you are creating the view controller using it's no arg initializer, i.e.: let controller = MyController() if you must create an instance of the controller programmatically do so by obtaining a reference to the Storyboard that contains the controller, i.e like this:

NOTE: Here I'm using "MyController" as the name of the class and the identifier that has been set in the storyboard.

func createMyController() -> MyController {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "MyController")

    return controller as! MyController
}

I'd also add a guard for view load state in your deleteSubview(:subView) method, so something like this:

func deleteSubView(subView: UIView) {
    guard isViewLoaded else { return }

    // Here i get nil from the trashImageView.frame
    if (subView.frame.intersects(trashImageView.frame)) {
        print("intersection")
        subView.removeFromSuperview()
    }
}
Related