47

I'm trying to access the url of an object stored in an array, but I'm getting errors no matters what methods I'm using.

let userPhotos = currentUser?.photos

    for var i = 0; i < userPhotos!.count ; ++i {
        let url = userPhotos[i].url
    }

Here I get

Could not find member 'url'

and with a foreach:

for photo in userPhotos {

        Utils.getImageAsync(photo.url , completion: { (img: UIImage?) -> () in

        })
    }

I get:

'[ModelAttachment]?' does not have a member named 'Generator'

My array is var photos: Array<ModelAttachment>? and my ModelAttachment looks like this:

class ModelAttachment :Model {
var id: String?
var url: String?
var thumb: String?
}

Any pointers to what I'm doing wrong would be great :)

1
  • 1
    If you declare your photos array as: [ModelAttachment], you should be able to use the for loops. Commented Jun 2, 2015 at 12:30

4 Answers 4

83

Unwrap and downcast the objects to the right type, safely, with if let, before doing the iteration with a simple for in loop.

if let currentUser = currentUser, 
    let photos = currentUser.photos as? [ModelAttachment] 
{
    for object in photos {
        let url = object.url
    }
}

There's also guard let else instead of if let if you prefer having the result available in scope:

guard let currentUser = currentUser, 
    let photos = currentUser.photos as? [ModelAttachment] else 
{
    // break or return
}
// now 'photos' is available outside the guard
for object in photos {
    let url = object.url
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! In the end it works by modifying your code like this: for object in userPhotos! as [ModelAttachment]
You can write simply for object in userPhotos! and it will work. But it defeats the purpose of optional types.
6

Your userPhotos array is option-typed, you should retrieve the actual underlying object with ! (if you want an error in case the object isn't there) or ? (if you want to receive nil in url):

let userPhotos = currentUser?.photos

for var i = 0; i < userPhotos!.count ; ++i {
    let url = userPhotos![i].url
}

But to preserve safe nil handling, you better use functional approach, for instance, with map, like this:

let urls = userPhotos?.map{ $0.url }

2 Comments

note that for;; syntax does not exist in Swift 3 anymore
This has been removed from Swift 3.
4

You can try using the simple NSArray in syntax for iterating over the array in swift which makes for shorter code. The following is working for me:

class ModelAttachment {
    var id: String?
    var url: String?
    var thumb: String?
}

var modelAttachementObj = ModelAttachment()
modelAttachementObj.id = "1"
modelAttachementObj.url = "http://www.google.com"
modelAttachementObj.thumb = "thumb"

var imgs: Array<ModelAttachment> = [modelAttachementObj]

for img in imgs  {
    let url = img.url
    NSLog(url!)
}

See docs here

Comments

0

The photos property is an optional array and must be unwrapped before accessing its elements (the same as you do to get the count property of the array):

for var i = 0; i < userPhotos!.count ; ++i {
    let url = userPhotos![i].url
}

1 Comment

This was supported formerly but has been deprecated since Swift 3.0. Please use formal Swift syntax

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.