类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray

Posted

技术标签:

【中文标题】类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray【英文标题】:Swift class field of type var Array is converted to immutable NSArray instead of NSMutableArray 【发布时间】:2014-09-19 09:42:28 【问题描述】:

一个简单的 Swift 类有一个 var Array 类型的字段。当类适应 Objective-C 时,字段类型公开为 NSArray(不可变),而它应该是 NSMutableArray(可变)

class Categoryy: NSObject 

    var items = Array<Item>()

Xcode生成的头文件MODULE_NAME-swift.h文件中的Categoryy swift类适配Objective-C如下:

SWIFT_CLASS("_TtC8waiterio9Categoryy")
@interface Categoryy : NSObject
@property (nonatomic, copy) NSArray * items;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

有没有办法将 var items : Array 字段转换为 Objective-c 中的可变 NSMutableArray?

【问题讨论】:

您无法将标头更改为 NSMutableArray? 这不是一个可行的解决方案 :( Xcode 生成的名为 MODULE-swift.h 的 Swift 标头在每次 swift 文件之一更改字段或方法签名时被 Xcode 擦除并重新创建。您可以手动将字段类型从 NSArray 更改为 NSMutableArray,但是一旦您更改了 swift 文件的字段或方法的签名,所有更改都会丢失。 您是否为此提交了雷达文件? 【参考方案1】:

那是因为items 属性实际上是不可变的

As you know,由于在 Swift 中基于struct 的实现Array,以下代码不会影响cat.items

let cat = Categoryy()

var _items = cat.items
_items.append(item)

相反,你必须这样调用

cat.items.append(item)

另一方面,在 Objective-C 中,[cat.items addObject:item] 与以下完全相同:

id _items = [cat items];
[_items addObject:item];

这与不工作的 Swift 代码非常相似。

遗憾的是,Objective-C 没有与 Swift 中的 cat.items.append(item) 等效的属性/方法调用语义。

这类似于:

// Objective-C
CGRect frame = view.frame;
view.frame = CGRectMake(frame.origin.x, 50, frame.size.width, frame.size.height)

// Swift
view.frame.origin.y = 50

--

也许 Apple 可以将其实现为 NSMutableArray(或私有子类),当然您可以提出要求。 我怀疑 Apple 会这样做,因为这会破坏泛型的编译时类型安全性。

无论如何,我认为你应该像这样实现Categoryy

class Categoryy: NSObject 
    var items:[Item] = []

    func addItem(item:Item) 
        items.append(item)
    

    func setItem(item:Item, atIndex:Int) 
        items[atIndex] = item;
    

    // and so on ..

【讨论】:

【参考方案2】:

如果你想要NSMutableArray,最简单的方法就是在 Swift 中使用 NSMutableArrayArray&lt;T&gt; 不会(也不能)同时表现为(不可变的)NSArrayNSMutableArray - 现在,它的行为表现为不可变的NSArray。 Swift 可以使用对应于NSMutableArray 的内置类类型,就像Array&lt;T&gt; 对应于NSArray 一样。

另一种选择是使用 Swift 类包装 NSMutableArray@objc 公开的方法来访问 NSMutableArray。这还允许您使用泛型将项目限制为 T

【讨论】:

【参考方案3】:

作为一种解决方法,您可以使用方法在 Swift 文件中调用 append,而不是直接在 Objective-C 中访问 Swift 数组。

斯威夫特:

func addItem(item:Item)

    items.append(item)

目标-C:

[yourSwiftObject addItem:item];

【讨论】:

以上是关于类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray的主要内容,如果未能解决你的问题,请参考以下文章

Swift学习笔记:集合类型

CORBA::String_var -> 我不能为这种类型的类字段分配任何值

Swift4.0 Array详解

Swift入坑系列—集合类型

《从零开始学Swift》学习笔记(Day 17)——Swift中数组集合

Swift 3:NSArray 元素无法匹配 Swift Array 元素类型