簡體   English   中英

如何在iOS中使用異步方法(JSON Restful服務)?

[英]How to use asynchronous methods (JSON Restful services) in iOS?

我有一個iOS應用程序,可以sync來自JSON restful web service 從外部類(不是UI controller )調用此方法。 這個類有一個sync方法,它可以毫無問題地發送和檢索數據。 我的問題是如何在獲得結果之前暫停UI。

以下將提供有關代碼的想法。

UIController類

let C : Customer = Customer(UserName: UserName!, Password: Password!)
let S : Syncronization = Syncronization()
S.Sync(C)

同步類

Class Syncronization : NSObject, NSURLSessionDataDelegate

func Sync(C : Customer){
        var datastr = ""
        datastr = "http://192.168.248.134:8008/MobileWeb.svc/GetFirstTimeSync/" + C.UserName + "/" + C.Password
        let url:NSURL = NSURL(string: datastr)!
        self.buffer = NSMutableData()
        let defaultConfigObject:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session:NSURLSession = NSURLSession(configuration: defaultConfigObject, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
        let req:NSMutableURLRequest = NSMutableURLRequest(URL: url)
        req.HTTPMethod = "POST"
        session.dataTaskWithURL(url).resume()
    }

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        print("Recieved with data")
        buffer.appendData(data)
    }

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
            if error == nil {
                print("Download Successful")
                print("Done with Bytes " + String(buffer.length))
                self.parseJSONA(self.buffer)
            }
            else  {
                print("Error %@",error!.userInfo);
                print("Error description %@", error!.localizedDescription);
                print("Error domain %@", error!.domain);
            }
    }

    func parseJSONA(data:NSMutableData) {
         do {
                let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! Array<AnyObject>
        } catch let error as NSError {
                print("Failed to load: \(error.localizedDescription)")
        }
   }

我已經嘗試過dispacther方法,但我相信我到目前為止還不知道如何使用它,因為大多數示例都關閉了UI控制器上的服務和數據交換。

任何形式的幫助表示贊賞。 謝謝

您可以為Sync類提供完成處理程序閉包。

在你的UIViewController

S.completion = {
 information in
 UIElement.updateWith(information)
}

當然,您需要在Syncronization類中添加一個成員:

var completion:((information:String)->())!

你可以從Syncronization類的parseJSON()URLSession()內部調用completion("here's some info!")

這里有關於Swift閉包的一些解讀

這可能會幫助你https://thatthinginswift.com/background-threads/

let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {

    // do downloading or sync task here

    dispatch_async(dispatch_get_main_queue()) {

        // update some UI with downloaded data/sync data

    }
}

如果我理解正確,您希望能夠根據您對S.Sync(C)調用結果在您的UI中執行某些操作

一種方法是將閉包作為Sync函數的參數。

這是我將如何做到的(免責聲明......我沒有檢查編譯器中的所有內容,因此可能會出現錯誤。看看你得到了多少,如果有問題,只需再寫一次:-)):

enum SynchronizationResult {
    case Success(Array<AnyObject>)
    case Failure(NSError)
}

class Syncronization : NSObject, NSURLSessionDataDelegate {

    var functionToExecuteWhenDone: ((SynchronizationResult) -> Void)?

    func Sync(C : Customer, callback: (SynchronizationResult) -> Void){
        functionToExecuteWhenDone = callback
        var datastr = ""
        datastr = "http://192.168.248.134:8008/MobileWeb.svc/GetFirstTimeSync/" + C.UserName + "/" + C.Password
        let url:NSURL = NSURL(string: datastr)!
        self.buffer = NSMutableData()
        let defaultConfigObject:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session:NSURLSession = NSURLSession(configuration: defaultConfigObject, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
        let req:NSMutableURLRequest = NSMutableURLRequest(URL: url)
        req.HTTPMethod = "POST"

        session.dataTaskWithURL(url).resume()
     }

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        print("Recieved with data")
        buffer.appendData(data)
    }

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        if error == nil {
            print("Download Successful")
            print("Done with Bytes " + String(buffer.length))
            self.parseJSONA(self.buffer)
        } else  {
            print("Error %@",error!.userInfo);
            print("Error description %@", error!.localizedDescription);
            print("Error domain %@", error!.domain);
            let result = SynchronizationResult.Failure(error!)
            if let functionToExecuteWhenDone = functionToExecuteWhenDone {
                functionToExecuteWhenDone(result)
            }
        }
    }

    func parseJSONA(data:NSMutableData) {
        do {
            let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! Array<AnyObject>
            let result = SynchronizationResult.Success(json)
            if let functionToExecuteWhenDone = functionToExecuteWhenDone {
                functionToExecuteWhenDone(result)
            }
         } catch let error as NSError {
             print("Failed to load: \(error.localizedDescription)")
             let result = SynchronizationResult.Failure(error)
             if let functionToExecuteWhenDone = functionToExecuteWhenDone {
                 functionToExecuteWhenDone(result)
             }
         }
     }
}

所以...我們引入了一個名為SynchronizationResult的Enum來處理獲取數據的結果。

然后我們添加一個要在完成時調用的函數,作為Sync函數的參數:

func Sync(C : Customer, callback: (SynchronizationResult) -> Void)

將使用SynchronizationResult作為參數調用此方法,並返回void。

我們將該回調存儲在functionToExecuteWhenDone供以后使用。

根據您是否看到任何錯誤或一切都是陽光,我們在此過程中生成不同的SynchronizationResult值,並在我們准備好時(當解析完成或我們失敗時)使用當前的SynchronizationResult調用functionToExecuteWhenDone

在你的ViewController中,你可以做一些事情

let C : Customer = Customer(UserName: UserName!, Password: Password!)
let S : Syncronization = Syncronization()
S.Sync(C) { (result) in
    switch result {
        case .Success(let json):
            //Your code to update UI based on json goes here
        case .Failure(let error):
            //Your code to handle error goes here
    }
}

我希望這是有道理的,也是你需要的。

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    print("This is run on the background queue")

   dispatch_async(dispatch_get_main_queue(), { () -> Void in
        print("This is run on the main queue, after the previous code in outer block")
    })
})

在這里找到

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM