2016-05-03 14 views
1

ここでは、以下の私のコードです:スウィフト:データソース構造体からデータを取得しようとすると

class DataSource: NSObject { 
    var categories = [String]() 
    var items = [Item]() 

    private override init() { 
     super.init() 
    } 

    class var sharedDataSource: DataSource { 
     struct Static { 
      static var onceToken: dispatch_once_t = 0 
      static var instance: DataSource! 
     } 
     dispatch_once(&Static.onceToken) { 
      let dataSource = DataSource() 
      Static.instance = dataSource 

      let urlPath = "myUrlPathString" 
      let endpoint = NSURL(string: urlPath) 
      let request = NSMutableURLRequest(URL: endpoint!) 

      NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in 
       let json = JSON(data: data!) 
       print(json) 
       for obj in json.arrayValue { 
        let item: Item = Item() 
        item.itemID = obj["item"].stringValue 
        item.price = obj["price"].floatValue 
        item.title = obj["title"].stringValue 
        item.category = obj["category"].stringValue 
        item.available = obj["available"].boolValue 
        item.image = obj["image"].stringValue 
        print(item.title) 
        dataSource.items.append(item) 
        print(dataSource.items) 
        print("STOP") 
       } 
      }).resume() 
     } 
     return Static.instance 
    } 
} 

私はアイテムの配列にその結果を割り当てることによって、UICollectionViewでこのデータソースの結果を使用しようとしています。 NSURLSession内のデータを正常に取得しています。ローカルリスト 'items'にデータが入力されています。 viewDidLoad内の値は常に値を持たない空の配列になりますが、私は値がわかっているの印刷

let dataSource = DataSource() 
items = dataSource.sharedInstance.items 

次のように私のUICollectionViewで

は、私のviewDidLoadで、私は私のローカル変数を代入していますNURLSessionが終了するまでにそこにいます。私はこれのための完了ハンドラを書く方法がわかりません。これは構造体であるsharedDataSourceでこのようなことを行うのは初めてのことです。

答えて

0

あなたがのviewDidLoadでこれをやっている場合は、それはだ

おかげで、

ショーンはそうNSURLセッションでは、あなたの項目の配列を取得しようとする時までに完了していません。データが受信され、項目を設定した後で、dataSourceクラスで通知を送信します。

例:

NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in 
      let json = JSON(data: data!) 
      print(json) 
      for obj in json.arrayValue { 
       let item: Item = Item() 
       item.itemID = obj["item"].stringValue 
       item.price = obj["price"].floatValue 
       item.title = obj["title"].stringValue 
       item.category = obj["category"].stringValue 
       item.available = obj["available"].boolValue 
       item.image = obj["image"].stringValue 
       print(item.title) 
       dataSource.items.append(item) 
       print(dataSource.items) 
       print("STOP") 
      } 
      NSNotificationCenter.defaultCenter().postNotificationName("dataRecievedNotification", object: nil) 

     }).resume() 

しかし、あなたはまた、collectionViewであなたのViewControllerにこの通知を受信できるようにする必要があります。

データソースがのviewDidLoad上で宣言された変数である
func dataRecieved() { 
    print("data received") 
    items = dataSource.sharedInstance.items 
    collectionView.reloadData() 
} 

:もしあなたことを忘れてはいけない

let dataSource = DataSource() 

をので、のviewDidLoadに続いて同じのViewControllerに機能を追加

NSNotificationCenter.defaultCenter().addObserver(self, selector: "dataRecieved", name: "dataRecievedNotification", object: nil) 

を追加クラスがメモリから削除されたときにオブザーバを削除する必要があるオブザーバを使用しているので、ViewControllerに次のdeinit関数を追加します。

deinit { 
    NSNotificationCenter.defaultCenter().removeObserver(self) 
} 

EDIT:あなたのシングルトンパターンは、現代の迅速を使用して簡略化できると思います。 structまたはdispatch_onceをそれ以上使用する必要はありません。静的なlet共有インスタンスがすべてのものを処理すると宣言するだけです。このことを念頭に置いて、私はあなたのデータソースクラスを簡素化しようとした:あなたは、のviewDidLoadで、次のロジックを追加

class DataSource { 

static let sharedInstance = DataSource() 

var items = [Item]() 

private init() {} 

func retrieveItems() { 

    let urlPath = "myUrlPathString" 
    let endpoint = NSURL(string: urlPath) 
    let request = NSMutableURLRequest(URL: endpoint!) 

    NSURLSession.sharedSession().dataTaskWithRequest(request,completionHandler: { (data, response, error) in 

     let json = JSON(data: data!) 
     print(json) 

     for obj in json.arrayValue { 
      let item: Item = Item() 
      item.itemID = obj["item"].stringValue 
      item.price = obj["price"].floatValue 
      item.title = obj["title"].stringValue 
      item.category = obj["category"].stringValue 
      item.available = obj["available"].boolValue 
      item.image = obj["image"].stringValue 
      print(item.title) 
      items.append(item) 
      print(items) 
      print("STOP") 
     } 

     NSNotificationCenter.defaultCenter().postNotificationName("dataRecievedNotification", object: nil) 

    }).resume() 

} 

} 

func dataRecieved() { 
    print("data received") 
    items = DataSource.sharedInstance.items //Notice the capital 
    collectionView.reloadData() 
} 

if DataSource.sharedInstance.items.count == 0 { 
    DataSource.sharedInstance.retrieveItems() 
} 

その後、変更dataRecievedをし、あなたの宣言を削除するvar dataSource = DataSource()viewDidLoadの上

+0

私は上記のコードを試しました。すべてが正しい順序で起こっているように見えますが、NSURL Sessionが終了してdataReceivedが実行されると配列はまだ空ですが、項目は何らかの理由でUICollectionViewの空の配列です。 Hrm。私もすることはできません: let dataSource = DataSource() 私はpublicに初期化子を設定しない限り。しかし、items = dataSource.sharedInstaince.itemsは機能しません。 items = dataSource.itemsでなければならず、それはNSURLSessionをまったくトリガーしません。 :( Hrm。 – Pleirosei

+0

私はあなたのdataSourceクラスを変更しました。それが意味をなさない/まだ動作していない場合は私にメッセージしてください:) –

関連する問題