所以我想: 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