如何创建在多个操作之间共享的实例变量

时间:2018-09-04 11:40:28

标签: swift swift4 swift4.1

我正在制作一个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数组。我有什么可以尝试的吗?

1 个答案:

答案 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及其协议。