让实例等待调用的函数完成 - Swift

Make instance wait until called functions are complete - Swift

如果这个问题已经得到解答,我提前道歉,但正如您可能从标题中看出的那样,我不太确定如何描述这个问题,而且我发现对类似问题的回答也没有帮助。

我试图创建一个 "Coupon" 的实例,在将 id 传递给 init 方法中的数据库后,它的属性从 SQL 数据库加载。

我的问题是,当我从另一个 viewController class 调用 init 方法时,它将 return 具有默认字符串值 "" 的实例作为来自 NSURLConnection 的数据在 return 进入 viewContoller 之前 been/decoded。

我正在寻找一种解决方案,以解决如何使 init 方法等待字段加载完毕的问题。

优惠券class相关属性:

var webData: NSMutableData?

var id: Int
var name: String = ""
var provider: String = ""
var details: String = ""

优惠券class相关方法:

convenience init(id: Int) {

    self.init()
    self.id = id

    self.selectSQL(id) //passes id to server and returns all other varibles

}

   func selectSQL(id: Int) {

    let url = NSURL(string: "http://wwww.website.php?id=\(id)") // acess php page
    let urlRequest = NSURLRequest(URL: url!)
    let connection = NSURLConnection(request: urlRequest, delegate: self)

}

func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {

    webData = NSMutableData()

}

func connection(connection: NSURLConnection, didReceiveData data: NSData) {

    webData?.appendData(data)

}

func connectionDidFinishLoading(connection: NSURLConnection) {

    let result = NSJSONSerialization.JSONObjectWithData(webData!, options: .AllowFragments, error: nil) as? NSArray

    let resultDict = result?[0] as? NSDictionary

    if let dict = resultDict {

        name = dict.objectForKey("name") as! String
        provider = dict.objectForKey("provider") as! String
        details = dict.objectForKey("details") as! String

    }

不可能从 init "wait for your SQL finishing" 然后 return 不阻塞你的线程(同步),这不是你想要的。

我建议使用带有回调的工厂方法来解决它。像这样:

class Coupon {
    private var handler: ((coupon: Coupon) -> ())?

    class func createCoupon(id: Int, completionHandler: ((coupon: Coupon) -> ())?) {
        let coupon = Coupon(id: id)

        // Store the handler in coupon
        coupon.handler = completionHandler
    }

    //...

    func connectionDidFinishLoading(connection: NSURLConnection) {

        //...Setup coupon properties
        handler?(coupon: self)
        handler = nil
    }
}

然后您可以像这样创建和使用您的优惠券:

Coupon.createCoupon(1, completionHandler: { (coupon) -> () in
    // Do your thing with fully "inited" coupon
})

当然,你还要考虑到你的服务器连接失败的情况,可能调用handler会报错,而你现在的代码不会出现这种情况。