Приносим извинения за простоту моего описания, я новичок в Swift как язык.Назначение данных после закрытия после dataTaskWithURL, приводящее к значениям nil
У меня есть REST api, который предоставляет все данные для моего приложения. Я пытаюсь заполнить табличный вид из канала JSON. По сути, я стараюсь изо всех сил придерживаться шаблонов MVC, которые я использую в веб-разработке. Поэтому я построил модель своего объекта данных, а затем модель списка, чтобы содержать отдельные экземпляры этого объекта.
Фактическая проблема, однако, когда я инициирую весь процесс (последний пример кода), число результатов равно 0, но это просто потому, что ответ данных для вызова API еще не произошел. Я бы предпочел не использовать синхронные вызовы, но я чувствую, что это единственный способ, которым я это исправлю, если только я не начну трахать свои вызовы API непосредственно в самом контроллере?
class NewsItem {
var id: Int
var headline: String
var summary: String
var created: String
var source: String
var company: String
var companyLogo: UIImage
init(headline: String, summary: String, created: String, source: String, company: String, companyLogoUrl: String, id: Int) {
self.id = id
self.headline = headline
self.summary = summary
self.created = created
self.source = source
self.company = company
if let url = NSURL(string: companyLogoUrl) {
if let data = NSData(contentsOfURL: url) {
companyLogo = UIImage(data: data)!
} else {
companyLogo = UIImage(named: "DefaultLogo")!
}
} else {
companyLogo = UIImage(named: "DefaultLogo")!
}
}
}
У меня тогда есть свой класс NewsList, который на самом деле создает массив новостей, используя закрытие для остального вызова.
class NewsList {
var name: String
var newsItems: [NewsItem]
init(named: String, includeNewsItems: [NewsItem]) {
name = named
newsItems = includeNewsItems
}
class func getNewsItems() -> [NewsList] {
return [self.parsedNews()]
}
private class func parsedNews() -> NewsList {
var newsItems = [NewsItem]()
api.getLatestActivityData({JSONData, error -> Void in
if (JSONData != nil) {
for (_, subJSON) in JSONData["data"] {
let headline = subJSON["headline"].string!
let summary = subJSON["summary"].string!
let created = subJSON["created"].string!
let source = subJSON["source"].string!
let company = subJSON["company"].string!
let companyLogo = subJSON["companyLogo"].string!
let id = subJSON["id"].int!
dispatch_async(dispatch_get_main_queue(), {
newsItems.append(NewsItem(headline: headline, summary: summary, created: created, source: source, company: company, companyLogoUrl: companyLogo, id: id))
})
}
} else {
print("api data fetch failed")
print(error)
}
})
return NewsList(named: "News", includeNewsItems: newsItems)
}
}
Для приведенного выше разговора, у меня есть следующий метод в моем классе RemoteAPI
func getLatestActivityData(completionHandler: ((JSON!, NSError!) -> Void)!) -> Void {
let requestUrl = self.baseUrl + "xxxxxxx"
print("Request URL: " + requestUrl)
let url = NSURL(string: requestUrl)!
let request = NSMutableURLRequest(URL: url)
request.setValue("text/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
if (error != nil) {
return completionHandler(nil, error)
}
print("Latest activity response received")
let returnString = NSString(data: data!, encoding: NSUTF8StringEncoding)
let jsonData = returnString!.dataUsingEncoding(NSUTF8StringEncoding)!
let readableJSON = JSON(data: jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
if (error != nil) {
return completionHandler(nil, error)
} else {
return completionHandler(readableJSON, nil)
}
})
task.resume()
}
Чтобы действительно начать цельные выше свернутой процесса, у меня есть это, на мой взгляд контроллер
var newsItems: [NewsItem] {
var newsList = NewsList.getNewsItems()
return newsList[0].newsItems
}
Вот наша точка боли. Если я запустил print(newsItems.count)
после вышеупомянутого вызова, результат равен 0. Однако через секунду или два обработчик обратного вызова фактически получит данные и начнет назначать элементы массиву newsList
.
Как предотвратить назначение массива, пока данные фактически не получены? Я просто об этом не так?
Xcode 7 + Swift 2.0 + IOS 9.0.x
Итак, после дальнейшего чтения я думаю, что здесь я ошибаюсь, я должен обновлять табличное представление внутри закрытия, а не просто назначать данные массиву в основном потоке и затем возвращать этот массив. Я попытаюсь сыграть с этим и ответить на свой вопрос в информационных целях, если это сработает. – Sean