在lazy var属性中调用异步函数

时间:2016-04-02 22:51:47

标签: ios swift

有没有办法从惰性或计算属性调用异步函数?

struct Item {
  lazy var name: String = {
    API.requestThing({ (string: String) in // Xcode didn't like this
      return string // this would not work here
    })
  }()
}

class API {
  class func requestThing(completion: String -> Void) {
    completion("string")
  }
}

4 个答案:

答案 0 :(得分:1)

API.requestThing中的完成处理程序返回一个String,但它应该没有返回值:

(completion: String -> Void)

我让这个工作:

struct Item {
    lazy var name: String = {
        API.requestThing({ (string: String) in 
            return string
        })
    }()
}

class API {
    class func requestThing(completion: String -> String) -> String {
        return completion("string")
    }
}

答案 1 :(得分:0)

首先,requestThing返回()(即无效),而不是String。因此,以下表达式的类型也是()而不是String

API.requestThing { string in
  return string
}

其次,对requestThing的调用是异步的,所以即使你将name定义为一个惰性var,对var body函数的调用仍然是synchronous并将立即返回。

因此,如果您可以将name转换为如下函数:

func name(completion: String -> ()) {
    API.requestThing { string in
        completion(string)
    }
}

// Later you call it in this way
myItem.name { name in
    // use the value of name
}

如果您想要缓存检索到的值,可以将Item修改为class并使用以下代码

class Item {
    private var nameValue: String?
    func name(completion: String -> ()) {
        if let value = nameValue {
            // return cached value
            return completion(value)
        } else {
            // request value
            API.requestThing { string in
                // cache retrieved value
                self.nameValue = string
                // return retrieved value
                completion(string)
            }
        }
    }
}

答案 2 :(得分:0)

没有充分的理由使用" lazy"在这种情况下。懒惰是用于初始化。只需创建一个普通的func并传递一个完成处理程序。

答案 3 :(得分:0)

可能没有令人信服的理由这样做,但以下方法似乎是合理的:

而是拥有String类型的变量 - 我们有时需要一个&#34; Future&#34;那个东西,例如Future<String>。未来代表异步操作的最终结果 - 这正是您问题中给出的内容。

未来本身就是一个正常的&#34;变量也可以延迟评估。它还没有最终的价值。这意味着,只有在明确请求时才会启动基础任务(例如 lazily )。从设计或架构的角度来看,这可能是有道理的。

func fetchString() -> Future<String> { ... }

lazy var name: Future<String> = fetchString()

稍后在您的代码中,您将获得如下变量:

item.name.map { string in
    print(string)
}

如果这是第一次访问惰性属性,它将启动计算字符串的底层异步操作。然后,当变量可用时,map函数中提供的映射函数将以变量作为参数调用 - 可能也会在一段时间之后调用。

否则(如果这不是第一次访问),它只会在参数可用时提供参数中的字符串。

由于操作可能会失败,因此未来&#34;还提供了处理此问题的方法:

item.name.map { string in
    print(string)
}.onFailure { error in
    print("Error: \(error)")
}

另请参阅:https://en.wikipedia.org/wiki/Futures_and_promises

在Swift和Objective-C中有Futures的实现,通常也被称为&#34; Promise&#34;。