I was wondering if anyone else is actually trying to utilize mmpk files in their iOS apps. I've seen very little documentation on the feature, and I've not been able to successfully utilize it, yet.
I looked at the documentation here:
Display a map—ArcGIS Runtime SDK for iOS (Quartz Beta) | ArcGIS for Developers
and then generated the mmpk file as "mobile.mmpk" using ArcGIS Pro 1.2.0:
arcpy.management.CreateMobileMapPackage(...)
My ViewController (in Swift) looks like:
import UIKit
import ArcGIS
class ArcGisViewController: UIViewController {
@IBOutlet var mapView: AGSMapView!
override func viewDidLoad() {
super.viewDidLoad()
print("creating map")
createMap()
}
func createMap() {
if let filepath = NSBundle.mainBundle().pathForResource("mobile", ofType:"mmpk") {
print("found map")
let mobileMapPackage = AGSMobileMapPackage(path: filepath)
mobileMapPackage.loadWithCompletion { (error) -> Void in
if let error = error {
print(error.localizedDescription)
}
else {
// In this case the first map in the array is obtained
print ("setting map")
print("The mobile map package contains \(mobileMapPackage.maps.count) maps")
self.mapView.map = mobileMapPackage.maps[0]
}
}
}
}
}
However, when I run the program, I get a crash from what appears to be an invalid thread execution.
The log prints normally right up to the crash (showing that I have 1 map in the mmpk file).
The error is on the highlighted line.
I'm attaching screenshot of the debugger. Has anyone else successfully utilized a mmpk file? Is there a sample somewhere that gives a working example?
Thanks in advance,
-Glenn
Can you provide the backtrace?
To get the backtrace simply type `bt` in the Debugger and hit Enter (when the application has crashed). Copy and paste the stub here.
Sure:
(lldb) bt
* thread #12: tid = 0xa3b9b, 0x000000010f91e45c libsystem_pthread.dylib`pthread_mutex_lock, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=1, address=0x560)
* frame #0: 0x000000010f91e45c libsystem_pthread.dylib`pthread_mutex_lock
frame #1: 0x000000010a56398f libc++.1.dylib`std::__1::mutex::lock() + 9
frame #2: 0x0000000106f985ab TransPatrol`Esri_runtimecore::Mapping::Geodatabase_feature_table::load_sync() + 171
frame #3: 0x000000010714d6b4 TransPatrol`std::__1::__function::__func<Esri_runtimecore::Mapping::Task<void>::Task<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86>(Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86, pplx::cancellation_token_source)::'lambda'(), std::__1::allocator<Esri_runtimecore::Mapping::Task<void>::Task<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86>(Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86, pplx::cancellation_token_source)::'lambda'()>, boost::any ()>::operator()() + 52
frame #4: 0x0000000107174b91 TransPatrol`std::__1::__function::__func<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502, std::__1::allocator<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502>, boost::any ()>::operator()() + 177
frame #5: 0x00000001071745b1 TransPatrol`pplx::details::_PPLTaskHandle<boost::any, pplx::task<boost::any>::_InitialTaskHandle<boost::any, Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502, pplx::details::_TypeSelectorNoAsync>, pplx::details::_TaskProcHandle>::invoke() const + 369
frame #6: 0x00000001071e3703 TransPatrol`pplx::details::_TaskProcHandle::_RunChoreBridge(void*) + 19
frame #7: 0x00000001065ea559 TransPatrol`Esri_runtimecore::Common::Constrained_scheduler::bridge_proc(void*) + 41
frame #8: 0x000000010f5e33eb libdispatch.dylib`_dispatch_client_callout + 8
frame #9: 0x000000010f5cbb2f libdispatch.dylib`_dispatch_root_queue_drain + 1829
frame #10: 0x000000010f5cb405 libdispatch.dylib`_dispatch_worker_thread3 + 111
frame #11: 0x000000010f9204de libsystem_pthread.dylib`_pthread_wqthread + 1129
frame #12: 0x000000010f91e341 libsystem_pthread.dylib`start_wqthread + 13
(lldb)
It seems like a known issue. As a work around can you make sure there are no empty or non visible layers when creating a mmpk?
Interesting. I exported a secondary file, and deleted all unused layers, and made the rest of the layers that had been previously selected as non-visible to visible.
Running the code with the new mmpk still generates an error:
creating map
found map
setting map
The mobile map package contains 1 maps
(lldb) bt
* thread #4: tid = 0xc7e0a, 0x000000011514545c libsystem_pthread.dylib`pthread_mutex_lock, queue = 'com.apple.root.default-qos', stop reason = EXC_BAD_ACCESS (code=1, address=0x560)
* frame #0: 0x000000011514545c libsystem_pthread.dylib`pthread_mutex_lock
frame #1: 0x000000010fd8a98f libc++.1.dylib`std::__1::mutex::lock() + 9
frame #2: 0x000000010c7bf5ab TransPatrol`Esri_runtimecore::Mapping::Geodatabase_feature_table::load_sync() + 171
frame #3: 0x000000010c9746b4 TransPatrol`std::__1::__function::__func<Esri_runtimecore::Mapping::Task<void>::Task<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86>(Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86, pplx::cancellation_token_source)::'lambda'(), std::__1::allocator<Esri_runtimecore::Mapping::Task<void>::Task<Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86>(Esri_runtimecore::Mapping::Geodatabase_feature_table::load_or_retry_(Esri_runtimecore::Mapping::Loadable::Load_or_retry_mode)::$_86, pplx::cancellation_token_source)::'lambda'()>, boost::any ()>::operator()() + 52
frame #4: 0x000000010c99bb91 TransPatrol`std::__1::__function::__func<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502, std::__1::allocator<Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502>, boost::any ()>::operator()() + 177
frame #5: 0x000000010c99b5b1 TransPatrol`pplx::details::_PPLTaskHandle<boost::any, pplx::task<boost::any>::_InitialTaskHandle<boost::any, Esri_runtimecore::Mapping::Task_implementation::Task_implementation(std::__1::function<boost::any ()>, pplx::cancellation_token_source)::$_502, pplx::details::_TypeSelectorNoAsync>, pplx::details::_TaskProcHandle>::invoke() const + 369
frame #6: 0x000000010ca0a703 TransPatrol`pplx::details::_TaskProcHandle::_RunChoreBridge(void*) + 19
frame #7: 0x000000010be11559 TransPatrol`Esri_runtimecore::Common::Constrained_scheduler::bridge_proc(void*) + 41
frame #8: 0x0000000114e0a3eb libdispatch.dylib`_dispatch_client_callout + 8
frame #9: 0x0000000114df2b2f libdispatch.dylib`_dispatch_root_queue_drain + 1829
frame #10: 0x0000000114df2405 libdispatch.dylib`_dispatch_worker_thread3 + 111
frame #11: 0x00000001151474de libsystem_pthread.dylib`_pthread_wqthread + 1129
frame #12: 0x0000000115145341 libsystem_pthread.dylib`start_wqthread + 13
(lldb)
In that case would it be possible for you to share the mmpk?
I can't share that particular mmpk. Let me export another mmpk without the proprietary information and verify that the error is still there. If it is, I'll upload it for your verification. I'll respond back regardless.
I'm having a hard time trying to figure out exactly what to send. My map has six layers, all of which are simple feature classes. Some are polylines and some are points. I've had success exporting just the points, and just the individual polylines, however, if I group the polylines in a layer group, or if I include both the polylines and the points, the resultant mmpk file crashes.
In addition, the working mmpk files are imposing a background that I don't think I defined. I don't have a basemap layer in the mmpk, and my assumption is that the layers would draw on top of the background color defined for the view. However, the SDK is drawing a black background instead.
I'm continuing to try and experiment so I can give you a file to play with, but until then, if you think of other suggestions, please let me know.
>however, if I group the polylines in a layer group, or if I include both the polylines and the points, the resultant mmpk file crashes.
This would be enough for us to investigate. Can you provide a mmpk for each case?
>In addition, the working mmpk files are imposing a background that I don't think I defined. I don't have a basemap layer in the mmpk, and my assumption is that the layers would draw on top of the background color defined for the view. However, the SDK is drawing a black background instead.
Your assumption is correct. There may be a bug which is turning the background black. Can you provide this mmpk too?
I'm not sure if you can PM on here, but if you can, let me know and I'll see about getting a couple of mmpks to you to work with.