【问题标题】:Swift class field of type var Array is converted to immutable NSArray instead of NSMutableArray类型为 var Array 的 Swift 类字段被转换为不可变的 NSArray 而不是 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 文件的字段或方法的签名,所有更改都会丢失。
  • 您是否为此提交了雷达文件?

标签: objective-c swift nsmutablearray nsarray xcode6


【解决方案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&lt;T&gt; 不会(也不能)同时表现为(不可变的)NSArray 和 NSMutableArray - 现在,它的行为表现为不可变的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];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        • 1970-01-01
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多