32

In CoreData I have defined an ordered to-many relationship. This relationship is defined in Swift like this:

@NSManaged var types : NSMutableArray

However, to use Swift at it's best, I want to use a normal Swift array like Type[]. However, CoreData forces me to use NS(Mutable)Array. How can I type-cast / convert the NSArray to Array<Type>[]?

Apparently the confusion arises from the following error:

let array = obj.types as T[] // Cannot convert expression's type 'Node[]' to type '$T2'

While this is accepted by the editor:

let array = obj.types as AnyObject[] as T[] // No complaint
3
  • An ordered relationship is (as far as I know) represented by an NSOrderedSet, not by an NSMutableArray. Commented Jun 26, 2014 at 5:24
  • 2
    "I'm currently using obj.types.allObjects as Type[], but that feels like a hack/workaround". No, that is how you cast an NSArray to a Swift array of a specific type. Commented Jun 26, 2014 at 5:36
  • 1
    Wow, why the downvotes? I have the same question and it does seem worthy of asking. Commented Jun 27, 2014 at 19:12

4 Answers 4

16

I'm currently using obj.types.allObjects as Type[], but that feels like a hack/workaround.

Then revise your feelings. What you're doing is exactly how you do "type-cast / convert the NSArray to Array<Type>[]."

An NSArray always arrives into Swift as containing AnyObject (i.e. an Array<AnyObject>, aka AnyObject[]). Casting it down to a specific type, if you know that it contains all one type, is up to you, and how you are doing it is exactly what you are supposed to do.

EDIT In Swift 2.0 and the new iOS 9 APIs, an NSArray will often arrive correctly typed, and no cast will be needed.

EDIT 2 In Swift 3.0, an NSArray that is not correctly typed, though uncommon, will arrive as containing Any instead of AnyObject and will still have to be cast down to a specific type.

Sign up to request clarification or add additional context in comments.

4 Comments

That 'workaround' is not valid for NSArray, but for NSSet. So I'm still looking for a nice solution.
it is valid for an array -allObjects is a method on NSSet that returns all elements as an array.
Admitted, I was expecting an allObjects on NSArray; but NSArray itself can be casted to an Array. However I'm still unclear of why two casts are required, see my updated question.
Using swift 2.2, the cast is still needed in order to properly use the map function.
2

The following is a working piece of code from one of my projects that might help?

if let rawArray = rawData as? NSArray,
   let castArray = rawArray as? Array< Dictionary< String, AnyObject > >
   { 
       // etc... 
   }

It works, although I'm not sure it would be considered optimal.

Comments

1

Enumerate them that way :

for type in types.array {
    // Do something
}

Or use simply the array property of the NSOrderedSet you are using, like so :

types.array

Comments

0

You are going to have to create a new generic array and manually populate it as follows:

    var result = Type[]()

    for item : AnyObject in self {
        //  Keep only objC objects compatible with OutType
        if let converted = bridgeFromObjectiveC(item, Type.self) {
            result.append(converted)
        }
    }

1 Comment

Iterating over an array to copy it to a new array doesn't seem very elegant to me. Is this the most simple solution, even when I know all the instances in the array will be of the same type?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.