在Swift中创建NSMutabaleArray子类

Col*_*inE 6 nsmutablearray swift

我正在尝试NSMutableArray在Swift中创建一个子类,它支持一个数组文字初始化器.

我可以创建一个简单的子类:

class MyArray: NSMutableArray {
}
Run Code Online (Sandbox Code Playgroud)

初始化工作正常:

let arrayInstance: MyArray = MyArray()
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试使用数组文字:

let arrayInstance: MyArray = ["one"]
Run Code Online (Sandbox Code Playgroud)

它在运行时失败了[NSMutableArray initWithCapacity:]: method only defined for abstract class..

我可以添加此初始化程序,因此我还必须添加其他所需的初始化程序:

class MyArray: NSMutableArray {
  override init(capacity numItems: Int) {
    super.init(capacity: numItems)
  }

  required init(coder aDecoder: NSCoder) {
      fatalError("init(coder:) has not been implemented")
  }

  required convenience init(arrayLiteral elements: AnyObject...) {
      fatalError("init(arrayLiteral:) has not been implemented")
  }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,第二个必需的初始化程序产生以下编译器错

来自扩展的声明无法覆盖

看起来我被卡住了!任何人都可以建议一种方法来创建一个NSMutableArray支持数组文字的子类吗?否则它会回到Objective-C对我来说!

Ham*_*mza 0

这里的问题不是数组文字,而且第一次初始化也不能正常工作,如果这样做,您可能会遇到“相同”的崩溃:

\n\n
let arrayInstance: MyArray = MyArray()\narrayInstance.count\n\n//OR\nlet secondArrayInstance: MyArray = MyArray(objects: ["one"], count: 1) // method used by literals syntax\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题在于 NSMutableArray 的子类化,因为它是一个类簇。\n根据 Apple 的说法,没有理由这样做:

\n\n
\n

通常没有什么理由对 NSArray 进行子类化。该类很好地完成了其设计目的\xe2\x80\x94维护对象的有序集合。但在某些情况下,自定义 NSArray 对象可能会派上用场。以下是一些可能性:

\n\n

更改 NSArray 存储其集合元素的方式。您可能出于性能原因或为了更好地与旧代码兼容而执行此操作。

\n\n

获取有关集合所发生情况的更多信息\n(例如,统计信息收集)。

\n
\n\n

类簇定义

\n\n
\n

类簇是 Foundation 框架广泛使用的一种设计模式。类簇将许多私有具体子类分组到公共抽象超类下。以这种方式对类进行分组简化了面向对象框架的公开可见体系结构,而不会降低其功能丰富性。类集群基于抽象工厂设计模式。

\n
\n\n

NSArray 子类化的替代方案

\n\n
\n

在创建 NSArray 的自定义类之前,请研究 NSPointerArray\n 和相应的 Core Foundation 类型 CFArray Reference。因为 NSArray 和 CFArray 是免费桥接的,所以您可以在代码中用 CFArray 对象替换 NSArray 对象(通过适当的转换)。虽然它们是对应的类型,但 CFArray 和 NSArray 不具有相同的接口或实现,有时您可以使用 CFArray 执行 NSArray 无法轻松执行的操作。例如,CFArray 提供了一组回调,其中一些用于实现自定义保留-释放行为。如果您为这些回调指定 NULL 实现,则可以轻松获得非保留数组。

\n\n

如果您想要添加的行为补充现有类的行为,您可以在 NSArray 上编写一个类别。但请记住,此类别将对您使用的所有 NSArray 实例都有效,这可能会产生意想不到的后果。或者,您可以使用组合来实现所需的行为。

\n
\n\n

NSArray 的子类化

\n\n

要子类化 NSArray,我们必须重写countobjectAtIndex : 方法

\n\n
\n

NSArray 的任何子类都必须重写原始实例方法\n count 和 objectAtIndex:。这些方法必须在您为集合元素提供的后备存储上运行。

\n\n
\n\n

从概念上讲,数组存储许多数据项,每个数据项都可以通过索引访问。NSArray 通过其两个原始方法 count 和 objectAtIndex: 表达了这个抽象概念。以这些方法为基础,可以实现其他方法\xe2\x80\x94派生方法\xe2\x80\x94;

\n
\n\n

静态数组示例

\n\n
class Months: NSArray {\n\n    let months =  [ "January", "February", "March", "April",\n                    "May", "June", "July", "August", "September",\n                    "October", "November", "December" ]\n\n    override var count: Int {\n        get {\n          return months.count\n        }\n    }\n\n    override func objectAtIndex(index: Int) -> AnyObject {\n        assert(index < count, "The index is out of bounds")\n        return months[index]\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

初始化

\n\n
let months = Months()\n\nprintln("My birthday month : \\(months.objectAtIndex(6))")\nprintln("The last month of the year : \\(months.lastObject)")\n
Run Code Online (Sandbox Code Playgroud)\n\n

包含对象的数组

\n\n
class MyArray: NSArray {\n\n    var array: [AnyObject] = []\n\n    func populateWith(#objects: [AnyObject]) {\n        self.array = objects\n    }\n\n    override var count: Int {\n        get {\n          return array.count\n        }\n    }\n\n    override func objectAtIndex(index: Int) -> AnyObject {\n\n        assert(index < count, "The index is out of bounds")\n        return array[index]\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

初始化

\n\n
let fruits = MyArray()\nfruits.populateWith(objects: ["Apple", "Banana", "Orange", "Pear", "Cherry"])\n\nprintln("Fruits count : \\(fruits.count)")\n
Run Code Online (Sandbox Code Playgroud)\n\n

NSMutableArray 子类化

\n\n

这与 NSArray 是一样的,但我们必须重写这些方法:

\n\n
    \n
  • 数数
  • \n
  • 对象索引:
  • \n
  • 插入对象:atIndex:
  • \n
  • 删除索引处的对象:
  • \n
  • 添加对象:
  • \n
  • 删除最后一个对象
  • \n
  • 替换ObjectAtIndex:withObject:
  • \n
\n\n

如果需要,我可以添加示例

\n\n

结论

\n\n

我们可以在 swift 中子类化 NSArray (仅当使用默认初始化器init()时),但我们(还)不能使用其他初始化器(例如 initWithObjects:count:)。

\n\n

所以,我同意你的观点,目前最好的解决方案是在 Objective-C 中子类化类簇

\n\n

类簇文档

\n\n

NSArray 文档

\n\n

希望有帮助

\n