Reputation: 5
I am trying to create a dictionary containing four images to set one of them as background of the UIView
. The image selected will depend on the value of a rand
number.
Here is code that creates a dictionary:
let backgroundDict = [
"Clouds": UIImage(named: "clouds.jpg"),
"Clouds2": UIImage(named: "clouds2.jpg"),
"Sunset": UIImage(named: "sunset.jpg"),
"Sunset2": UIImage(named: "sunset2.jpg")
]
Here is how I create the rand
number:
var randNumber = Int(arc4random_uniform(UInt32(backgroundDict.count)))
This is the code that declares an array with the keys of the dictionary:
let backgroundArray = Array(backgroundDict.keys)
I get the error 'Int' is not convertible to 'Range<Int>
when I try to set the background image:
self.view.backgroundColor = UIColor(patternImage: backgroundDict[backgroundArray[randNumber] as String])
Why is that happening?
Upvotes: 0
Views: 493
Reputation: 4653
Dictionaries return optionals in swift to handle the case of non-existing keys. Using if let image = backgroundDict[backgroundArray[randNumber]]
makes sure there's a corresponding UIImage for the key backgroundArray[randNumber]
before assigning to the variable image
.
The image!
(optional unwrapping) inside the conditional is used because image
is of type UIImage?
(this will cause an error if it's nil). Initialising UIImage by name returns an optional to handle the case of not finding an image with the name provided.
let backgroundDict = [
"Clouds": UIImage(named: "clouds.jpg"),
"Clouds2": UIImage(named: "clouds2.jpg"),
"Sunset": UIImage(named: "sunset.jpg"),
"Sunset2": UIImage(named: "sunset2.jpg")
]
var randNumber = Int(arc4random_uniform(UInt32(backgroundDict.count)))
let backgroundArray = Array(backgroundDict.keys)
if let image = backgroundDict[backgroundArray[randNumber]] {
self.view.backgroundColor = UIColor(patternImage: image!)
}
Upvotes: 0
Reputation: 12833
UIImage(named: "")
is an optional initializer init?
and UIColor(patternImage: ...)
takes a UIImage, so you need to unwrap your images before using them. You also need to unwrap the value returned from the dictionary:
//In Swift 1.2
if let optionalImage = backgroundDict[backgroundArray[randNumber] as String], image = optionalImage {
UIImage(patternImage: image)
}
//In Swift 1.1
if let optionalImage = backgroundDict[backgroundArray[randNumber] as String] {
if let image = optionalImage {
UIImage(patternImage: image)
}
}
Upvotes: 1
Reputation: 72760
There are 2 similar problems:
UIImage
initializer is failable, so it returns an optionalThere are 2 ways to fix it:
force unwrapping the image twice:
UIColor(patternImage: backgroundDict[backgroundArray[randNumber] as String]!!)
^^
force unwrap images when creating the dictionary:
let backgroundDict = [
"Clouds": UIImage(named: "clouds.jpg")!,
"Clouds2": UIImage(named: "clouds2.jpg")!,
"Sunset": UIImage(named: "sunset.jpg")!,
"Sunset2": UIImage(named: "sunset2.jpg")!
]
then use a single force unwrap when accessing the dictionary by value:
UIColor(patternImage: backgroundDict[backgroundArray[randNumber] as String]!)
Although I'd usually recommend using optional binding to prevent runtime exceptions, I presume that in this case images must exist, and if they don't it is a development mistake (i.e. failing to add the images to the project or mistyping their names) - so an exception is a great way to figure that out.
Upvotes: 2