2016-03-12 33 views
0

讓我通過說我是Swift 2的新手,並構建我的第一個調用api(php)數據(JSON)的應用程序。我遇到的問題是,當我調用api時,其他函數在api可以發回數據之前運行。Swift 2 api調用需要比其他函數運行更長的時間

我研究了一些onComplete類型,以便在api響應完成後調用一個函數。我相信你們中的大多數人很容易,但我似乎無法想象它是我們的。

在此先感謝!

class ViewController: UIViewController { 

    var Selects = [Selectors]() 

    var list = [AnyObject]() 

    var options = [String]() 

    var index = 0 

    @IBOutlet var Buttons: [UIButton]! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.API() 
     self.Render() 
    } 

    func API() { 
     let url = NSURL(string: "http:api.php") 
     let request = NSMutableURLRequest(URL: url!) 

     let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 
      data, response, error in 
      if data == nil { 
       print("request failed \(error)") 
       return 
      } 
      do { 
       let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) 

       if let songs = json["songs"] as? [[String: AnyObject]] { 
        for song in songs { 
         self.list.append(song) 
        } 
       } 
       self.Selects = [Selectors(Name: self.list[self.index]["name"] as? String, Options: self.BuildOptions(), Correct: 2)] 
      } 
      catch let error as NSError { 
       print("json error: \(error.localizedDescription)") 
      } 
     } 
     task.resume() 
    } 

    func BuildOptions() { 
     // BuildOptions stuff happens here 
    } 

    func Render() { 
     // I do stuff here with the data 
    } 
} 

回答

1

因此,我假設你的Render()方法在數據從api回來之前被調用?在視圖控制器中保存你的API調用代碼是不好的設計,但是因爲你是新的,我不會在這方面進行擴展。在你的情況下,就像在viewDidLoad()中調用Render()方法一樣簡單 - 在完成從JSON解析數據(在self.Selects = [Selectors...行之後)之後調用它。 NSURLSession.sharedSession().dataTaskWithRequest(request)方法異步調用,並且在獲取數據完成此方法後執行帶data, response, error參數的回調塊,因此可能在viewDidLoad長時間完成並且由於異步方法仍在等待而原本沒有數據需要處理用於API的響應。

編輯 - 說到處理api調用,明智的做法是讓它們與特定的視圖控制器分離以保持清晰的可重用代碼庫。你應該調用API,並等待它回調,所以我只是做你的API函數,它應該是這樣的:

static func callAPI(callback: [AnyObject]? -> Void) { 
    let url = NSURL(string: "http:api.php") 
    let request = NSMutableURLRequest(URL: url!) 

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { 
     data, response, error in 
     if data == nil { 
      completion(nil) 
     } 
     do { 
      var list = [AnyObject]() 
      let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments) 

      if let songs = json["songs"] as? [[String: AnyObject]] { 
       for song in songs { 
        self.list.append(song) 
       } 
      } 
      completion(list) 
     } 
     catch let error as NSError { 
      print("json error: \(error.localizedDescription)") 
      completion(nil) 
     } 
    } 
    task.resume() 
} 

一般來說方法應該做一個具體的東西 - 你的情況調用api並返回數據或錯誤。在回調中初始化視圖控制器中的選擇器。您的視圖控制器的viewDidLoad看起來像這樣使用上面的代碼:

override func viewDidLoad() { 
    super.viewDidLoad() 
    YourApiCallingClass.callApi() { 
     result in 
     if let list = result { 
      self.list = list 
      self.Selects = [Selectors(Name: self.list[self.index]["name"] as? String, Options: self.BuildOptions(), Correct: 2)] 
      self.Render() 
     } else { 
      //Handle situation where no data will be returned, you can add second parameter to the closue in callApi method that will hold your custom errors just as the dataTaskWithRequest does :D 
     } 

    } 
} 

現在你有關注一個很好的分離,API的方法是可重複使用和瀏覽器只是處理時,得到的數據會發生什麼。如果你在等待屏幕中間放一個UIActivityIndi​​cator會很好,那麼它會看起來很整齊,專業:P

+0

我正在構建一個包含十個問題的測驗樣式應用程序。在每個被回答的問題之後,調用Render()方法來填充下一個問題和選項。我有興趣瞭解API調用應該去哪裏,我正在學習,這聽起來像我需要更多地瞭解它。感謝您的反饋 – Mike

+0

因此,基本上,當視圖加載時,您從測驗的API中獲取一些數據?我將編輯答案 – FruitAddict

+0

正確,我抓住一個帶有十個元素的JSON對象,並將其推入列表數組中。 – Mike

相關問題