[TIMOB-24740] iOS - Unable to use Mapbox SDK (third-party framework) with Hyperloop
| GitHub Issue | n/a |
|---|---|
| Type | Bug |
| Priority | Critical |
| Status | Closed |
| Resolution | Not Our Bug |
| Resolution Date | 2017-08-08T08:25:34.000+0000 |
| Affected Version/s | n/a |
| Fix Version/s | n/a |
| Components | Hyperloop |
| Labels | Hyperloop, appcelerator, ios, mapbox, thirdparty |
| Reporter | La Fabrik |
| Assignee | Eric Merriman |
| Created | 2017-05-25T21:47:44.000+0000 |
| Updated | 2017-08-23T18:19:14.000+0000 |
Description
Hi,
I'm trying to use Hyperloop to integrate the mapbox framework to my app, but it is not working.
After following the appcelerator's guide for include third-party framework to ios, when I run the app on the ios simulator, the app crashes and I got a crash report (see attachments).
step to reproduce :
-create a new project in appcelerator using the default alloy project with hyperloop enabled.
-download the Mapbox iOS sdk at http://mapbox.s3.amazonaws.com/mapbox-gl-native/ios/builds/mapbox-ios-sdk-3.5.4-dynamic.zip
-Unzip and place the Mapbox.framework file in "src" folder in the project's root directory
-I add an appc.js file on the project's root directory with those lines :
module.exports = {
hyperloop: {
ios: {
xcodebuild: {
flags: {
FRAMEWORK_SEARCH_PATHS: '../../src',
LD_RUNPATH_SEARCH_PATHS: '@executable_path'
},
frameworks: [
'Mapbox'
]
},
thirdparty: {
'Mapbox': {
source: ['src'],
header: 'src',
resource: 'src'
}
}
}
}
};
-Add the "MGLMapboxAccessToken" key in the tiapp.xml
-Edit the index.js controler :
function doClick(e) {
alert($.label.text);
}
var MGLMapView = require('Mapbox/MGLMapView');
var map = new MGLMapView();
$.index.add(map);
$.index.open();
-run the app on iOS simulator
Attachments
| File | Date | Size |
|---|---|---|
| mapboxtest_2017-05-26-084428_Julien.crash | 2017-05-25T21:45:56.000+0000 | 16203 |
Hello @emerriman , Have you got some news? Thanks,
Just a general note for who ever is working on this. This problem is because Hyperloop doesn't support embedded binaries. I was able to get Mapbox to work using some modification to ti.dynamiclib....
Hello @Dee Clawson Thanks for the reply, I already tried this solution but without success, can you post an example please?
Hey La Fabrik, Sorry no, our code contains some trade secrets. When ti.dynamiclib is properly modified it works perfect though, best of luck. I would suggest getting Matise's module to work first. https://github.com/MatiseAms/ti-mapbox-gl Once you understand it and how he set up dynamiclib it is pretty easy to get working.
Actually here you go:
module.exports = { hyperloop: { ios: { xcodebuild: { flags: { FRAMEWORK_SEARCH_PATHS: '../../src', LD_RUNPATH_SEARCH_PATHS: '$(inherited) "@executable_path/Frameworks" $(FRAMEWORK_SEARCH_PATHS)' } }, thirdparty: { 'Mapbox': { source: ['src'], header: 'src', resource: 'src' } } } } };if (!Array.prototype.last) { Object.defineProperty(Array.prototype, 'last', { value: function() { return this[this.length - 1]; } }); } exports.id = 'ti.dynamiclib'; exports.cliVersion = '>=3.2'; exports.init = function (logger, config, cli, appc) { cli.on('build.ios.xcodeproject', { pre: function (data) { // Replace the following variables with your framework / script: // --- var scriptPath = null; '../../src/Mapbox.framework/strip-frameworks.sh'; //'<path-to-strip-frameworks-script>/strip-frameworks.sh'; // Or set to null if not required var frameworkPaths = [ '../../src/Mapbox.framework' ]; // --- var builder = this; var xcodeProject = data.args[0]; var xobjs = xcodeProject.hash.project.objects; if (typeof builder.generateXcodeUuid !== 'function') { var uuidIndex = 1; var uuidRegExp = /^(0{18}\d{6})$/; var lpad = appc.string.lpad; Object.keys(xobjs).forEach(function (section) { Object.keys(xobjs[section]).forEach(function (uuid) { var m = uuid.match(uuidRegExp); var n = m && parseInt(m[1]); if (n && n > uuidIndex) { uuidIndex = n + 1; } }); }); builder.generateXcodeUuid = function generateXcodeUuid() { return lpad(uuidIndex++, 24, '0'); }; } addLibrary(builder, cli, xobjs, frameworkPaths); addScriptBuildPhase(scriptPath); } }); }; function addLibrary(builder, cli, xobjs, frameworkPaths) { if (!frameworkPaths || frameworkPaths.length == 0) { return; // Skip if no frameworks are specified } frameworkPaths.forEach(function (framework_path) { var framework_name = framework_path.split('/').last(); // B6CE2C7E1C90C08400B37C55 var frameword_uuid = builder.generateXcodeUuid(); // B6CE2C7F1C90C08400B37C55 var embeddedFrameword_uuid = builder.generateXcodeUuid(); // B6CE2C7D1C90C08400B37C55 var fileRef_uuid = builder.generateXcodeUuid(); // B6CE2C801C90C08400B37C55 var embeddedFrameword_copy_uuid = builder.generateXcodeUuid(); createPBXBuildFile(xobjs, frameword_uuid, fileRef_uuid, embeddedFrameword_uuid, framework_name); createPBXCopyFilesBuildPhase(xobjs, embeddedFrameword_copy_uuid, embeddedFrameword_uuid, framework_name); createPBXFileReference(xobjs, fileRef_uuid, framework_path, framework_name); createPBXFrameworksBuildPhase(xobjs, frameword_uuid, framework_name); createPBXGroup(xobjs, fileRef_uuid, framework_name); createPBXNativeTarget(xobjs, embeddedFrameword_copy_uuid); }); } function addScriptBuildPhase(scriptPath) { if (!scriptPath) return; var script_uuid = builder.generateXcodeUuid(); var shell_path = '/bin/sh'; var shell_script = 'bash \"' + scriptPath + '\"'; createPBXRunShellScriptBuildPhase(xobjs, script_uuid, shell_path, shell_script); createPBXRunScriptNativeTarget(xobjs, script_uuid); } function createPBXBuildFile(xobjs, frameword_uuid, fileRef_uuid, embeddedFrameword_uuid, framework_name) { /** * // <YourFramework>.framework in Frameworks * B6CE2C7E1C90C08400B37C55 = { * isa = PBXBuildFile; * // <YourFramework>.framework * fileRef = B6CE2C7D1C90C08400B37C55 * }; */ xobjs.PBXBuildFile[frameword_uuid] = { isa: 'PBXBuildFile', fileRef: fileRef_uuid, fileRef_comment: framework_name + ' in Frameworks' }; xobjs.PBXBuildFile[frameword_uuid][frameword_uuid + '_comment'] = framework_name + ' in Frameworks'; /** * // <YourFramework>.framework in Embed Frameworks * B6CE2C7F1C90C08400B37C55 = { * isa = PBXBuildFile; * // <YourFramework>.framework * fileRef = B6CE2C7D1C90C08400B37C55 * settings = { * ATTRIBUTES = [CodeSignOnCopy, RemoveHeadersOnCopy] * } * } */ xobjs.PBXBuildFile[embeddedFrameword_uuid] = { isa: 'PBXBuildFile', fileRef: fileRef_uuid, fileRef_comment: framework_name + ' in Embed Frameworks', settings: { ATTRIBUTES: ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] } }; xobjs.PBXBuildFile[embeddedFrameword_uuid][embeddedFrameword_uuid + '_comment'] = 'MyFramework in Embed Frameworks'; } function createPBXCopyFilesBuildPhase(xobjs, embeddedFrameword_copy_uuid, embeddedFrameword_uuid, framework_name) { /** * B6CE2C801C90C08400B37C55 = { * isa = PBXCopyFilesBuildPhase; * buildActionMask = 2147483647; * dstPath = ""; * dstSubfolderSpec = 10; * files = ( * // <YourFramework>.framework in Embed Frameworks * B6CE2C7F1C90C08400B37C55, * ); * name = "Embed Frameworks"; * runOnlyForDeploymentPostprocessing = 0; * }; */ xobjs.PBXCopyFilesBuildPhase = xobjs.PBXCopyFilesBuildPhase || {}; xobjs.PBXCopyFilesBuildPhase[embeddedFrameword_copy_uuid] = { isa: 'PBXCopyFilesBuildPhase', buildActionMask: '2147483647', dstPath: '""', dstSubfolderSpec: '10', files: [{ value: embeddedFrameword_uuid + '', comment: framework_name + ' in Embed Frameworks' }], name: '"Embed Frameworks"', runOnlyForDeploymentPostprocessing: 0 }; } function createPBXFileReference(xobjs, fileRef_uuid, framework_path, framework_name) { /** * B6CE2C7D1C90C08400B37C55 = { * isa = PBXFileReference; * lastKnownFileType = wrapper.framework; * name = <YourFramework>.framework; * path = ../../modules/iphone/com.janx.wowza/1/platform/<YourFramework>.framework; * sourceTree = "<group>"; * }; */ xobjs.PBXFileReference[fileRef_uuid] = { isa: 'PBXFileReference', lastKnownFileType: 'wrapper.framework', name: framework_name, path: framework_path, sourceTree: '"<group>"' }; } function createPBXFrameworksBuildPhase(xobjs, frameword_uuid, framework_name) { /** * 1D60588F0D05DD3D006BFB54 = { * isa = PBXFrameworksBuildPhase; * buildActionMask = 2147483647; * files = ( * // MyFramework in Frameworks * B6CE2C7E1C90C08400B37C55, * more stuff * ); * }; */ for (var key in xobjs.PBXFrameworksBuildPhase) { xobjs.PBXFrameworksBuildPhase[key].files.push({ value: frameword_uuid + '', comment: framework_name + ' in Frameworks' }); return; } } function createPBXGroup(xobjs, fileRef_uuid, framework_name) { for (var key in xobjs.PBXGroup) { if (xobjs.PBXGroup[key].name == 'Frameworks') { xobjs.PBXGroup[key].children.push({ value: fileRef_uuid, comment: framework_name }); return; } } } function createPBXNativeTarget(xobjs, embeddedFrameword_copy_uuid) { for (var key in xobjs.PBXNativeTarget) { xobjs.PBXNativeTarget[key].buildPhases.push({ value: embeddedFrameword_copy_uuid + '', comment: 'Embed Frameworks' }); return; } } function createPBXRunShellScriptBuildPhase(xobjs, script_uuid, shell_path, shell_script){ xobjs.PBXShellScriptBuildPhase = xobjs.PBXShellScriptBuildPhase || {}; xobjs.PBXShellScriptBuildPhase[script_uuid] = { isa: 'PBXShellScriptBuildPhase', buildActionMask: '2147483647', files: '(\n)', inputPaths: '(\n)', outputPaths: '(\n)', runOnlyForDeploymentPostprocessing: 0, shellPath: shell_path, shellScript: JSON.stringify(shell_script) }; } function createPBXRunScriptNativeTarget(xobjs, script_uuid) { for (var key in xobjs.PBXNativeTarget) { xobjs.PBXNativeTarget[key].buildPhases.push({ value: script_uuid + '', comment: 'Run Script Phase' }); return; } }Hey La Fabrik, I did you one better. I have made an example iOS project with it working. https://github.com/kdclaw3/hyperloop-mapbox
hi @Dee Clawson, Oh thank you, I'll try it asap!
Resolving issue since this was no Titanium related issue. Side-note: Hyperloop 2.2.0 and SDK 6.2.0 will have core-support for dynamic libraries, so hook won't be necessary anymore.
Closing ticket with regards to the above observations.