NativeScript Cheat Sheet & Tips
September 1, 2017
I worked on a multi-year project for a platform that delivered online education to thousands of students each year. For those students using mobile iOS/Android platforms, we provided a NativeScript application that used a blended web-and-native experience to deliver content to students.
NativeScript (like any write-once-run-anywhere mobile solution) definitely gets trickier as the abstraction leaks to reveal Android/iOS-specific issues, but if you build a base-layer of platform specific knowledge, you can get quite far.
I learned a bit along the way, and want to share with you!
Troubleshooting: It's broken and I have no idea what is wrong
NativeScript app builds can be finnicky. There's a lot of moving pieces necessary to construct your app. Sometimes, things get out-of-whack. It's a scientific thing.
Here's my favorite bash-script recipe to obtaining a "clean slate" on which to verify that your random, weird little problem is truly a persistent one worth wringing hands about:
rm -rf hooks/
rm -rf node_modules/
rm -rf platforms/
tns platform remove android || true
tns platform remove ios || true
tns platform add ios
tns platform add android
# Carry out builds just to see if they work!
tns build ios
tns build android
Troubleshooting: Type 'X' is not assignable to type 'X'
You've somehow managed to pass an object of type X that is actually of a different "version" than the thing
you're assigning to. A TypeScript issue that typically pops up in conflict with
To debug, figure out what package type X belongs to, and run
npm list to locate the package and see where
it is duplicated – you'll likely find the package listed twice under different version numbers.
You can then use
package.json to pin to a specific version you prefer. If the conflict is with a
related package, it's advised that you let the
nativescript-* package version preference win.
Profiling memory on Android
You'll want to read a primer, first: Android Performance - The Why and The How
You'll need to use the Android device emulator, NOT Genymotion.
Here are the general steps to getting started with profiling
tns build android
- (Install) and run Android Studio, and use it to start the emulator (don't worry about opening your project)
adb install platforms/android/build/outputs/apk/your-file-here-debug.apk(replace
your-file-here-!) in your NativeScript project directory
- Now, in Android Studio, look for the dropdown to select your running app
- Finally, select a monitor (e.g. Memory Monitor)
Troubleshooting: Podfile-related errors
tns prepare ios --release, and then open the
platforms/ios/*.xcworkspace (replace the
file in XCode, then launch using the Play button. This usually works, and magically fixes the issue for
subsequent calls to
tns run ios.
Profiling iOS memory usage and debugging memory leaks
While you cannot set a "maximum memory" threshold in the simulator, you can profile memory usage using Instruments. Instruments is a bit funky and may sometimes require you to force-kill it; sometimes, it refuses to show profiling results, or menu options disappear!
To start, you can trigger a "low memory warning" using Instrument > Simulate Memory Warning. This triggers garbage collection, which should flatten out your memory usage to mostly-just-what's-really-being-used. It's a good way to verify memory is actually leaking.
To start profiling, launch the Instruments app while the iOS simulator is running. Near "Choose a profiling template for:", select the emulator and then the running app.
You can use Allocations profiling to monitor object allocations. You must select some sort of statistic to gather, click record, carry out some app activity you want to profile, and then stop recording to see results.
To find leaks, watch "Persistent bytes" – that is, what was allocated, but not de-allocated. Repeat the same activity that you think is causing the memory leak, and then see if Persistent bytes becomes a line (i.e. stops growing) or continues unbounded growth over time.
For more information:
- Using Instrument - https://spin.atomicobject.com/2016/01/25/ios-memory-leak-xcode/
- Memory limits - http://stackoverflow.com/questions/5887248/ios-app-maximum-memory-budget/15200855#15200855
- Clean vs. dirty memory - http://stackoverflow.com/questions/13437365/what-is-resident-and-dirty-memory-of-ios
Debugging iOS segfaults
Service exited due to Segmentation fault: 11 when running Simulator.
You will need to go to
~/Library/Logs/DiagnosticReports/ and find the most recent crash report.
This will include a full stack trace with debug symbols that may help you trace the problem back to
what is causing the segfault.
Segfault code 11 is a memory access problem – for example, accessing deallocated memory. You've potentially uncovered a NativeScript bug in its native interface code – e.g. using components in a way they were not intended to be used, and/or using certain methods at the wrong point in their lifecycle.
Troubleshooting: "tns publish ios" fails with "Your app can’t contain standalone executables or libraries"
Same as this problem. You can use
filter-modules.json to remove the problematic module – though be sure your app
still works afterward!
Genymotion makes development easy
Starting with the vanilla Android emulator gets you started, but can become frustrating from two perspectives:
- It's a bit slow
- It's tricky (or near impossible) to use a local
dnsmasqconfiguration so that your virtual Android instance can connect back to a custom Vagrant-exposed API that lives on its own virtual interface and IP – you can perhaps get this working with the Android emulator
-dns-serverflag, but as of writing, it's not clear how to do this in conjunction with
Genymotion is pretty fast, and seems to be using NAT via your host machine – for me,
it simply used my local
dnsmasq server configuration, so I could easily access
my favorite local-only
*.test hostnames that pointed back to running
instances of my API.
By Daniel Starling
Software consultant in Portland, OR
Software consultant in Portland, OR