reloadData没有在主线程上填充公开指标

时间:2016-04-14 22:46:31

标签: ios swift multithreading asynchronous reloaddata

所以我想: 1.从网站上提取用户列表 2.保存相关图像 3.根据此数据刷新表格

按下按钮后,我能够成功下拉所有数据,但最后一次可识别的代码调用与“屏幕上的刷新”数据之间有30秒的延迟。我尝试在主线程异步调用中调用reloadData,但我得到的输出缺少2行和所有披露指标。

根据configurecell中的调试代码,这两行正在评估,但最终没有显示。当它在30秒后再次刷新时,披露指示器和前2个单元格都正确显示。不确定我做错了什么。我正在使用nsoperator但似乎waituntilalloperations调用正在工作,因为除了主线程和在此调用之后执行更新的线程之外,所有线程都显示为非活动状态。

我知道等待调用以及我的其他一些代码阻塞了异步线程一段时间但是坦白说用户此时无法在我的软件中执行任何操作,这是一个完整的擦除和刷新所有数据都没有实际的并行处理。

我的下载功能,由按钮运行并解析和下载网站:

func getDataFromWebsite(completion: ((result:NSString?) -> Void)!) {    
    let loadingNotification = MBProgressHUD.showHUDAddedTo(self.navigationController?.view, animated: true)
    self.navigationController?.view.addSubview(loadingNotification)
    loadingNotification.mode = MBProgressHUDMode.Indeterminate
    loadingNotification.labelText = "Loading"

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {

        // create the request
        let url = NSURL(string: "http://176.32.230.47/kaisersscerdevelopment.com/")
        let session = NSURLSession.sharedSession()

        // set up array of most current records to be downloaded
        var downloadRecords = [downloadInfo]()

        // confirm that connection was made to website
        var websiteFound:Bool = false

        // download data synchronously and store in results array
        let results = session.synchronousDataTaskWithURL(url!)
        // extract status to determine if website was found or not
        let status = results.3
        let error = results.2
        // if website was not found, warn user and quit data refresh
        if ((status < 200) || (status > 299) || (error != nil)) {
            dispatch_async(dispatch_get_main_queue(), {
                let alert = UIAlertController(title: "Download Error", message: "Profiles could not be downloaded. Please ensure that you have access to the Intranet.", preferredStyle: UIAlertControllerStyle.Alert)

                // add an action (button)
                alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))

                // show the alert
                self.presentViewController(alert, animated: true, completion: nil)
            })
        } else {
            // if website was found, proceed with data refresh
            websiteFound = true

            // clear existing records
            dispatch_async(dispatch_get_main_queue(), {
                self.clearExistingData()
            })
            //run parser with data obtained
            let websiteParser = TFHpple(data: results.0, isXML: false)
            if let profiles = websiteParser.searchWithXPathQuery("/html/body/div[@class='profile']") as? [TFHppleElement] {
                for profile in profiles {
                    let downloadRecord = downloadInfo()
                    let names = profile.childrenWithClassName("name")[0].content as NSString
                    let name = names.componentsSeparatedByString(" ")
                    downloadRecord.firstName = name[0]
                    downloadRecord.lastName = name[1]
                    downloadRecord.searchTerms = profile.childrenWithClassName("searchTerms")[0].content as NSString
                    downloadRecord.gender = profile.childrenWithClassName("gender")[0].content
                    downloadRecord.position = profile.childrenWithClassName("position")[0].content
                    downloadRecord.photoPath = profile.childrenWithClassName("sphoto")[0].objectForKey("src") as NSString
                    downloadRecords.append(downloadRecord)
                } //closes for loop
            } //closes TFHpple
        }
        // downloadRecords array now synchronously populated

        // if we have now downloaded from a website, then
        if websiteFound {
            let queue = NSOperationQueue()
            queue.name = "Download queue"
            for downloadRecord in downloadRecords {
                // pull image address from website

                if downloadRecord.photoPath == nil {
                    print ("PhotoURL is nil")
                }
                let photoURL = NSURL(string: downloadRecord.photoPath as! String)
                // download image
                let imageDownload = DownloadOperation(session: NSURLSession.sharedSession(), URL: photoURL!)
                queue.addOperation(imageDownload)

                let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
                let context:NSManagedObjectContext = appDel.managedObjectContext!

                //prep and save coredata
                let newStaff = NSEntityDescription.insertNewObjectForEntityForName("Staff", inManagedObjectContext: context) as NSManagedObject
                newStaff.setValue(downloadRecord.firstName, forKey: "firstName")
                newStaff.setValue(downloadRecord.lastName, forKey: "lastName")
                if downloadRecord.gender == "F" {newStaff.setValue(true, forKey: "isFemale")
                } else {
                    newStaff.setValue(false, forKey: "isFemale")
                }
                newStaff.setValue(downloadRecord.position, forKey: "position")
                newStaff.setValue("\(downloadRecord.firstName) \(downloadRecord.lastName) \(downloadRecord.searchTerms)", forKey: "searchTerms")
                newStaff.setValue(NSDate(), forKey: "timeStamp")
                let photoName = downloadRecord.photoPath!.componentsSeparatedByString("/").last!
                do {
                    newStaff.setValue(photoName, forKey: "imagePath")
                    try context.save()
                }
                catch _ {
                    print("save error")
                }
            }
            queue.waitUntilAllOperationsAreFinished()

        }
        dispatch_async(dispatch_get_main_queue(), {
            MBProgressHUD.hideAllHUDsForView(self.navigationController?.view, animated: true)
            self.tableView.reloadData()
        })


    })
}

