11

So I have the function collectionView: cellForItemAtIndexPath here:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellID", forIndexPath: indexPath)
        print("Creating collection view number: \(indexPath.row)")
        // Configure the cell
        cell.backgroundColor = UIColor.lightGrayColor()
        let thing = Mirror(reflecting: annotation?.photos!)
        print(thing.subjectType)
        print(annotation?.photos![indexPath.row])
        return cell
}

Here is the declaration of my annotation object and photo object

class CustomAnnotation : NSManagedObject, MKAnnotation {
    @NSManaged var latitude: NSNumber
    @NSManaged var longitude : NSNumber
    @NSManaged var title : String?
    @NSManaged var subtitle: String?
    @NSManaged var photos : [Photo]?

    var coordinate = CLLocationCoordinate2D()

    override init(entity: NSEntityDescription, insertIntoManagedObjectContext context : NSManagedObjectContext?) {
        super.init(entity: entity, insertIntoManagedObjectContext: context)
    }

    init(coordinate : CLLocationCoordinate2D, context: NSManagedObjectContext) {
        let entity = NSEntityDescription.entityForName("CustomAnnotation", inManagedObjectContext: context)!
        super.init(entity: entity, insertIntoManagedObjectContext: context)
        self.longitude = coordinate.longitude
        self.latitude = coordinate.latitude
        print(photos)
    }

    func setCoordinate() {
        self.coordinate.longitude = CLLocationDegrees(self.longitude)
        self.coordinate.latitude = CLLocationDegrees(self.latitude)
    }
}

class Photo : NSManagedObject {

    @NSManaged var imagePath : String
    @NSManaged var customAnnotation : CustomAnnotation

    override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
        super.init(entity: entity, insertIntoManagedObjectContext: context)
    }
    init(imagePath: String, context : NSManagedObjectContext) {
        let entity = NSEntityDescription.entityForName("Photo", inManagedObjectContext: context)!
        super.init(entity: entity, insertIntoManagedObjectContext: context)
        self.imagePath = imagePath

    }
}

This is how I am saving the Photos object that has an inverse many-one relationship with the CustomAnnotation class

 if (annotation?.photos)!.isEmpty {
            // Load photos
            print("downloading photos")
            dispatch_async(dispatch_get_main_queue()) {
                FlickrClient.sharedInstance().getFlickrImages(self) {(result, success, errorString) in
                    if success {
                        print("loading photos")

                        // Use the inverse relationship to save the data
                        for photoURL in result as! [String] {
                            let photo = Photo(imagePath: photoURL, context: self.sharedContext)
                            photo.customAnnotation = self.annotation!
                            print(photo.imagePath)
                        }
                        dispatch_async(dispatch_get_main_queue()) {
                            self.collectionView!.reloadData()
                        }
                        CoreDataStackManager.sharedInstance().saveContext()


                    }
                    else {
                        self.showAlert("Error", message: errorString!, confirmButton: "OK")
                    }
                }
            }
        }

Here is the logs for what happens when it crashes:

Creating collection view number: 0

Optional <Array<Photo>> 

2015-12-27 00:15:07.046 VirtualTourist[10413:1965722] -[_NSFaultingMutableSet objectAtIndex:]: unrecognized selector sent to instance 0x7f956d4d8cf0

2015-12-27 00:15:07.058 VirtualTourist[10413:1965722] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSFaultingMutableSet objectAtIndex:]: unrecognized selector sent to instance 0x7f956d4d8cf0'

I don't understand why print(annotation?.photos![indexPath.row]) crashes my program. I've read online and it says that this is a result of the object being an NSSet but annotation?.photo! is an Array.So I'm kind of stuck, any hints?

YellowPillow
  • 4,100
  • 6
  • 31
  • 57

2 Answers2

20

I have solved it so because in my data model I chose the photos relationship in the CustomAnnotation entity to be unordered, a NSSet is always returned even though the in the class definition the photos variable is an Array.

enter image description here

All I needed to do was to set the Arranged to Ordered:

enter image description here

And everything works, an Array is returned instead of NSSet

YellowPillow
  • 4,100
  • 6
  • 31
  • 57
1

Relationships in Core Data is an unordered sets - you can see it in your error message [_NSFaultingMutableSet objectAtIndex:]: unrecognized selector. _NSFaultingMutableSet is an internal class, part of NSSet cluster, does not have a method objectAtIndex:.

You should sort the photos into an NSArray first.

bteapot
  • 1,897
  • 16
  • 24
  • I'm not very familiar with Swift, so it was a revelation to me that such a simple task as printing object class in console can cause SO' discussions with more than six answers. Can you check the `annotation.photos` class directly? Or is that `Mirror()` thing an official way to do it? – bteapot Dec 26 '15 at 17:29
  • I think it's the best way to do it from what I have read on SO – YellowPillow Dec 26 '15 at 17:49