Reputation: 470
I am developing an app in swift 2 but I'm a little bit stuck. I have a solid program that takes a unique identifier and gets a name in return, all the names are stored in an array. When I run my code I see the printed names but I while the names are downloading, I sometimes get a lot times the same error in the console, and then the name downloading goes on. Also not all the array content is displayed in the TableView. This is the error in the console:
`Marthe Tordeur Jorn Christiaens Yarne Leuckx Jordi Stevens Jonathan Essende Hanne Pappaert Bert Van den Abbeele Cedric de Smedt Hanne Delcourt 2015-09-10 17:26:33.934 ProfileViewer[1130:82460] This application is modifying the autolayout engine from a background thread, which can
lead to engine corruption and weird crashes. This will cause an exception in a future release. Stack:( 0 CoreFoundation 0x00000001051d79b5 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000106dd6deb objc_exception_throw + 48 2 CoreFoundation 0x00000001051d78ed +[NSException raise:format:] + 205 3 Foundation 0x000000010574a3f5 _AssertAutolayoutOnMainThreadOnly + 79 4 Foundation 0x00000001055ab23e -[NSISEngine withBehaviors:performModifications:] + 31 5 UIKit 0x0000000105a916e0 -[UIView(Hierarchy) _postMovedFromSuperview:] + 575 6 UIKit 0x0000000105a9e3e2 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1967 7 UIKit 0x0000000105b16a54 -[UITableView _addContentSubview:atBack:] + 420 8 UIKit 0x0000000105b34fef __53-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke + 2679 9 UIKit 0x0000000105a97548 +[UIView(Animation) performWithoutAnimation:] + 65 10 UIKit 0x0000000105b3455f -[UITableView _configureCellForDisplay:forIndexPath:] + 475 11 UIKit 0x0000000105b3f0f4 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 828 12 UIKit 0x0000000105b3f1db -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74 13 UIKit 0x0000000105b15250 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3187 14 UIKit 0x0000000105b47fa8 -[UITableView _performWithCachedTraitCollection:] + 92 15 UIKit 0x0000000105b30599 -[UITableView layoutSubviews] + 218 16 UIKit 0x0000000105aa1a3b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710 17 QuartzCore 0x0000000109e5636a -[CALayer layoutSublayers] + 146 18 QuartzCore 0x0000000109e4abd0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366 19 QuartzCore 0x0000000109e4aa4e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24 20 QuartzCore 0x0000000109e3f1d5 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277 21 QuartzCore 0x0000000109e6c9f0 _ZN2CA11Transaction6commitEv + 508 22 QuartzCore 0x0000000109e6ccd4 _ZN2CA11Transaction14release_threadEPv + 224 23 libsystem_pthread.dylib 0x0000000107c0a39c _pthread_tsd_cleanup + 470 24 libsystem_pthread.dylib 0x0000000107c09f78 _pthread_exit + 117 25 libsystem_pthread.dylib 0x0000000107c08596 pthread_attr_getschedpolicy + 0 26 libsystem_pthread.dylib 0x0000000107c06375 start_wqthread + 13 ) 2015-09-10 17:26:33.942 ProfileViewer[1130:82460] This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release. Stack:( 0 CoreFoundation 0x00000001051d79b5 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000106dd6deb objc_exception_throw + 48 2 CoreFoundation 0x00000001051d78ed +[NSException raise:format:] + 205 3 Foundation 0x000000010574a3f5 _AssertAutolayoutOnMainThreadOnly + 79 4 Foundation 0x00000001055aaa52 -[NSISEngine optimize] + 49 5 Foundation 0x00000001055ab314 -[NSISEngine withBehaviors:performModifications:] + 245 6 UIKit 0x0000000105a916e0 -[UIView(Hierarchy) _postMovedFromSuperview:] + 575 7 UIKit 0x0000000105a9e3e2 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1967 8 UIKit 0x0000000105b16a54 -[UITableView _addContentSubview:atBack:] + 420 9 UIKit 0x0000000105b34fef __53-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke + 2679 10 UIKit 0x0000000105a97548 +[UIView(Animation) performWithoutAnimation:] + 65 11 UIKit 0x0000000105b3455f -[UITableView _configureCellForDisplay:forIndexPath:] + 475 12 UIKit 0x0000000105b3f0f4 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 828 13 UIKit 0x0000000105b3f1db -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74 14 UIKit 0x0000000105b15250 -[UITableView _updateVisibleCellsNow:isRecursive:] + 3187 15 UIKit 0x0000000105b47fa8 -[UITableView _performWithCachedTraitCollection:] + 92 16 UIKit 0x0000000105b30599 -[UITableView layoutSubviews] + 218 17 UIKit 0x0000000105aa1a3b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 710 18 QuartzCore 0x0000000109e5636a -[CALayer layoutSublayers] + 146 19 QuartzCore 0x0000000109e4abd0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366 20 QuartzCore 0x0000000109e4aa4e _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24 21 QuartzCore 0x0000000109e3f1d5 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277 22 QuartzCore 0x0000000109e6c9f0 _ZN2CA11Transaction6commitEv + 508 23 QuartzCore 0x0000000109e6ccd4 _ZN2CA11Transaction14release_threadEPv + 224 24 libsystem_pthread.dylib 0x0000000107c0a39c _pthread_tsd_cleanup + 470 25 libsystem_pthread.dylib 0x0000000107c09f78 _pthread_exit + 117 26 libsystem_pthread.dylib 0x0000000107c08596 pthread_attr_getschedpolicy + 0 27 libsystem_pthread.dylib 0x0000000107c06375 start_wqthread + 13 ) `
func fetchTitle(identifier: String, completion: (title: String) -> Void) {
let profileUrl = NSURL(string:"http://www.facebook.com/" + identifier)!
let task = NSURLSession.sharedSession().dataTaskWithURL(profileUrl) {
(data, response, error) -> Void in
if let urlContent = data {
let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)
let websiteArray = webContent!.componentsSeparatedByString("pageTitle\">")
let secondArray = websiteArray[1].componentsSeparatedByString("</title>")
let title = secondArray[0]
completion(title: title)
print(title)
self.tableView.reloadData()
}
}
task.resume()
}
//print(newArray)
var titles = [String]()
let queue = dispatch_queue_create("titles", DISPATCH_QUEUE_SERIAL)
dispatch_apply(newArray.count, queue) { index in
let identifier = newArray[index]
fetchTitle(identifier) { title in
dispatch_async(queue) {
titles.append(title)
array.append(title)
}
}
}
Any help is appreciated! thanks!
Upvotes: 0
Views: 292
Reputation: 131503
As Eric said in his comment, your code is trying to UI updates on the background thread, which is bad.
Change your code as follows:
func fetchTitle(identifier: String, completion: (title: String) -> Void)
{
let profileUrl = NSURL(string:"http://www.facebook.com/" + identifier)!
let task = NSURLSession.sharedSession().dataTaskWithURL(profileUrl) {
(data, response, error) -> Void in
if let urlContent = data
{
let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)
let websiteArray = webContent!.componentsSeparatedByString("pageTitle\">")
let secondArray = websiteArray[1].componentsSeparatedByString("</title>")
let title = secondArray[0]
//------------------------------------------
//invoke the completion closure
//and the call to reloadData on the main thread.
dispatch_async(dispatch_get_main_queue())
{
completion(title: title)
print(title)
self.tableView.reloadData()
}
//------------------------------------------
}
}
task.resume()
}
By putting your calls to the completion handler and reloadData in a dispatch_async call to the main queue, you (asynchronously) hand it off to the main thread for processing.
Upvotes: 3