我的configurecell为前两行触发但不显示:

func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
    let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject
    if (((object.valueForKey("firstName")?.description) != nil) && ((object.valueForKey("lastName")?.description) != nil) && ((object.valueForKey("position")?.description) != nil)) {
        cell.textLabel?.text = object.valueForKey("firstName")!.description + " " + object.valueForKey("lastName")!.description
        print("refreshing for staff \(cell.textLabel?.text) at index \(indexPath)")
        cell.detailTextLabel?.text = object.valueForKey("position")!.description
    }
    var documentsDirectory:String?
    var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    if paths.count > 0 {
        documentsDirectory = paths[0] as? String
        let savePath = documentsDirectory! + "/" + object.valueForKey("imagePath")!.description
        if UIImage(named: savePath) != nil
        {
            cell.imageView!.image = UIImage(named: savePath)
            let picWidth = cell.imageView?.image?.size.width
            let picHeight  = cell.imageView?.image?.size.height
            if ((picHeight != nil) && (picWidth != nil))
            {
                let aspect = picWidth! / picHeight!
                var itemSize:CGSize
                if picWidth! / aspect <= picHeight {
                    itemSize = CGSizeMake(picWidth!, picWidth!)
                } else {
                    itemSize = CGSizeMake(picHeight!, picHeight!)
                }
                UIGraphicsBeginImageContextWithOptions(itemSize, false, UIScreen.mainScreen().scale)
                let imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height) as CGRect
                cell.imageView?.image?.drawInRect(imageRect)
                cell.imageView?.image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
            }
            else {
                print("pic width or height is nil!")
            }
        }
        else {
            print("savepath is nil!")
        }
    }
}

我的reloadData调用后的应用程序(没有披露指标和前2行缺失): !http://176.32.230.47/kaisersscerdevelopment.com/Photos/Screenshot1.png

应用30秒等待和神秘的自动刷新(正确): !http://176.32.230.47/kaisersscerdevelopment.com/Photos/Screenshot2.png

对任一方面的任何见解:

a)为什么我必须等待30秒才能进行“工作刷新”,因为我已经调用了waituntil ...用于我的异步调用以及第二次刷新来自或...

b)configurecell如何使用正确的调试信息运行前两行,但这些行和公开指示符都不会显示在初始reloadData或...

c)任何一般的代码提示或批评(我想我的代码中的内存泄漏是我正在寻找的地方)

非常感谢!显然没有期待对所有事情的完美答案,但我是自学而且刚开始并且会欣赏任何明智的话语。

谢谢你们!

ZDB

0 个答案:

没有答案