以下是我的代码:
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来做这种事情。
任何想法?
谢谢,
肖恩
答案 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()声明