2016-01-08 21 views
1

我有以下代碼:斯威夫特價值封閉內消失

let context = DBHelper.privateContext() 
    context.performBlock({ [weak self] in 
     if let ss = self { 
      //1. 
      let articles = DBHelper.clientFetchArticles(context) 
      //2. 
      dispatch_async(dispatch_get_main_queue(), { 
       //3. 
       ss.articles = articles 
       ss.tableView.reloadData() 
       ss.refreshControl.endRefreshing() 
      }) 
     } 
    }) 

調用tableView.reloadData()後,下面的代碼運行:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCellWithIdentifier("ArticleCell", forIndexPath: indexPath) as! ArticleCell 

    #4 
    let article = articles[indexPath.row] 


    cell.setupWithArticle(article) 

    return cell 
} 

DBHelper.clientFetchArticles將返回[Article]有2篇文章(類型ManagedObject的) 。

  • 在#1,當我打印po articles[0].title,我得到正確的title打印出來。

  • 在#3,po articles.count打印2po articles[0].title也是正確的

  • 在#4,po self.articles[0].title得到爲零。

我試過dispatch_sync(dispatch_get_main_queue())但仍然是相同的結果。

+0

你在#4試過'po self.articles [0]'嗎? – anhtu

+0

是的,我已經試過了,它是一樣的('文章'是視圖控制器的屬性) – OMGPOP

+0

它也是零? – anhtu

回答

2

很可能是因爲您的privateContext()實現。執行回調後,將捕獲的context解除分配,這將使您從該上下文中獲取的Article對象失效。

推薦的約定是在處理UI提取請求時使用「主要上下文」(從你的AppDelegate一路通過的那個)。出於異步更新(例如,網絡連接)的目的使用private context

1

我的猜測是dispatch_async閉包捕獲周圍的值,但是因爲你沒有修改捕獲的值,在這種情況下,它將複製它而不是對該數組的引用。

最簡單的解決將是使articles該類

鏈路的特性的Swift docs

+0

我再次測試,問題是不正確的。我更新了我的問題 – OMGPOP

+0

「它製作了它的副本,而不是對該數組的引用。」如果它是一個本地swift'Array',它將永遠是一個副本:Swift數組是結構體和結構體是值類型。如果他使用'NSArray' /'NSMutableArray',它只能是一個參考。 –

+0

是的,但爲什麼複製版本的'articles'缺少屬性 – OMGPOP