POST
|
Confirmed. I gave it several minutes and the status messages never came back. Here is the whole method call and blocks: let params = AGSGDBGenerateParameters(featureServiceInfo: weakSelf.gdbSyncTask.featureServiceInfo) var totalBytesDownloaded : NSNumber? var totalBytesExpected : NSNumber? var errorOccured = false weakSelf.agsResumableTaskJob = weakSelf.gdbSyncTask?.generateGeodatabaseWithParameters(params, downloadFolderPath: nil, useExisting: false, status: { status, userInfo in #if DEBUG print("GDB Download Status: \(AGSResumableTaskJobStatusAsString(status))") #endif if let userinfo = userInfo { if let error = userinfo["statusRequestError"] { print("Error: Could not generate geodatabase. Error details:\(error)") errorOccured = true weakSelf.agsResumableTaskJob?.cancel() if error.localizedDescription == "The Internet connection appears to be offline." { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Network Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the WSDOT Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } else if error.localizedDescription == "A server with the specified hostname could not be found." { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Network Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the WSDOT Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } else { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the WSDOT Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } } } if status == AGSResumableTaskJobStatus.Cancelled { dispatch_async(dispatch_get_main_queue()) { weakSelf.stopTimer() weakSelf.downloadButton.enabled = true weakSelf.downloadButton.hidden = false weakSelf.cancelDownloadButton.enabled = false weakSelf.cancelDownloadButton.hidden = true weakSelf.progressBar.progress = 0 weakSelf.timeElapsedLabel.text = "00:00:00"; weakSelf.progressFileSizeLabel.text = "0 MB of 0 MB" weakSelf.progressPercentLabel.text = "0 %" weakSelf.currentDownloadSpeedLabel.text = "0 MB" weakSelf.currentDownloadSpeedHeaderLabel.text = "Current D/L Speed:" } } else if status == AGSResumableTaskJobStatus.FetchingResult && errorOccured == false{ if let userinfo = userInfo { totalBytesDownloaded = userinfo["AGSDownloadProgressTotalBytesDownloaded"] as? NSNumber totalBytesExpected = userinfo["AGSDownloadProgressTotalBytesExpected"] as? NSNumber if(weakSelf.startTimeMapDl == 0) { weakSelf.startTimeMapDl = NSDate().timeIntervalSinceReferenceDate dispatch_async(dispatch_get_main_queue()) { weakSelf.currentDownloadSpeedHeaderLabel.text = "Current D/L Speed:" } } if totalBytesDownloaded != nil && totalBytesExpected != nil { let percentage = totalBytesDownloaded!.doubleValue/totalBytesExpected!.doubleValue dispatch_async(dispatch_get_main_queue()) { weakSelf.progressBar.progress = Float((percentage/2) + 0.5) weakSelf.progressFileSizeLabel.text = "\(NSByteCountFormatter.stringFromByteCount(totalBytesDownloaded!.longLongValue, countStyle:NSByteCountFormatterCountStyle.File)) of \(NSByteCountFormatter.stringFromByteCount(totalBytesExpected!.longLongValue, countStyle:NSByteCountFormatterCountStyle.File))" } let speed = totalBytesDownloaded!.doubleValue / Double((NSDate().timeIntervalSinceReferenceDate - weakSelf.startTimeMapDl)) if(speed != 0) { weakSelf.totalSpeedInBytes += speed weakSelf.numberOfSpeedReadings++ } dispatch_async(dispatch_get_main_queue()) { weakSelf.currentDownloadSpeedLabel.text = "\(NSByteCountFormatter.stringFromByteCount(Int64(speed), countStyle:NSByteCountFormatterCountStyle.File))" } } } } else if errorOccured == false { if status == AGSResumableTaskJobStatus.PreProcessingJob || status == AGSResumableTaskJobStatus.WaitingForDefaultParameters { dispatch_async(dispatch_get_main_queue()) { weakSelf.progressFileSizeLabel.text = "Pre-Processing.." } } if status == AGSResumableTaskJobStatus.StartingJob { dispatch_async(dispatch_get_main_queue()) { weakSelf.progressFileSizeLabel.text = "Starting.." } } if status == AGSResumableTaskJobStatus.Done { dispatch_async(dispatch_get_main_queue()) { if weakSelf.numberOfSpeedReadings != 0 { let averageSpeedInBytes = weakSelf.totalSpeedInBytes / weakSelf.numberOfSpeedReadings if averageSpeedInBytes != 0 { weakSelf.currentDownloadSpeedHeaderLabel.text = "Average D/L Speed:" weakSelf.currentDownloadSpeedLabel.text = "\(NSByteCountFormatter.stringFromByteCount(Int64(averageSpeedInBytes), countStyle:NSByteCountFormatterCountStyle.File))" } else { weakSelf.currentDownloadSpeedHeaderLabel.text = "Average D/L Speed:" weakSelf.currentDownloadSpeedLabel.text = "N/A" } } else { weakSelf.currentDownloadSpeedHeaderLabel.text = "Average D/L Speed:" weakSelf.currentDownloadSpeedLabel.text = "N/A" } } } if status == AGSResumableTaskJobStatus.Polling { dispatch_async(dispatch_get_main_queue()) { weakSelf.progressFileSizeLabel.text = "Acquiring map metadata. This can take several minutes." } } dispatch_async(dispatch_get_main_queue()) { if weakSelf.progressBar.progress < 0.5 { weakSelf.progressBar.progress += 0.01 } } } dispatch_async(dispatch_get_main_queue()) { weakSelf.progressPercentLabel.text = "\(Int(weakSelf.progressBar.progress * 100)) %" } }, completion: { geodatabase, error in if let error = error { print("Error: Could not download the geodatabase from feature service. Error details: \(error)") dispatch_async(dispatch_get_main_queue()) { weakSelf.stopTimer() weakSelf.downloadButton.enabled = true weakSelf.downloadButton.hidden = false weakSelf.cancelDownloadButton.enabled = false weakSelf.cancelDownloadButton.hidden = true weakSelf.progressBar.progress = 0 weakSelf.timeElapsedLabel.text = "00:00:00"; weakSelf.progressFileSizeLabel.text = "0 MB of 0 MB" weakSelf.progressPercentLabel.text = "0 %" weakSelf.currentDownloadSpeedLabel.text = "0 MB" weakSelf.currentDownloadSpeedHeaderLabel.text = "Current D/L Speed:" let alert = UIAlertController(title: "Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the WSDOT Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } return } else { #if DEBUG print("GDB download completed successfully, path is \(geodatabase.path)") #endif let featuresPath = Utility.getDocumentsDirectoryPath() + "/HATS-features.geodatabase" var currentGeodatabaseDeletedOrDoesentExist = false var currentGeodatabaseShmDeletedOrDoesentExist = false var currentGeodatabaseWalDeletedOrDoesentExist = false if( NSFileManager.defaultManager().isReadableFileAtPath(featuresPath)) { do { try NSFileManager.defaultManager().removeItemAtPath(featuresPath) currentGeodatabaseDeletedOrDoesentExist = true } catch { print("Could not delete the current geodatabase file.") } } else { currentGeodatabaseDeletedOrDoesentExist = true } if( NSFileManager.defaultManager().isReadableFileAtPath(featuresPath + "-shm")) { do { try NSFileManager.defaultManager().removeItemAtPath(featuresPath + "-shm") currentGeodatabaseShmDeletedOrDoesentExist = true } catch { print("Could not delete the current geodatabase shm file.") } } else { currentGeodatabaseShmDeletedOrDoesentExist = true } if( NSFileManager.defaultManager().isReadableFileAtPath(featuresPath + "-wal")) { do { try NSFileManager.defaultManager().removeItemAtPath(featuresPath + "-wal") currentGeodatabaseWalDeletedOrDoesentExist = true } catch { print("Could not delete the current geodatabase wal file.") } } else { currentGeodatabaseWalDeletedOrDoesentExist = true } if currentGeodatabaseDeletedOrDoesentExist { if( NSFileManager.defaultManager().isReadableFileAtPath(geodatabase.path)) { do { try NSFileManager.defaultManager().moveItemAtPath(geodatabase.path, toPath: featuresPath) } catch { print("Could not move the downloaded geodatabase to its final path") } } } if currentGeodatabaseShmDeletedOrDoesentExist { if( NSFileManager.defaultManager().isReadableFileAtPath(geodatabase.path + "-shm")) { do { try NSFileManager.defaultManager().moveItemAtPath(geodatabase.path + "-shm", toPath: featuresPath + "-shm") } catch { print("Could not move the downloaded geodatabase shm to its final path") } } } if currentGeodatabaseWalDeletedOrDoesentExist { if( NSFileManager.defaultManager().isReadableFileAtPath(geodatabase.path + "-wal")) { do { try NSFileManager.defaultManager().moveItemAtPath(geodatabase.path + "-wal", toPath: featuresPath + "-wal") } catch { print("Could not move the downloaded geodatabase wal to its final path") } } } Utility.setPathToNotBackupByiCloud(featuresPath) Utility.setPathToNotBackupByiCloud(featuresPath + "-shm") Utility.setPathToNotBackupByiCloud(featuresPath + "-wal") dispatch_async(dispatch_get_main_queue()) { weakSelf.cancelDownloadButton.enabled = false weakSelf.cancelDownloadButton.hidden = true } weakSelf.registerHatsMapFeaturesGdb() } } )
... View more
10-15-2015
01:21 PM
|
0
|
0
|
378
|
POST
|
That one did resume but paused a long wile after network was re-enabled but did eventually continue on. The difference I saw when looking at the code is that it is a different task method: [self.tileCacheTask exportTileCacheWithParameters:params downloadFolderPath:nil useExisting:YES status:^(AGSResumableTaskJobStatus status, NSDictionary *userInfo) { vs generateGeodatbaseWithParameters Let met try again with my code but time leave it up for a couple minutes.
... View more
10-15-2015
01:08 PM
|
0
|
1
|
378
|
POST
|
Thanks for the reply Divesh! I've noticed that most status resume once network picks up or it switches from wifi to cellular for example. I am not seeing the behavior you describe during the fetch result stage. During the fetch result stage if I kill the network access and reenable I don't get status updates again. Here is an example. As you can see in our enterprise app here, the download is going on. I then reach up and kill wifi (my only connection) to simulate a lost of network activity. At 3:30 I went up and reenabled the connection and as you can see the status never fired again because the progress just froze. I already thought about detecting the no transfer for x seconds trick, and that will work if there is not another solution. Our users for this app are not technical GIS users, so we have to code in a lot of error handling and detection so they even know an issue is going on.
... View more
10-15-2015
12:39 PM
|
0
|
3
|
378
|
POST
|
Ok, I have the following code in generateGeodatabaseWithParameters it fires fine and calculates the download speed. The problem I'm having is if a network disruption happens in the AGSResumableTaskJobStatus.FetchingResult status state, I no longer get status updates, and the call never timeouts. So to the user it just looks like their download has frozen forever. I have a cancel button and I can cancel it but I would rather detect the error and let the user knows that the generate process has failed during that step. if status == AGSResumableTaskJobStatus.FetchingResult { if let userinfo = userInfo { totalBytesDownloaded = userinfo["AGSDownloadProgressTotalBytesDownloaded"] as? NSNumber totalBytesExpected = userinfo["AGSDownloadProgressTotalBytesExpected"] as? NSNumber if totalBytesDownloaded != nil && totalBytesExpected != nil { elapsedTime = CACurrentMediaTime() - weakSelf.startTimeMapDl elapsedSeconds = UInt(elapsedTime) if elapsedSeconds > 0 && elapsedSeconds != previousSeconds { var bytesPerSecond = UInt(0) if previousSeconds == 0 { dispatch_async(dispatch_get_main_queue()) { weakSelf.currentDownloadSpeedHeaderLabel.text = "Current D/L Speed:" } bytesPerSecond = totalBytesDownloaded!.unsignedLongValue / elapsedSeconds } else { bytesPerSecond = (totalBytesDownloaded!.unsignedLongValue - previousBytesDownloaded.unsignedLongValue ) / (elapsedSeconds - previousSeconds ) } //dl speed bounced between 0 and some other number if checked every second, so spreading it out over 3 seconds //for a better UI experience. It still bounces around, but not as much. let secondsDifference = elapsedSeconds - previousSeconds if secondsDifference > 1 && previousBytesDownloaded.unsignedLongValue != totalBytesDownloaded!.unsignedLongValue { dispatch_async(dispatch_get_main_queue()) { weakSelf.currentDownloadSpeedLabel.text = "\(NSByteCountFormatter.stringFromByteCount(Int64(bytesPerSecond), countStyle:NSByteCountFormatterCountStyle.File))" } previousBytesDownloaded = totalBytesDownloaded! previousSeconds = elapsedSeconds } } } } } For other status states if there is an error I get a error message in the user info, but that does not populate or fire in the fetching result stage. This at the top of the method call detects network errors for all states, but since FetchingResults never calls back, it can't run. weakSelf.agsResumableTaskJob = weakSelf.gdbSyncTask?.generateGeodatabaseWithParameters(params, downloadFolderPath: nil, useExisting: false, status: { status, userInfo in if let userinfo = userInfo { if let error = userinfo["statusRequestError"] { print("Error: Could not generate geodatabase. Error details:\(error)") errorOccured = true weakSelf.agsResumableTaskJob?.cancel() if error.localizedDescription == "The Internet connection appears to be offline." { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Network Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } else if error.localizedDescription == "A server with the specified hostname could not be found." { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Network Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } else { dispatch_async(dispatch_get_main_queue()) { let alert = UIAlertController(title: "Error", message: "Could not download the map inventory.\r\n\r\nPlease verify you are connected to the Network and try again.", preferredStyle: UIAlertControllerStyle.Alert) alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)) weakSelf.presentViewController(alert, animated: true, completion: nil) } } } } Using the latest sdk build (10.2.5)
... View more
10-14-2015
06:00 PM
|
0
|
5
|
2164
|
POST
|
This crash bug appears to be fixed by apple in Beta 4, which was released today.
... View more
07-21-2015
12:34 PM
|
0
|
2
|
595
|
POST
|
I also had added a bug report to apple on this issue. They asked the following, may be worth to pass on to development: We need more information to investigate this issue. It looks like the pointer is being passed directly from the app to pthread_mutex_init (nothing changes x0 before this stlr) and is misaligned (because it contains a pointer it should be 64-bit aligned, but it’s not: 0x12cd07564 == 4 (mod 8)) That address looks like it might be somewhere in the heap to us. How are you obtaining the pthread_mutex_t pointer that you pass in?
... View more
07-20-2015
04:51 PM
|
0
|
0
|
595
|
POST
|
I can confirm here at WSDOT that our app, using the latest ESRI iOS SDK, crashes on iOS 9 beta 3, but only on device. Have tested on a iPad Mini 2 and an Air 2. Works fine in simulator so we can continue to make changes and test for IOS 9 support for now.
... View more
07-20-2015
04:49 PM
|
0
|
1
|
595
|
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:25 AM
|