【问题标题】:Passing Data Between Two NSOperations在两个 NSOperations 之间传递数据
【发布时间】:2015-10-19 15:21:00
【问题描述】:

我非常专注地观看了关于 Advanced NSOperations 的 WWDC 2015 会议,并玩了一点 example code

提供的抽象真的很棒,但有些东西我可能不太理解。

我想在不使用 MOC 的情况下在两个后续操作子类之间传递结果数据。

假设我有一个APIQueryOperation,它有一个NSData? 属性和第二个操作ParseJSONOperation 使用这个属性。如何将此NSData? 实例提供给第二次操作?

我试过这样的:

queryOperation = APIQueryOperation(request: registerAPICall)  
parseOperation = ParseJSONOperation(data: queryOperation.responseData)  
parseOperation.addDependency(queryOperation) 

但是当我进入ParseJSONOperationexecute方法时,实例中的实例与初始化器中的不一样。

我做错了什么?

【问题讨论】:

  • responseData 在构造 ParseJSONOp 时可能为 nil。您可能希望通过 queryOp 或将保存响应的对象,以便您可以在 parseOp 启动时查询 responseHolder.responseData
  • 肯定是零。 Optionals 不是引用类型吗?
  • 请记住,您的数据对象是 Nil,这意味着在填充时没有可以使用和保留的指针...
  • 好的。所以我应该考虑 Optional 只有当它们不是 nil 时才作为参考类型?
  • 可选性的概念与引用类型无关。引用类型只是一个通过引用而不是值传递的对象。在这种情况下,你没有传递一个对象,你传递的是 nil :)

标签: swift nsoperation


【解决方案1】:

您的问题是您正在使用 nil 值构建 ParseJSONOperation。由于您有两个操作依赖于此 NSData 对象,因此我建议您编写一个包装器对象来容纳此数据。

为了尝试与 WWDC 谈话保持一致,让我们将此对象称为 APIResultContext:

class APIResultContext {
    var data: NSData?
}

现在我们可以将这个对象传递给APIQueryOperationParseJSONOperation,这样我们就有了一个有效的对象来存储从API 传输的数据。

这将使查询的构造函数:

let context = APIResultContext()
APIQueryOperation(request: registerAPICall, context: context)
ParseJSONOperation(context: context)  

在您的ParseJSONOperation 中,假设查询在设置数据后完成,您应该能够访问数据。

线程安全

正如@CouchDeveloper 指出的那样,data 严格来说并不是线程安全的。对于这个简单的例子,因为这两个操作是相互依赖的,我们可以安全地读写,因为知道这些访问不会同时发生。然而,为了完善解决方案并使上下文线程安全,我们可以添加一个简单的NSLock

class APIResultContext {
    var data: NSData? {
        set {
            lock.lock()
            _data = newValue
            lock.unlock()
        }
        get {
            lock.lock()
            var result =  _data
            lock.unlock()
            return result
        }
    }

    private var _data: NSData?
    private let lock = NSLock()
}

【讨论】:

  • 在访问APIResultContext 类中的data 值时需要同步原语。否则,您的方法不是“线程安全的”。此外,您仍然需要设置依赖项。
  • 从技术上讲,它是线程安全的,因为操作依赖于另一个操作,因此 ParseOperation 在写入之前不会访问它。但有效点@CouchDeveloper
  • 我不同意:对成员值data 的访问可以从不同的执行上下文 执行(Apple 有时使用术语Execution Environment)。这些在调用站点是未知的,并且是NSOperation 的两个子类中的实现细节。也就是说,实际上,这些可能是不同的线程、不同的调度队列或其他任何东西。在 Swift 中,没有隐式同步。此外,方法和函数会被内联和优化,从而使访问在并发方面不安全。
  • 不管执行上下文如何,操作 2 不可能在操作 1 完成并写入 data 之前开始。发生这种情况的唯一方法是操作 1 异步写入数据并立即完成执行。 @CouchDeveloper
  • @CouchDeveloper 本着学术正确的精神更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多