Arrays Swift:子类NSMutableArray

Arrays Swift:子类NSMutableArray,arrays,swift,nsmutablearray,Arrays,Swift,Nsmutablearray,我试图在Swift中对NSMutableArray进行子类化,以便为Swift数组提供桥接功能,将其连接到一些旧的Objective-C代码库。然而,我找不到一个函数示例,到目前为止,我所有的尝试都失败了。这是我得到的最接近函数示例: import UIKit class MyArray: NSMutableArray { var array: [Int]? // Adding an initializer triggers the error: 'required' initia

我试图在Swift中对NSMutableArray进行子类化,以便为Swift数组提供桥接功能,将其连接到一些旧的Objective-C代码库。然而,我找不到一个函数示例,到目前为止,我所有的尝试都失败了。这是我得到的最接近函数示例:

import UIKit

class MyArray: NSMutableArray {

    var array: [Int]?

// Adding an initializer triggers the error: 'required' initializer 'init(arrayLiteral:)' must be provided by subclass of 'NSArray'
//    override init() {
//        self.array = []
//        super.init()
//    }

    static func makeArray() -> MyArray {
        let array = MyArray()
        array.array = []
        return array
    }

    override var count: Int {
        get {
            if let count = array?.count {
                return count
            }

            return 0
        }
    }

    override func insert(_ anObject: Any, at index: Int) {
        print("insert called")
    }

    override func removeObject(at index: Int) {
        print("removeObject called")
    }

    override func add(_ anObject: Any) {
        print("Trying to add \(anObject)")
        if let newInt = anObject as? Int {
            array?.append(newInt)
        }
    }

    override func removeLastObject() {
        print("removeLastObject called")
    }

    override func replaceObject(at index: Int, with anObject: Any) {
        print("replaceObject called")
    }
}

func append42(array: NSMutableArray) {
    array.add(42)
}

let myArray = MyArray.makeArray()

print("Before: \(myArray.array)")
myArray.array?.append(42)
// The following two lines generate a SIGABRT
//myArray.add(42)
//append42(array: myArray)
print("After: \(myArray.array)")
但是,使用
add
方法始终会触发
SIGABRT
。我在Catalina上使用XCode 12.4

编辑(澄清):我知道Swift将
Array
s连接到
NSArray
s。但是,我需要将对Swift数组的引用传递给一些接受
NSMutableArray
并可能对数组进行更新的Objective-C代码

本质上,我将向现有项目添加一些Swift代码,我希望在新代码中使用Swift类型的数组,但我仍然需要将这些数组传递给旧代码。我知道我可以制作Swift数组的
NSMutableArray
副本,将此副本传递给旧代码,然后将其复制回Swift数组,但它非常复杂且难以维护。我试图做的是将对Swift数组的引用封装到“NSMutableArray”子类中,这样我就可以在遗留代码中透明地使用该子类。

您是否:

导入基础框架时,SWIFT覆盖提供了许多桥接引用类型的值类型。许多其他类型被重命名或嵌套以澄清关系

具体而言:

包含不可变和可变子类(如NSArray和NSMutableArray)的类集群桥接到单个值类型

因此,您可以使用
Array
代替
NSArray
,如果您想要
NSMutableArray
也是一个Swift
Array
(但是
var
)。 同样的情况也适用于
字典
NSDictionary

免责声明 我可能不会在生产代码中使用它,尽管子类
NSArray
NSMutableArray
是不被禁止的,文档中说:

通常很少有理由将NSMutableArray子类化

<> P>这应该是考虑另一个解决方案IMHO/P>的理由。 编辑 看完这个

我决定检查
NSMutableArray

重写的方法

NSMutableArray定义了五种基本方法:

插入(地址:)

removeObject(位于:)

加上

RemovelAsObject()

replaceObject(位于:with:)

在子类中,必须重写所有这些方法。还必须重写NSArray类的基元方法

所以我也检查了
NSArray

NSArray的任何子类都必须重写原语实例方法count和object(at:)。这些方法必须在为集合元素提供的备份存储上操作。对于此备份存储,您可以使用静态数组、标准NSArray对象或某些其他数据类型或机制。您还可以选择部分或完全覆盖要为其提供替代实现的任何其他NSArray方法

现在

@objc class MyArray: NSMutableArray {

    var array: [Int] = []
    static func makeArray() -> MyArray {
        let array = MyArray()
        array.array = []
        return array
    }

    override var count: Int {
        array.count
    }
    
    override func object(at index: Int) -> Any {
        array[index]
    }

    override func insert(_ anObject: Any, at index: Int) {
        print("insert called")
        if let newInt = anObject as? Int {
            array.insert(newInt, at: index)
        }
    }

    override func removeObject(at index: Int) {
        array.remove(at: index)
        print("removeObject called")
    }

    override func add(_ anObject: Any) {
        print("Trying to add \(anObject)")
        if let newInt = anObject as? Int {
            array.append(newInt)
        }
    }
}

func append42(array: NSMutableArray) {
    array.add(42)
}
我有:

let myArray = MyArray.makeArray()

print("Before: \(myArray.array)")
myArray.array.append(42) // [42]
// The following two lines generate a SIGABRT
myArray.add(42) // [42, 42]
append42(array: myArray)
print("After: \(myArray.array)")

// Before: []
// Trying to add 42
// Trying to add 42
// After: [42, 42, 42]

有趣的事实
  • 我在操场上试过你的密码,然后复制了那次撞车。我在
    XCTestCase
    中进行了尝试,但没有崩溃
  • add(:)
    中调用
    super.add(:)
    将触发
    insert(:)
  • NSMutableArray
    ExpressibleByArrayLiteral
    的一致性可能是在一个扩展中编写的(这非常有意义,因为
    NSMutableArray
    是一个Objective-C类),因此重写
    init()
    您可以重写
    init(ArrayLiteral:)
    并且编译器说不支持在扩展中重写声明:
自动初始值设定项继承

规则1

如果您的子类没有定义任何指定的初始值设定项,它将自动继承其所有超类指定的初始值设定项

规则2

如果您的子类通过按照规则1继承其所有超类指定的初始值设定项,或者通过提供自定义实现作为其定义的一部分,来提供其所有超类指定初始值设定项的实现,那么它将自动继承所有超类便利初始值设定项

你是说:

导入基础框架时,SWIFT覆盖提供了许多桥接引用类型的值类型。许多其他类型被重命名或嵌套以澄清关系

具体而言:

包含不可变和可变子类(如NSArray和NSMutableArray)的类集群桥接到单个值类型

因此,您可以使用
Array
代替
NSArray
,如果您想要
NSMutableArray
也是一个Swift
Array
(但是
var
)。 同样的情况也适用于
字典
NSDictionary

免责声明 我可能不会在生产代码中使用它,尽管子类
NSArray
NSMutableArray
是不被禁止的,文档中说:

通常很少有理由将NSMutableArray子类化

<> P>这应该是考虑另一个解决方案IMHO/P>的理由。 编辑 看完这个

我决定检查
NSMutableArray

重写的方法

NSMutableArray定义了五种基本方法:

插入(地址:)

removeObject(位于:)

加上

RemovelAsObject()

replaceObject(位于:with:)

在子类中,必须重写所有这些方法。还必须重写NSArray类的基元方法

所以我也检查了
NSArray

NSArray的任何子类都必须重写原语实例方法count和object(at:)。这些方法必须在为集合元素提供的备份存储上操作。对于此备份存储,可以使用静态数组、标准NSArray对象等