NativeScript / ios-jsc

NativeScript for iOS using JavaScriptCore
http://docs.nativescript.org/runtimes/ios
Apache License 2.0
299 stars 59 forks source link

Metadata for "Google2.kGAIScreenName" found but symbol not available at runtime. #543

Closed sitefinitysteve closed 8 years ago

sitefinitysteve commented 8 years ago

@manijak is trying to publish an app to iTunes Connect, but it's tanking on the GoogleAnalytics plugin with the {N} runtime.

https://github.com/NativeScript/ios-runtime/blob/master/src/NativeScript/GlobalObject.mm#L319

file:///app/tns_modules/nativescript-google-analytics/index.js:14:91: JS ERROR ReferenceError: Metadata for "Google2.kGAIScreenName" found but symbol not available at runtime.

Any idea what might be happening here, can you guys replicate at all? It seems to be blocking a new {N} app in the app store

https://www.npmjs.com/package/nativescript-google-analytics

manijak commented 8 years ago

I am using version 1.7.0 of the runtime. I did not see any issues or crashes when running the app in debug on simulator or device. Also ran the app with the --release flag, still all normal. But after deploying the app to iTunes & TestFlight, it crashes on every view where I have used googleAnalytics plugin.

Version 1.0 of the app was approved for appstore release, but I rejected it since I wanted the analytics implemented on launch. After adding the plugin, all later builds (5 of them) where rejected.

manijak commented 8 years ago

Ok, I seem to have found a temporrary fix for the issue. We'll se what Apple has to say...

Line 14 in the index.ios.js of the plugin, changed to this:

var event = GAIDictionaryBuilder.createScreenView().setForKey(viewname, "&cd");

The last parameter, "&cd" is same as kGAIScreenName, it's called a "measurement protocol" equal to the http query tags for google analytics.

App worked with this fix. And on top of that it passed the TestFlight on iTunesConnect! Waiting for review now...

jasssonpet commented 8 years ago

Hello @manijak ,

I'm glad that you found a workaround for your problem. Indeed, hardcoding the value of the constant would fix the problem, but let me tell you what's happening here.

It seems that the Google Analytics SDK is distributed as a static library. You can see some of the limitations of static libraries described in the docs.

Most notably this one:

Some C symbols are stripped and can not be used dynamically from JavaScript.

This includes all C functions and variables. You can try setting the following linker flag in the build.xcconfig of the plugin to force the linker to preserve the symbol in the binary, but it's still not guaranteed that the symbol will get linked.

OTHER_LDFLAGS = -force_load $(PODS_ROOT)/GoogleAnalytics/Libraries/libGoogleAnalytics.a -Wl,-exported_symbol,_kGAIScreenName

This a limitation that we are well aware of and we are looking for ways to ease the use of static libraries. We have thoughts about statically analyzing the JavaScript code and generating such flags automatically. Let us know what are your thoughts on this 😄

P.S To see all exported symbols from the library you can run the following command: nm platforms/ios/build/device/YourApp.app/YourApp | grep kGAI. You can see that they are there in debug and release configurations, but if you archive the application from Xcode you'll see that the list is empty.

manijak commented 8 years ago

Hi @jasssonpet , Thanks for the explanation, didn't realize at first that this had anything to do with static libraries. Didn't understand why it worked in debug and on device with the "--release" flag.

Really glad there was an alternative I could use, needed to get the app released.

I guess this would probably affect the entire Google SDK, not just the analytics library. Good to know if we decide to implement GCM for iOS in the push-notifications plugin...

manijak commented 8 years ago

@jasssonpet , @sitefinitysteve Guys, it seems there is something more here. My app did pass the TestFlight init, but testers are reporting that the app crashes at launch on iPhone 4s and iPad 2 (older devices). Works just fine on iPhone 5s and up (newer).

I managed to get a hold of a few crash reports, is it safe to post it here so that you can take a look at? I did not understand anything from the log, since it does not point to any part of my code.

This is the last part of all crash reports:

NativeScript::toValue(JSC::ExecState*, objc_object*, objc_class*) + 184
manijak commented 8 years ago

UPDATE: Below is the link to one of the crash-logs. Both devices that crash are on iOS 9.3.1. The app was build and released using XCode 7.2.1 and iOS 9.2

https://dl.dropboxusercontent.com/u/33168380/2016-04-07_22-30-17.17_%2B0200-4fafbf1908ebfdce13d711036c591bc12e8e058a.crash

jasssonpet commented 8 years ago

Hey @manijak,

There isn't much to be seen from the crash log, but it seems that their is a message call to a deallocated instance, that is no longer valid. Can you try running your app with zombies enabled? This should report any memory corruptions and would probably report errors even if the app was running correctly on the device. Let me know if this works.

manijak commented 8 years ago

@jasssonpet , @sitefinitysteve

I managed to debug the app on a iPad2 device (apps fail here). And it is for sure Google-Analytics related. I removed everything GA in my app and re-ran it. The app ran just fine, no errors.

Included GA again, only added one "analytics.logView(...)" method in a sub-view (so that I can tap inn after the app has fully loaded). Ran the app on device again, in debug, and it crashed on tap (view fully loaded).

I've added the crash from xcode in the link below, have no idea how to export this to a file, so I just took a screenshot. All of this is very cryptic to me, nothing makes sense in the stack trace... :)

Here is the output from the debug:

2016-04-08 16:47:14.547 fkzeljoapp[489:] <GMR/INFO> App measurement v.2003000 started
2016-04-08 16:47:14.558 fkzeljoapp[489:] <GMR/INFO> To enable debug logging set the following application argument: -GMRDebugEnabled (see http://goo.gl/Y0Yjwu)
2016-04-08 16:47:15.589 fkzeljoapp[489:] <GMR/INFO> App measurement enabled
2016-04-08 16:47:27.930 fkzeljoapp[489:87406] void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode

warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.

https://dl.dropboxusercontent.com/u/33168380/ipad2_crash.png

Why should there be any difference between iPhone 4s/iPad2 and the rest? 64bit contra 32bit?

sitefinitysteve commented 8 years ago

Issue related to the {N} Protocol implimentation, fixed in 1.7 https://groups.google.com/d/msg/nativescript/lzGP7QdXI7E/6ZqCf0_tDwAJ

ignaciolarranaga commented 7 years ago

@sitefinitysteve / @jasssonpet I have a similar issue with Admob (https://github.com/EddyVerbruggen/nativescript-admob/issues/19) but the plugin owner already added instructions to preserve the symbols (https://github.com/EddyVerbruggen/nativescript-admob/blob/master/platforms/ios/build.xcconfig). But unfortunately it still does not have the symbols after being published.

I get this error on runtime after download the app from the store: "There was an error creating the AdMob banner: ReferenceError: Metadata for \"GoogleMobileAds.kGADAdSizeBanner\" found but symbol not available at runtime."

Some additional suggestion that I might use ?