Swift:尝试从dataSource Struct

时间:2016-05-03 20:26:35

标签: ios swift nsurlsession completionhandler

以下是我的代码:

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
    }
}

我试图通过将其结果分配给Item数组来在UICollectionView中使用此dataSource的结果。我成功地抓取了我的NSURLSession中的数据,并且正在填充其本地列表“items”。

在我的UICollectionView中,在我的viewDidLoad中,我按如下方式分配我的局部变量:

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

在viewDidLoad中打印值总是会产生一个没有值的空数组,但我知道NURLSession完成时的值就在那里。我不知道如何为此编写完成处理程序。这是我第一次使用作为结构的sharedDataSource来做这种事情。

任何想法?

谢谢,

肖恩

1 个答案:

答案 0 :(得分:0)

如果你在viewDidLoad中这样做,那么当你尝试获取你的items数组时,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()

但您还需要能够在ViewController中使用collectionView接收此通知。所以在viewDidLoad中添加

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

然后在同一个ViewController中添加一个函数:

func dataRecieved() {
    print("data received")
    items = dataSource.sharedInstance.items
    collectionView.reloadData()
}

其中dataSource是在viewDidLoad上面声明的变量:

let dataSource = DataSource()

不要忘记,如果您正在使用观察者,则需要在从内存中删除类时删除它们,因此在ViewController中添加此deinit函数:

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

编辑:我认为使用现代swift可以简化你的单例模式。您不必再使用struct或dispatch_once,只需声明静态let共享实例将为您处理所有这些。考虑到这一点,我试图简化您的dataSource类:

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()

}

}

你在viewDidLoad中添加以下逻辑:

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

然后将dataRecieved更改为

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

并删除viewDidLoad

上方的var dataSource = DataSource()声明