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 write multiple language code snippets in MkDocs

MkDocs is using markdown to generate documents on static web pages.

Recently, I was working on writing documents for a iOS project. In iOS, I would need to document 2 programming languages: Objective-C & Swift. If I write them in two separate code snippets, that would be very unreadable. So to improve the readability, I decided to put them together by using HTML Tabs.

We will need to use custom configuration to let MkDocs generate those HTML syntax with the javascript and CSS.

In mkdocs.yaml, specify the js and CSS files used for the tabs.

    - styles/tab.css
    - custom/tab.js

Javascript: when clicks the tab, it will hide others tab contents.

function openCode(codeName, elmnt, color) {
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";

// Remove the background color of all tablinks/buttons
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
tablinks[i].style.color = "black";

// Show the specific tabs content
var elements = document.getElementsByClassName(codeName);
for (i = 0; i< elements.length; i++) {
elements[i].style.display = "block";

// Add the specific color to the button used to open the tab content
elements = document.getElementsByClassName(elmnt.className);
for (i = 0; i< elements.length; i++) {
elements[i].style.backgroundColor = color;
elements[i].style.color = "white";

// Get the element with id="defaultOpen" and click on it
if(document.getElementsByClassName("objbutton") !== null){
var elements = document.getElementsByClassName("objbutton");
for (i = 0; i< elements.length; i++) {

CSS: for Tab styling

/* Style the tab buttons */
.tablink {
    color: black;
    float: left;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 12px;
    font-size: 12px;
    width: 100px;

/* Change background color of buttons on hover */
.tablink:hover {
    background-color: #777;

/* Set default styles for tab content */
.tabcontent {
    color: black;
    display: none;

/* Style each tab content individually */ 
#Obj {background-color:white;}
#Swift {background-color:white;}

Then finally in markdown file, we can easily create a multi-language code snippet.

<button class="tablink objbutton" onclick="openCode('obj', this, '#03a9f4')" markdown="1">Objective-C</button> 
<button class="tablink swiftbutton" onclick="openCode('swift', this, '#03a9f4')" markdown="1">Swift</button> 


<div class="obj tabcontent"> 
Your objective-c code goes here.


<div class="swift tabcontent"> 
Your swift code goes here.


In HTML tags, the markdown="1" tells MkDocs do not parse its content so it will be generated as normal HTML syntax.

Here it is how it looks like.

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:


Logitech G213 Prodigy Keyboard

My first mechanical keyboard was CM Storm QuickFire TK. I likes its CHERRY MX RED Switches. Unfortunately, it did not come along with me to Australia. I had to use MacBook’s keyboard for 9 months. Finally, G213 caught my eyes with its shiny LED lights, and very fair price.

G213 supports OS X, its multimedia buttons are functional, including playing iTunes music, lower/raise the volume.

Though, it is not a mechanical keyboard, its keys actually provides a similar feeling as using cherry red switches. Nonetheless, the sound of clicking is not so clear and sharp as cherry red switches.

Its RGB lights are bright, and the keyboard can support multiple colors in 4 zones at once.

For this fair price, 70AUD, it worths purchasing.

GoPro 5 Black is here!

關注於動作攝影機已有兩三年了吧,一直在Sony 與 GoPro之間遊蕩。為了即將開始的Road Trip,有恰當的理由可以入手了!可以錄起我最愛的運動:衝浪,滑板,滑雪,潛水!

car charger, 3 way stick, GoPro 5, 2 batteries(Wasabi) with charger, head strap, quick clip.

Choice of memory card for 4K recording

SanDisk Extreme 128GB
Samsung Pro Plus 64GB

I bought the SanDisk Extreme 128GB first, then I found out that it is incompatible with GoPro 5 Black. After searching online, it seems that every SanDisk card with UHS-speed 3 has issue.
Then I got another one which is Samsung Pro plus 64GB, which works well.


Whilst using SanDisk Extreme, I had to insert and remove the SD card 4 or 5 times to get it work when the GoPro is on. This is very annoying and it is impossible to do that when you are doing sports.


Updated: After the firmware v1.57 of GoPro5, SanDisk Extreme 128GB works really well!!!

Osaka Universal Studio 大阪 環球影城

歡迎來到 Universal Studio




門票的部分,我們在網路上已經先訂好了Express 7,可以快速通關七項遊樂設施。進場時,出示QR Code便可以,不需有紙本票根。如果有購買快速通關的話,就不需要花太多時間排隊囉,真的挺貴的。但是逆轉世界這項遊樂設施還是排了挺久的,一個多小時吧。如果沒有快速通關大概要兩三小時吧….









霍格華滋提供了軌道列車搭載4K3D影院,感覺就像法國迪士尼的L’Aventure Totalement Toquée de Rémy 料理鼠王的實境歷險。不過霍格華滋的刺激度更上一層樓,坐完可能會暈眩唷,因人而異。這項設施有快速通關的話,可以節省不少時間,我幾乎沒有花到什麼等待的時間。

這個遊樂設施跟逆轉世界比…等待的時間也挺久的 >_<