2
votes

I have a class, StandardObject, that conforms to the protocol Object. Another class, ObjectManager, has a property called objects which is an array containing instances of Object. Both StandardObject and ObjectManager are subclasses of NSObject and conform to NSCoding.

When I try to encode the objects property of ObjectManager in encodeWithCoder:, I receive an error:

cannot convert value of type '[Object]' to expected argument type 'AnyObject?'

Here is my code:

ObjectManager:

class ObjectManager: NSObject, NSCoding {

    var objects = [Object]()

    required init?(coder aDecoder: NSCoder) {

    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(objects, forKey: "Objects") //// ERROR HERE
    }

}

Object protocol:

protocol Object: class, NSCoding {
    // Currently completely empty
}

StandardObject:

class StandardObject: NSObject, Object {

    required init?(coder aDecoder: NSCoder) {

    }

    func encodeWithCoder(aCoder: NSCoder) {

    }

}

I know it has to do with the fact that you can only encode objects (or arrays of them), not structs, enums, or in this case, protocols. However, the Object protocol's declaration is:

protocol Object: class, NSCoding

which means that only classes can conform to this protocol.

Shouldn't that mean that there are only instances of classes in the objects array? Why can't it be encoded?

I have also tried casting the array to an NSArray before encoding, but I get this error:

cannot convert value of type '[Object]' to type 'NSArray' in coercion

So here are my two questions:

  1. If I made the Object protocol only have objects conform to it, shouldn't an array of Object be an array of objects?
  2. If question 1 isn't possible for some reason, how do you convert the array of Object to be able to be encoded with NSCoding?
1

1 Answers

2
votes

You need to declare your protocol as @objc, to place it into the Objective-C world:

@objc protocol Object: class, NSCoding {

The compiler will then know he will be able to toll-free bridge the Swift array with a NSArray, as you'll be able to build-up the array only with instances of classes derived from NSObject.