我正在尝试使用grand central dispatch创建一个后台线程,并在alertcontroller操作中执行一些操作,但它阻止了主线程。这是我的完整课程代码,请检查,因为我找不到我做错了什么? :
class DisplayMangaViewController: UIViewController, UIScrollViewDelegate, UIPageViewControllerDataSource, UIToolbarDelegate {
//variables set there
@IBAction func actionBarButtonItem(sender: AnyObject) {
if let popoverController = controller!.popoverPresentationController {
popoverController.barButtonItem = sender as! UIBarButtonItem
}
self.presentViewController(controller!, animated: true, completion: nil)
}
@IBAction func actionTabBarItem(sender: AnyObject) {
ActionSheetStringPicker.showPickerWithTitle("Sayfaya Git", rows: self.pages, initialSelection: self.pageCounter, doneBlock: {
picker, value, index in
var pageIndex = index.integerValue - 1
let aimedController = self.getItemController(pageIndex)!
let startingViewControllers: NSArray = [aimedController]
self.pageViewController!.setViewControllers(startingViewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
return
}, cancelBlock: { ActionStringCancelBlock in return }, origin: sender)
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = self.currentChapter
setActionSheet()
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
pageController.dataSource = self
if self.currentToolBar.hidden {
pageController.view.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: (self.view.frame.size.height))
}else {
pageController.view.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: (self.view.frame.size.height - 40.0))
}
if imageUrlsList.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemViewController
if itemController.itemIndex > 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! PageItemViewController
if itemController.itemIndex+1 < pages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
private func getItemController(itemIndex: Int) -> PageItemViewController? {
pageCounter = itemIndex
setLabel()
if itemIndex < pages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("PageItemViewController") as! PageItemViewController
pageItemController.itemIndex = itemIndex
pageItemController.totalItem = self.pages.count
pageItemController.strUrl1 = self.imageUrlsList[pageCounter]
pageItemController.strUrl2 = self.imageUrlsList[(pageCounter + 1)]
return pageItemController
}
return nil
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return pages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(animated: Bool) {
self.view.addGestureRecognizer(tapGesture)
self.tabBarController?.tabBar.hidden = true
}
override func viewDidAppear(animated: Bool) {
if !userDefaults.boolForKey("kalınanMangaBool"){
var viewToDisplay : UIWindow = UIApplication.sharedApplication().windows.last as! UIWindow
self.mbProHud = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
self.mbProHud.dimBackground = true
self.mbProHud.mode = MBProgressHUDMode.Indeterminate
self.mbProHud.labelText = "Yükleniyor!.."
UrlAndNameList.getPageUrlsOfChapter(currentChapter, ofManga: self.obtainedManga.name)
}else{
var encodedObject : NSData? = userDefaults.objectForKey("kalınanManga") as? NSData
self.obtainedManga = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as! Manga
currentChapter = obtainedManga.chapterNu
pageCounter = obtainedManga.pageNu
self.pageCounter = 0
pages = userDefaults.objectForKey("kalınanMangaPages") as! [String]
self.imageUrlsList = userDefaults.objectForKey("kalınanMangaImageUrlsList") as! [String]
self.navigationItem.title = obtainedManga.name + " " + currentChapter
setLabel()
createPageViewController()
}
}
func setActionSheet(){
controller = UIAlertController(title: "Seçenekler", message: "Ne yapmak İstersiniz?", preferredStyle: .ActionSheet)
let actionDownload = UIAlertAction(title: "Bölümü İndir", style: UIAlertActionStyle.Default, handler: {(paramAction : UIAlertAction!) in
var mbProHud : MBProgressHUD!
var viewToDisplay : UIWindow = UIApplication.sharedApplication().windows.last as! UIWindow
mbProHud = MBProgressHUD.showHUDAddedTo(viewToDisplay, animated: true)
mbProHud.customView = UIImageView(image: UIImage(named: "37x-Checkmark.png"))
mbProHud.mode = MBProgressHUDMode.CustomView
mbProHud.dimBackground = true
mbProHud.labelText = "İndirme Başlatıldı!"
mbProHud.hide(true, afterDelay: 2)
let qos = Int(QOS_CLASS_BACKGROUND.value)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
var selectedChapters : [String] = [self.currentChapter]
var mangaNameArray = [self.obtainedManga.name]
let notification = NSNotification(name: "downloadListNotification", object: self, userInfo: ["downloadList" : selectedChapters, "mangaName" : mangaNameArray])
self.downloadChapter(notification)
//NSNotificationCenter.defaultCenter().postNotification(notification)
})
})
controller!.addAction(actionDownload)
let actionShare = UIAlertAction(title: "Paylaş", style: UIAlertActionStyle.Default, handler: {(paramAction : UIAlertAction!) in
var itemsToShare : [String] = [self.obtainedManga.name, self.obtainedManga.chapterNu, self.pages[self.pageCounter], "Süperr bi mangadan süperr bi sahne! TürkİşManga Aracılığıyla..."]
let activityViewController = UIActivityViewController(activityItems: itemsToShare, applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)
})
controller!.addAction(actionShare)
let actionSave = UIAlertAction(title: "Favorilere Ekle", style: UIAlertActionStyle.Default, handler: {(paramAction : UIAlertAction!) in
self.addToFav(self.obtainedManga)
})
controller!.addAction(actionSave)
let actionSettings = UIAlertAction(title: "Ayarlar vs.", style: UIAlertActionStyle.Default, handler: {(paramAction : UIAlertAction!) in
self.performSegueWithIdentifier("ayarlar", sender: self)
})
controller!.addAction(actionSettings)
let actionAboutUs = UIAlertAction(title: "Biz Kimiz?", style: UIAlertActionStyle.Default, handler: {(paramAction : UIAlertAction!) in
self.performSegueWithIdentifier("hakkımızda", sender: self)
})
controller!.addAction(actionAboutUs)
let actionCancel = UIAlertAction(title: "İptal", style: UIAlertActionStyle.Default, handler: nil)
controller!.addAction(actionCancel)
}
func downloadChapter(notification : NSNotification){
let userDefaults = NSUserDefaults.standardUserDefaults()
var filePath : String = "Turk Isi Manga"
let qos = Int(QOS_CLASS_USER_INITIATED.value)
//dispatch_async(dispatch_get_global_queue( qos, 0), {
var chaptersToDownload : [String] = notification.userInfo!["downloadList"] as! [String]
var mangaName : String = (notification.userInfo!["mangaName"] as! [String]).first!
var downList : [DownloadingManga] = []
for chapter in chaptersToDownload{
var down = DownloadingManga()
down.mangaName = mangaName
down.chapterName = chapter
down.progress = 0
down.title = down.mangaName + " " + down.chapterName + "İndirilen \(down.progress)"
downList.append(down)
}
var encodedObject : NSData? = userDefaults.objectForKey("currentDownloadingList") as? NSData
var unarchivedlist = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as! [DownloadingManga]
unarchivedlist.extend(downList)
var archivedList = NSKeyedArchiver.archivedDataWithRootObject(unarchivedlist)
userDefaults.setObject(archivedList, forKey: "currentDownloadingList")
userDefaults.synchronize()
let path = NSURL.documentsFolder().URLByAppendingPathComponent("\(filePath)/covers/\(mangaName)")
let manager = NSFileManager.defaultManager()
if (manager.fileExistsAtPath("\(path)")) {
println("cover image of manga named \(mangaName) has already saved")
}else{
var query = PFQuery(className:"MangaNamesAndUrls")
query.whereKey("mangaName", equalTo: mangaName)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
var url = objects[0].objectForKey("coverImageUrl") as! String
if Reachability.isConnectedToNetwork(){
let url : NSURL? = NSURL(string: url)
let urlRequest = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 15.0)
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
var error : NSErrorPointer = nil;
if let data = (NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: response, error: error) as NSData?) {
if let img = UIImage(data: data){
let filePath = NSURL.documentsFolder().URLByAppendingPathComponent("\(filePath)/covers/\(mangaName)")
println("file path that cover image will be saved is \(filePath)")
var fileError : NSErrorPointer = nil
filePath.setResourceValue(NSNumber(bool: true), forKey: NSURLIsExcludedFromBackupKey, error: fileError)
UIImagePNGRepresentation(img).writeToURL(filePath, atomically: true)
}
}else{
}
}
}
} else {
println("Error: \(error!) \(error!.userInfo!)")
}
}
}
for chapter in chaptersToDownload{
self.createDirectory(mangaName, chapter: chapter)
var pagesList : [String] = []
var succeed = false
var query = PFQuery(className: "MangaItems")
query.whereKey("mangaName", equalTo: mangaName)
query.whereKey("chapterName", equalTo: chapter)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
println(objects?.count)
if error == nil {
if let inobjects = objects as? [PFObject] {
for object in inobjects {
if let pages = object.objectForKey("pages") as? [String] {
pagesList.extend(pages)
println(pages)
}
}
}
}else{
println("Error: \(error!) \(error!.userInfo!)")
}
var counter = 0
for var i = 0 ; i < pagesList.count ; i++ {
println("attempted to download page number : \(i)")
if Reachability.isConnectedToNetwork(){
let url : NSURL? = NSURL(string: pagesList[i])
let urlRequest = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 15.0)
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
var error : NSErrorPointer = nil;
if let data = (NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse: response, error: error) as NSData?) {
if let img = UIImage(data: data){
let filePath = NSURL.documentsFolder().URLByAppendingPathComponent("\(filePath)/\(mangaName)/\(chapter)/\(i)")
UIImagePNGRepresentation(img).writeToURL(filePath, atomically: true)
counter++
println("downloaded page number : \(i) and counter is : \(counter)")
//dispatch_async(dispatch_get_main_queue(), {
var downloaded = DownloadingManga()
downloaded.mangaName = mangaName
downloaded.chapterName = chapter
downloaded.progress = ((i + 1) * 100)/pagesList.count
downloaded.title = downloaded.mangaName + " " + downloaded.chapterName + " İndirilen : \(downloaded.progress)"
let notification = NSNotification(name: "downloadedNotification", object: DownloadHandler.self, userInfo: ["downloading" : downloaded])
var downque = DownloadingQueueViewController()
NSNotificationCenter.defaultCenter().postNotification(notification)
//})
}
}else{
}
}else{
if userDefaults.boolForKey("isApplicationActive"){
//bağlantı koptu bildirilmeli ve indirmeler durdurulmalı
println("bağlantı koptu kontrol et")
}
//dispatch_async(dispatch_get_main_queue(), {
let notification = UILocalNotification()
notification.fireDate = NSDate(timeIntervalSinceNow: 1)
notification.timeZone = NSCalendar.currentCalendar().timeZone
notification.alertBody = "Bölüm İndirilirken Bağlantı Koptu. İndirme Tamamlanamadı! :("
notification.hasAction = true
notification.alertAction = "View"
notification.userInfo = [:]
UIApplication.sharedApplication().scheduleLocalNotification(notification)
//})
break
}
if counter == pagesList.count {
succeed = true
println("succeed = \(succeed)")
}else{
succeed = false
println("succeed = \(succeed)")
}
}
if succeed {
if !self.isContaining(mangaName){
var encodedObject : NSData? = userDefaults.objectForKey("indirilenlerList") as? NSData
var tempIndList = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as! [Manga]
var manga = Manga()
manga.name = mangaName
tempIndList.insert(manga, atIndex: 0)
var updatedTempIndList = NSKeyedArchiver.archivedDataWithRootObject(tempIndList)
userDefaults.setObject(updatedTempIndList, forKey: "indirilenlerList")
}
if userDefaults.boolForKey("isApplicationActive"){
}else{
//dispatch_async(dispatch_get_main_queue(), {
let notification = UILocalNotification()
notification.fireDate = NSDate(timeIntervalSinceNow: 1)
notification.timeZone = NSCalendar.currentCalendar().timeZone
notification.alertBody = "Bölüm İndirildi :) : Belgeler/\(mangaName)/\(chapter)/! Tıkla, Hemen Oku!"
notification.hasAction = true
notification.alertAction = "View"
notification.applicationIconBadgeNumber++
notification.userInfo = [
"MangaName" : mangaName,
"Chapter" : chapter
]
UIApplication.sharedApplication().scheduleLocalNotification(notification)
//})
}
}
}
}
println("async download method has came to the end!!!!!!!!!")
//})
}
func createDirectory(mangaName : String, chapter : String){
var filePath1 : String = "Turk Isi Manga"
// before create a new file path check it whether exist
let filePath = NSURL.documentsFolder().URLByAppendingPathComponent("\(filePath1)/\(mangaName)/\(chapter)")
var error:NSError?
let fileManager = NSFileManager()
if fileManager.createDirectoryAtURL(filePath, withIntermediateDirectories: true, attributes: nil, error: nil){
println("succeed to create the directory")
var fileError : NSErrorPointer = nil
filePath.setResourceValue(NSNumber(bool: true), forKey: NSURLIsExcludedFromBackupKey, error: fileError)
}else {
println("failed to create the directory")
}
}
func isContaining(name : String) -> Bool {
let userDefaults = NSUserDefaults.standardUserDefaults()
var encodedObject : NSData? = userDefaults.objectForKey("indirilenlerList") as? NSData
var tempIndList = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject!) as! [Manga]
var returnValue = false
for manga in tempIndList {
if manga.name == name {
returnValue = true
}
}
return returnValue
}
这是一个很长的代码,但任何帮助将非常感谢,谢谢...... 编辑:只有当我点击ui警报控制器操作按钮“Bölümüİndir”时才会出现问题。因为从该动作调用的所有背景材料。所有其他代码都可以视为上下文。我认为它与下载章节方法有关...
答案 0 :(得分:0)
问题在于dowloadChapter。我对这里发生的事情的猜测是,query.findObjectsInBackgroundWithBlock在主线程上调用完成块然后你正在进行nsurlconnection调用同步意味着它们阻塞直到完成。
因此,如果您希望它是异步的,则需要在查询完成内再次调度到后台线程。此外,您可能需要考虑使用NSURLSession而不是NSURLConnection。