2015-10-16 101 views
1

我正在使用NSURLSession。我有一個餐廳陣列,我正在向api中的每個餐廳請求菜餚。 dataTask的工作原理,我只是在所有dataTasks完成時才試圖調用一個方法。NSURLSession,完成塊,Swift

self.findAllDishesOfRestaurants(self.restaurantsNearMe) { (result) -> Void in 
     if result.count != 0 { 
       self.updateDataSourceAndReloadTableView(result, term: "protein") 
     } else { 
      print("not ready yet") 
     } 
    } 

的self.updateDataSourceAndREloadTableView不會被調用,不管我完成塊。這裏是我的findAllDishesOfRestaurants功能

func findAllDishesOfRestaurants(restaurants:NSArray, completion:(result: NSArray) -> Void) { 
    let allDishesArray:NSMutableArray = NSMutableArray() 
    for restaurant in restaurants as! [Resturant] { 
     let currentRestaurant:Resturant? = restaurant 
     if currentRestaurant == nil { 
      print("restaurant is nil") 
     } else { 
      self.getDishesByRestaurantName(restaurant, completion: { (result) -> Void in 
              if let dishesArray:NSArray = result { 
               restaurant.dishes = dishesArray 
               print(restaurant.dishes?.count) 
               allDishesArray.addObjectsFromArray(dishesArray as [AnyObject]) 
               self.allDishes.addObjectsFromArray(dishesArray as [AnyObject]) 
               print(self.allDishes.count) 
              } 
              else { 
               print("not dishes found") 
             } 
              // completion(result:allDishesArray) 
            }) 
      completion(result:allDishesArray) 
     } 
    } 
} 

這裏是我在哪裏執行dataTasks功能。

func getDishesByRestaurantName(restaurant:Resturant, completion:(result:NSArray) ->Void) { 

    var restaurantNameFormatted = String() 
    if let name = restaurant.name { 
    for charachter in name.characters { 
     var newString = String() 
     var sameCharacter:Character! 
     if charachter == " " { 
      newString = "%20" 
      restaurantNameFormatted = restaurantNameFormatted + newString 
     } else { 
      sameCharacter = charachter 
      restaurantNameFormatted.append(sameCharacter) 
     } 
     // print(restaurantNameFormatted) 
    } 
} 
    var urlString:String! 
     //not to myself, when using string with format, we need to igone all the % marks arent ours to replace with a string, otherwise they will be expecting to be replaced by a value 
     urlString = String(format:"https://api.nutritionix.com/v1_1/search/%@?results=0%%3A20&cal_min=0&cal_max=50000&fields=*&appId=XXXXXXXXXappKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXX",restaurantNameFormatted) 
    let URL = NSURL(string:urlString) 
    let restaurantDishesArray = NSMutableArray() 
    let session = NSURLSession.sharedSession() 
       let dataTask = session.dataTaskWithURL(URL!) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in 
       do { 
       let anyObjectFromResponse:AnyObject = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) 
        if let asNSDictionary = anyObjectFromResponse as? NSDictionary { 
         let hitsArray = asNSDictionary.valueForKey("hits") as? [AnyObject] 
               for newDictionary in hitsArray! as! [NSDictionary]{ 
                let fieldsDictionary = newDictionary.valueForKey("fields") as? NSDictionary 
                let newDish = Dish.init(dictionary:fieldsDictionary!, restaurant: restaurant) 
                restaurantDishesArray.addObject(newDish) 
         } 
        } 
        completion(result:restaurantDishesArray) 
       } catch let error as NSError { 
        print("failed to connec to api") 
        print(error.localizedDescription) 
       } 
      } 
      dataTask.resume() 
} 

就像我之前說的,我需要等到有趣的findAllDishesOfRestaurants完成。我試圖寫我的完成塊,但我不知道我做得對。任何幫助是極大的讚賞。感謝

回答

4

問題是你在al任務完成之前調用findAllDishesOfRestaurants中的completion方法。實際上,你爲列表中的每個餐廳都調用一次,這可能不是你想要的。

我的建議是你尋找到NSOperationQueue的原因有兩個:

  1. 它可以讓你限制併發請求到服務器的數量,所以你的服務器不會與請求淹沒。
  2. 它可以讓您輕鬆控制所有操作何時完成。

但是,如果你正在尋找一個快速解決,你需要的是使用GCD組dispatch_group_createdispatch_group_enterdispatch_group_leavedispatch_group_notify如下。

func findAllDishesOfRestaurants(restaurants:NSArray, completion:(result: NSArray) -> Void) { 
    let group = dispatch_group_create() // Create GCD group 

    let allDishesArray:NSMutableArray = NSMutableArray() 
    for restaurant in restaurants as! [Resturant] { 
     let currentRestaurant:Resturant? = restaurant 
     if currentRestaurant == nil { 
      print("restaurant is nil") 
     } else { 
      dispatch_group_enter(group) // Enter group for this restaurant 
      self.getDishesByRestaurantName(restaurant, completion: { (result) -> Void in 
       if let dishesArray:NSArray = result { 
        restaurant.dishes = dishesArray 
        print(restaurant.dishes?.count) 
        allDishesArray.addObjectsFromArray(dishesArray as [AnyObject]) 
        // self.allDishes.addObjectsFromArray(dishesArray as [AnyObject]) <-- do not do this 
        // print(self.allDishes.count) 
       } 
       else { 
        print("not dishes found") 
       } 
       // completion(result:allDishesArray) <-- No need for this, remove 
       dispatch_group_leave(group) // Leave group, marking this restaurant as complete 
      }) 
      // completion(result:allDishesArray) <-- Do not call here either 
     } 
    } 

    // Wait for all groups to complete 
    dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) { 
     completion(result:allDishesArray) 
    } 
} 
+0

是的,我剛剛離開完成部分有原因,否則它不會被稱爲直到它爲時已晚。你的建議聽起來很棒,我從來沒有聽說過它。謝謝你,我會讓你知道它是如何去接受你的答案。 –

+1

夥計!非常感謝這個建議,「快速修復」的工作,但我更多地關注NSOpertationQueue。 –