类型为 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 中使用 NSMutableArray
。 Array<T>
不会(也不能)同时表现为(不可变的)NSArray
和 NSMutableArray
- 现在,它的行为表现为不可变的NSArray
。 Swift 可以使用对应于NSMutableArray
的内置类类型,就像Array<T>
对应于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的主要内容,如果未能解决你的问题,请参考以下文章
CORBA::String_var -> 我不能为这种类型的类字段分配任何值