Background Location Update in iOS 11

In iOS 11, CoreLocation has some changes including the showsBackgroundLocationIndicator property, a new Info.plist key : NSLocationAlwaysAndWhenInUseUsageDescription.

To suppor iOS 11, there are two keys for location service.

  1. NSLocationWhenInUseUsageDescription
  2. NSLocationAlwaysAndWhenInUseUsageDescription
  3. NSLocationAlwaysUsageDescription (support iOS 10 device or below)

Apple encourages developers to use location service more in foreground than in background, and gives users a clearer understanding of when and how the location service is used.

The arrow indicator of location service

  • stays hollow when device is either monitoring geofences or using significant location service.
  • stays solid when device receives location updates

The mechanism of CL Location Manager has been changed. There are some reports showing that apps can no longer receive background updates. During my testing on iOS 11.2.2, I found out the following scenarios work.

  1. Significant location service work in both foreground, background, and even user kills the App, it will wake up.
  2. Standard location service doesn’t start when the App is in the background. However, if the App also registers significant location service, standard location service is able to start in the background, even the App has been killed manually by users and significant location service launches the App before starting standard location service. (This requires UIBackgroundMode is set with Location Update).
  3. Entering geofences will give the App 10 seconds of execution time. During that time, the App can launch standard location service.
// setting up location manager

locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation // accuracy enhanced by sensor data

locationManager.pausesLocationUpdatesAutomatically = false // or true depends on you

locationManager.distanceFilter = 5 // how you want to receive the updates, every 5 meters? In real situation, it may report less than 5 meters!

if #available(iOS 11.0, *) {
    locationManager.showsBackgroundLocationIndicator = true // show users when standard location service is activated, good for debugging.

locationManager.allowsBackgroundLocationUpdates = true //  necessary to make standard location service work in background

locationManager.requestAlwaysAuthorization() // request permission

locationManager.startMonitoringSignificantLocationChanges() // crucial to start standard location service in background

// start standard location service when user enters a geofence
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {


I’ve tested the code on iPhone X iOS 11.2.2.
If you want to share test results on other devices, please do so! Thanks!


How to create iOS fat dynamic framework

“Fat” means that this framework has many slices. Each slice (machine code) is built for certain architecture. The fat framework we are going to build contains i386 x86_64 armv7 armv7s arm64.

  • armv7 is for iPhone 4s
  • armv7s is for iPhone 5
  • arm64 is for iPhone 6

Firstly we need to create a target for dynamic framework: Cocoa Touch Framework

Secondly we create a new target: External Build System

Go to Build Phases -> Run script

Paste the below code snippet in there


# make sure the output directory exists
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to desktop directory
ditto "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${HOME}/Desktop/${PROJECT_NAME}.framework"

Build it then your fat dynamic framework will be located on your desktop! Before submitting the App to AppStore, you must strip off the simulator slice (i386 x86_64) from the framework

lipo -remove i386 Name.framework/Name -output Path/name

lipo -remove x86_64 Name.framework/Name -output Path/name

Or you can refer to this solution:


IBM Bluemix MobileFirst Services Starter for Cordova Tutorial 教學

Create an account on
Search the template: MobileFirst Services Starter, and create it.
螢幕快照 2016-06-04 11.22.21

After that, download the source code from

Before installing Cordova, you will require node.js which is downloaded from

If you do not have Cordova installed, then type

npm install -g cordova

Update Cordova

sudo npm update -g cordova

Go to the directory of source code, add cordova platform

cordova platform add android
cordova platform add ios

Install the IBM Bluemix plugin
cordova plugin add ibm-mfp-core

Go to /project-dir/www/js/index.js, paste your route & GUID
route: https://your-proj-name/
GUID: can be found in the first line of Cloud Foundry’s log in the panel

route: ""
GUID: ""

Open xcodeproj in /project-dir/platform/ios/
If it prompts to update latest swift version, cancel it.
Go to build settings tab and edit Objective-C Bridging Header
Find Runpath search Path, and add

Build Cordova
cordova build
Then run
cordova run android

Run iOS platform on Xcode

Cloud Foundry

Install CF CLI from

Install Bluemix CLI from

If this error occurs

panic: Config error: open config.json: permission denied


sudo chmod -R 777 ~/.cf

If this error occurs

panic: no supported languages found []string{“zh_TW.UTF-8”}

go to ~/.cf/config.json

set “Local” : “zh-Hant”

Download your project source code

螢幕快照 2016-06-04 12.11.58

go to /proj-dir , type

bluemix login -a

push your project

cf your-project-name

Now you are ready to build your own project.

How to make a UIScrollView using Auto Layout

From the official document :

UIView: Position with constraints.
UIScrollView: Bind to UIView with constraints.
UIDetailView: Set size (intrinsic content size), max out compression-resistance, set top-, bottom-, leading- and trailing constraints to UIScrollView to 0 manually.

Now let’s set up the outlet as the image.

螢幕快照 2014-04-18 下午6.53.10

Next, select Scroll View and in the option menu : Editor -> Resolve Auto Layout Issues -> Add Missing Constraints

Select View under Scroll View in the Size Inspector, make its height as your desire.

And select View and in the option menu : Editor -> Resolve Auto Layout Issues -> Add Missing Constraints

螢幕快照 2014-04-18 下午7.19.30

Now we do some changes.

1. add Width 320 ( Editor ->Pin -> Width)

2. delete Center X alignment

3. Open Vertical Space – (-480) – Scroll View – View in Attributes Inspector

Set Constant : zero

Now the outlet will look like..

螢幕快照 2014-04-18 下午7.07.35


Then your ScrollView can be scrolled !

Finished !

Change User Agent in iOS

Sometimes, different User Agents will show different content in the WebView.
in order to cater your html content, you will need to change UIWebView’s user agent.

Add the below code in AppDelegate.m

 + (void)initialize {

// Set user agent (the only problem is that we can’t modify the User-Agent later in the program)

NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:@”Your User Agent”, @”UserAgent”, nil];

[[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];


Don’t forget to fill in “Your User Agent”.
For example, my user agent is

Mozilla/5.0 (iPad; CPU OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53

Find your own user agent from WhatsMyUserAgent

How to import library using cocoa pods

CocoaPods URL

Using CocoaPods is really easy to import Library to our iOS project.

I will show you how to import a library. I use MarqueeLabel as an example.

MarqueeLabel GitHub

First we need instal Ruby.
I use third-party-tool to install it.

Ruby Version Manager (RVM)

Type the following code in Terminal :

\curl -sSL | bash -s stable

After installing Ruby, we need to install CocoaPods now.

sudo gem install cocoapods

If you can't get anything now, maybe your Internet is blocked. I use these to change the install source.

gem sources --remove
gem sources -a

Type this to check

gem sources -l

It will then display :


Run install code again

sudo gem install cocoapods

After the installation completed, use cd command to direct to your project folder. Then, we create a Podfile using vim command

vim Podfile

Type the following

platform :ios, '7.1'
pod 'MarqueeLabel', '~> 1.4.1'

press Exit, and type   :wq    to exit editing with saving

Then install it now

pod install

Now you can open your Xcode (xworkspace)

open YourAppName.xcworkspace

Try to import it in your file

#import "MarqueeLabel.h"

Succeed ?