Reputation: 41
I am new to Swift/iOS, so please bear with me:
I am trying to access a function in one class from another class, and update an UIImage name.
Within my viewcontroller class I have
class Documents: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var UpdateImage: UIImageView
override func viewDidLoad() {
super.viewDidLoad()
UpdateImage()
}
func UpdateImage() {
UpdateImage.image = UIImage(named: "NewImage")
}
}
Everything works, the Image gets updated to "NewImage"
Question: I can access the UpdateImage func from another class, but why is it generating an error when trying to change the image in the Documents class?
class GetChanges {
var success = { operation:AFHTTPRequestOperation!, response:AnyObject!) -> Void in
var MakeChange = Documents()
MakeChange.UpdateImage()
}
}
This generates an error on the "UpdateImage.image = UIImage(named: "NewImage")" in the Documents Class; "fatal error: unexpectedly found nil while unwrapping an Optional value"
Upvotes: 4
Views: 1363
Reputation: 900
Read about View Contoller's lifecycle, it's very important knowledge for iOS developer.
As Logan said:
You are creating a new instance of Documents. This is not initialized through the nib/storyboard, and thus it never populated the IBOutlet value UpdateImage
This means that after call init
for ViewController (i.e. Documents()
) nib
isn't loaded. You can use outlets of viewController in another code only after viewDidLoad
stage. Apple docs:
The nib file you specify is not loaded right away. It is loaded the first time the view controller's view is accessed. If you want to perform additional initialization after the nib file is loaded, override the viewDidLoad() method and perform your tasks there.
You can remove MakeChange.UpdateImage()
, because it will be called in viewDidLoad
. Or, if you want pass specific image name to view controller:
class Documents: UIViewController, UITableViewDataSource,
UITableViewDelegate {
@IBOutlet var UpdateImage: UIImageView
var imageName: String?
override func viewDidLoad() {
super.viewDidLoad()
updateImageView()
}
func updateImageView() {
if let imageName = imageName {
UpdateImage.image = UIImage(named: imageName)
}
}
}
After that, you can use
let documentsViewController = Documents
documentsViewController.imageName = "newImage"
When you load documentsViewController, newImage will be presented
Upvotes: 0
Reputation: 53142
When you call it within the class itself, it is operating on itself and it has already been created from a nib/storyboard. This means that UpdateImage
exists.
When you call the method from another class, when you call this line:
var MakeChange = Documents()
You are creating a new instance of Documents
. This is not initialized through the nib/storyboard, and thus it never populated the IBOutlet
value UpdateImage
. Because this value doesn't exist, it unexpectedly finds nil
and throws an error.
You need to somehow retain a reference to the instance of Documents
you're trying to display. I'd need more information to tell you how to do that.
Also, because you mentioned that you're new, I'd like to point out a few issues I notice with your code that is making it very difficult to read.
Capitalized names are reserved for Types
variable names should (almost) never begin with a capital letter.
Variable names should reflect the object they represent. UpdateImage
sounds like it is an image. It would be better to name this updateImageView
Functions should be lowercase as well. It is strange to see capitalization this way and makes the code a bit uncomfortable to read.
Good luck!
Upvotes: 5