我正在制作一个UITableView,它显示从处理后的数据创建的图像。
此处理任务太重,我决定声明一个UITableView类的数组类型实例变量,并为每个处理任务创建一个操作。
因为每个结果都将存储到由索引标识的单独的内存空间中,所以我认为它是线程安全的。
简短版本示例:
class TestOperation: Operation {
var pi: [Int?];
override var isExecuting: Bool { ... }
override var isFinished: Bool { ... }
init(_ p: inout [Int?]) {
pi = p;
}
override func start() {
if pi[0] == nil {
pi[0] = 0;
} else if pi[1] == nil {
pi[1] = 1;
} else {
pi[2] = 2;
}
}
}
class Root {
var sharedArr: [Int?];
var queue: OperationQueue;
init() {
sharedArr = Array(repeating: nil, count: 3);
queue = OperationQueue.init();
for _ in 0...2 {
let operation = TestOperation.init(&sharedArr);
queue.addOperation(operation);
}
}
}
Root.init();
我期望sharedArr
会改变,但是我得到的只是nil数组。我有什么可以尝试的吗?
答案 0 :(得分:1)
swift中的数组是结构,因此按值传递。我看到您将数组作为inout传递,所以您已经知道这一点。我遇到过几次这个问题,最后我作弊。
作弊1:将对Root的引用传递到TestOperation,然后在Root上调用将值添加到共享数组的方法。您可以使用协议使此清洁器更干净。
作弊2:创建一个包装共享数组并具有更新包装后的数组的方法的类。
在两种情况下,我都会将要使用的索引传递给TestOperation,而不是从数组内容中推断出来。推断可能与时间有关。
我知道这是在避免而不是解决问题,但是有时候寿命太短了。
这里是要旨,未经测试:
protocol TestOperationProtocol: class {
function setValue(index: Int, value: Int)
}
class TestOperation: Operation {
weak var owner: TestOperationProtocol
let index: Int
override var isExecuting: Bool { ... }
override var isFinished: Bool { ... }
init(owner: TestOperationProtocol, index: Int) {
self.owner = owner
self.index = index
}
override func start() {
// calculate value
let value = self.index
self.owner?.setValue(self.index, value)
}
}
class Root: TestOperationProtocol {
var sharedArr: [Int?];
var queue: OperationQueue;
init() {
sharedArr = Array(repeating: nil, count: 3);
queue = OperationQueue.init();
for i in 0...sharedArr.count {
let operation = TestOperation.init(self, index: index);
queue.addOperation(operation);
}
}
func setValue(index: Int, value: Int) {
sharedArray[index] = value
}
}
该协议使您可以打破依赖关系周期。 TestOperation取决于TestOperationProtocol,而不取决于Root。根取决于TestOperation及其协议。