2016-03-15 34 views
0

我有作爲一個數組存儲在NSUserDefaults中的數據。我需要使用Parse Server將這些數據存儲在數據庫中。當我嘗試循環訪問數組並使用saveInBackgroundWithBlock時,循環在塊完成之前再次運行設置新值。將數據保存爲數據庫上的單個對象的最佳方法是什麼?如何在循環中快速保存背景

let other = PFObject(className: "Other") 
if (NSUserDefaults.standardUserDefaults().objectForKey("otherTypes") != nil) && (NSUserDefaults.standardUserDefaults().objectForKey("otherCosts") != nil) { 
     otherCosts = NSUserDefaults.standardUserDefaults().objectForKey("otherCosts") as! [Double] 

     otherTypes = NSUserDefaults.standardUserDefaults().objectForKey("otherTypes") as! [String] 

     for costs in otherCosts { 

      other.setObject(PFUser.currentUser()!.objectId!, forKey: "userId") 
      other.setObject(otherTypes[i], forKey: "otherName") 
      let cost = String(costs) 
      other.setObject(cost, forKey: "otherCost") 
      i = i + 1 
      other.saveInBackgroundWithBlock({ (success, error) -> Void in 
       if error == nil { 
        print("Success") 
        NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherTypes") 
        NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherCosts") 
       } else { 
        print("Fail") 
       } 
      }) 
     } 
+1

查找到NSCondition類,它允許一個線程等待另一個線程完成。使用它你可以等待之前的save()完成,然後再次開始循環。 –

+0

你想在Parse中包含多個'Other'對象嗎?還是包含兩個數組的對象? – Paulw11

回答

0

您需要分配PFObject for循環,否則你只是與同一個對象遍地搞亂。

if (NSUserDefaults.standardUserDefaults().objectForKey("otherTypes") != nil) && (NSUserDefaults.standardUserDefaults().objectForKey("otherCosts") != nil) { 
     otherCosts = NSUserDefaults.standardUserDefaults().objectForKey("otherCosts") as! [Double] 

     otherTypes = NSUserDefaults.standardUserDefaults().objectForKey("otherTypes") as! [String] 

     for costs in otherCosts { 
      let other = PFObject(className: "Other") 
      other.setObject(PFUser.currentUser()!, forKey: "userId") 
      other.setObject(otherTypes[i], forKey: "otherName") 
      let cost = String(costs) 
      other.setObject(cost, forKey: "otherCost") 
      i = i + 1 
      other.saveInBackgroundWithBlock({ (success, error) -> Void in 
       if error == nil { 
        print("Success") 
        NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherTypes") 
        NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherCosts") 
       } else { 
        print("Fail") 
       } 
      }) 
     } 

由於

0

您可以在後臺線程上運行所有這一切,並使用一個信號阻斷:

let semaphore = dispatch_semaphore_create(0) 
for costs in otherCosts { 
    //... 
    other.saveInBackgroundWithBlock({ (success, error) -> Void in 
     // ... 
     dispatch_semaphore_signal(semaphore) 
    }) 
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) 
} 

注意,因爲這是一個長期運行的操作,你肯定不希望這樣做節省在前臺線程中。其他

一種可能性是整個事情轉化爲工作隊列安排,它看起來像:

func tryToSend() { 
    let defaults = NSUserDefaults.standardUserDefaults() 
    if let otherTypes = defaults.objectForKey("otherTypes") as? [String], 
     let otherCosts = defaults.objectForKey("otherCosts") as? [Double] { 
      if otherTypes.count > 0 { 
       let other = PFObject(className: "Other") 
       other.setObject(PFUser.currentUser()!.objectId!, forKey: "userId") 
       other.setObject(otherTypes[0], forKey:"otherName") 
       other.setObject("\(otherCosts[0])", forKey:"otherCost") 
       other.saveInBackgroundWithBlock({ (success, error) -> Void in 
        if error == nil { 
         print("Success") 
         otherTypes = otherTypes[1..<otherTypes.count] 
         otherCosts = otherCosts[1..<otherCosts.count] 
         defaults.setObject(otherTypes, forKey: "otherTypes") 
         defaults.setObject(otherCosts, forKey: "otherCosts") 
         tryToSend() 
        } else { 
         print("Fail") 
        } 
       }) 
      } 
    } 
} 

這樣做的好處是,你不必擔心分拆另一個線程,並且可以動態地添加更多的條目otherTypes和otherCosts(用適當的同步,以確保在NSUserDefaults的不修改而讀)

一個在這種情況下最終的想法,就是用PFObject.saveAllInBackground方法來做這件事在一個網絡操作,看起來像這樣:

let defaults = NSUserDefaults.standardUserDefaults() 
if let otherTypes = defaults.objectForKey("otherTypes") as? [String], 
    let otherCosts = defaults.objectForKey("otherCosts") as? [Double] { 
     let others = zip(otherTypes, otherCosts).map { type, cost in 
      let other = PFObject(className:"Other") 
      other.setObject(PFUser.currentUser()!.objectId!, forKey: "userId") 
      other.setObject(type, forKey: "otherName") 
      other.setObject("\(cost)", forKey: "otherCost") 
      return other 
     } 

     PFObject.saveAllInBackground(others) { (success, error) in 
      if error == nil { 
       print("Success") 
       NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherTypes") 
       NSUserDefaults.standardUserDefaults().setObject(nil, forKey: "otherCosts") 
      } else { 
       print("Fail") 
      } 
     } 
} 
+1

另外,請注意,按照書面形式,當第一個值成功保存時,您的代碼將清除整個otherTypes和其他成員數組。 –

+0

PaulW11的回答對於這種情況已經足夠了。我很欣賞處理這個問題的多種不同方式,並給我未來的選擇。 – bobthegoalie