【问题标题】:Make instance wait until called functions are complete - Swift让实例等到调用的函数完成 - Swift
【发布时间】:2015-07-08 02:34:27
【问题描述】:

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

我正在尝试创建一个“优惠券”实例,该实例在将 ID 传递给 init 方法中的数据库后,其属性从 SQL 数据库中加载。

我的问题是,当我从不同的 viewController 类调用 init 方法时,它将返回具有默认字符串值“”的实例,因为来自 NSURLConnection 的数据在返回到 viewContoller 之前尚未/解码。

我正在寻找一种解决方案,以解决如何让 init 方法等到字段加载完成。

优惠券类相关属性:

var webData: NSMutableData?

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

优惠券类相关方法:

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

    }

【问题讨论】:

    标签: ios swift init


    【解决方案1】:

    不可能“等待您的 SQL 完成”然后从 init 返回而不阻塞您的线程(同步),这不是您想要的。

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

    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 时出现错误,这在您当前的代码中不存在。

    【讨论】:

    • 非常感谢!我还在纠结这是如何工作的,我只是好奇为什么在 connectionDidFinishingLoading 函数结束时我们将处理程序设置为 nil
    • sorry to double post - 当我们设置处理程序时?(coupon: self) 是当我们从 Coupon.createCoupon:: 传入的实际闭包被调用时
    • 这里在class func createCoupon 方法中,我们创建了一个空的优惠券对象并设置处理程序属性来存储优惠券从您的服务器“完全初始化”属性后应该调用的内容。在connectionDidFinishLoading 中,我们调用了存储的处理程序来通知调用者事情已经完成。之后,不再需要处理程序,因此我们将其设置为nil 以防止持有不必要的东西。这取决于您在调用createCoupon时在completionHandler中写的内容,它可能是一个保留循环,以防止优惠券正常释放。
    猜你喜欢
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    相关资源
    最近更新 更多