swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.3k stars 10.34k forks source link

[SR-4950] Swift does not honor NSMutableArray generics from objective-c classes #47527

Open swift-ci opened 7 years ago

swift-ci commented 7 years ago
Previous ID SR-4950
Radar None
Original Reporter tourultimate (JIRA User)
Type Bug

Attachment: Download

Environment xcode 8.2.1
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 1 | |Component/s | Compiler | |Labels | Bug, ClangImporter | |Assignee | None | |Priority | Medium | md5: 3c3968f70787ac6cfb10e89bbcfe9e20

Issue Description:

Consider the following objective-c classes:

```objective-c
@interface Layer : NSObject
@property (nonatomic, strong) NSString *name;
@end

@interface Map : NSObject

@property (nonatomic, strong, readonly) NSMutableArray\<Layer *> *layers;

@end
```

Trying to use them with swift like so:

```swift
let map = Map()

for layer in map.layers{
print(layer.name)
}
```

You will end up with compiler errors as the array is emitting AnyObjects instead of the expected type (Layer in this case)

belkadan commented 7 years ago

Yep, we're not able to import NSArray with generics right now, and that extends to NSMutableArray for consistency. I agree that it can be frustrating in cases like this, though.

swift-ci commented 7 years ago

Comment by tourultimate (JIRA)

Jordan,

I'm not quite sure what you mean that we aren't able to import NSArray with generics. If I change the code to this:

```
@property (nonatomic, strong, readonly) NSArray\<Layer *> *layers;
```

It works fine. It seems to be only a problem with NSMutableArray.

belkadan commented 7 years ago

That's imported as a Swift Array rather than a Foundation NSArray. We can't just do that for NSMutableArray because Swift arrays are value types, which means an update to the array isn't automatically visible across clients.

One workaround here is to expose your property as an NSArray, but declare the backing instance variable in the .m file to be an NSMutableArray.