Mika Mika - 5 months ago 27
Swift Question

Loop through [AnyObject]? results in does not have a member named generator

Why can't you loop through

[AnyObject]?
directly? What does it mean that there is no named generator? What is the proper technique for looping through an
[AnyObject]?
type?

This code is giving me an error telling me that it does not have a member named generator.

for screen in NSScreen.screens() {
var result : Bool = workspace.setDesktopImageURL(imgurl, forScreen: screen, options: nil, error: &error)
}

Answer

screens returns an optional, so before using the actual value you have to unwrap - the recommended method is optional binding:

if let screens = NSScreen.screens() {
    for screen in screens {
        var result : Bool = workspace.setDesktopImageURL(imgurl, forScreen: screen, options: nil, error: &error)
    }
}

Read more about Optionals

Note that NSScreen.screens returns [AnyObject]?, so you might want to cast the array as [NSScreen] in the optional binding:

if let screens = NSScreen.screens() as? [NSScreen] {
    for screen in screens {
        var result : Bool = workspace.setDesktopImageURL(imgurl, forScreen: screen, options: nil, error: &error)
    }
}

Addendum Answer to question in comment: why the error message says [AnyObject]? does not have a member named generator

An optional is of a different type than the value it contains (an optional is actually an enum). You can iterate an array, but you cannot iterate over an integer or an enum.

To understand the difference, let me make a real life example: you buy a new TV on ebay, the package is shipped to you, the first thing you do is to check if the package (the optional) is empty (nil). Once you verify that the TV is inside, you have to unwrap it, and put the box aside. You cannot use the TV while it's in the package. Similarly, an optional is a container: it is not the value it contains, and it doesn't have the same type. It can be empty, or it can contain a valid value.