在 macOS 上使用名片型 LED 字幕機

前兩週在逛光華商場的時候,看到店家在賣一種名片型的 LED 字幕機,想想如果在身上或是桌上有一塊這樣的玩意,顯示一些文字/圖案,應該還頂有意思的,就買了兩組回家當做玩具。

這玩意看起來稱呼很多種,我後來在網路上看了一下,以這一則網路拍賣來說,就還有「LED跑馬名牌」、「LED名片」、「LED名牌」、「LED胸牌」、「LED電子名片」等稱呼—販賣這種商品的店家還頂多的,甚至看起來型號都一樣,不太了解這個業界,也不知道是同一個工廠有很多個代理商,還是說有很多家都在生產,但是共用同一個設計。

這類字幕機價格在台幣五六百元之譜,有紅、藍、黃、綠等多種顏色,我買來的這組解析度為 12×48 pixels,但是好像還有一種更小一點的,解析度是 11×44 pixels。在裝置上可以容納八條訊息,可以用後方的按鈕決定要切換到哪一條訊息,後面還有磁碟以及別針,可以讓你貼在鐵器或是別在身上。

機器上也提供 USB 接頭,除了拿來充電之外,連接電腦之後,還可以透過軟體修改字幕機裡頭的內容,但軟體這部份其實有點麻煩。

Continue reading

因為你用來做 Code Sign 的 Certificate 是幾個月前產生的,所以你的 App 會 Crash

這篇 blog 就是我在 2015 年四月份台北 Cocoaheads 在台上講的事情。

在過年期間,我把去年 11 月時寫的捷運轉乘這個個人的小 iOS App 改了改,在年假結束的前幾天 submit 一個版本,結果,過了一週,被 reject。

蘋果的 reviewer 說,他們只要一安裝這個 App 的 binary,就會馬上 crash;可是在我自己的開發環境中,完全無法重現這個狀況,由於過完年公司的事情就一件一件接著來,所以也就擱在一邊不管了,我到今天才知道為什麼會 crash,而且理由還頂荒唐的。

這兩天我們把公司產品 code 裡頭的一條新功能的開發分支(講 feature branch 不知道會不會比較好懂)併回主線,然後讓主線的程式進入 Jenkins build,讓公司的 QA 部門做出貨前的測試。狀況很奇妙,原本的 App 也是跑得好好的,在支線開發的過程中,也跑得好好的,但是從 Jenkins 編出來的 build,只要一跑起來,就會 crash。

Continue reading

WatchKit

更新

Xcode 6.2 beta 4 之後,就有「+ openParentApplication:reply:」可以呼叫,可以解決大部分的 Watch App Extension 與 Hosting App 之間的溝通問題。這篇大概是 code 6.2 beta 1 推出時寫的。

另外,Hosting App 要通知 Watch App Extension,大概還是得透過 CFNotificationCenter。

原文如下:

要開始嘗試使用 WatchKit 開發 Apple Watch 的相關應用,首先要安裝 Xcode 6.2 Beta 版本與 iOS 8.2 SDK,然後從 File 選單中,選擇 New Target,再從 Apple Watch 分頁中選擇 Watch App。

Xcode 6.2 Beta 版本有個 Bug,如果你原本的專案檔案中,Build Phases 裡頭包含了 Run Script Phase,那麼再加入了 Watch App 之後,Xcode Beta 就會一直當一直當一直當。

所以,在目前 Apple Watch 還沒有上市,蘋果也只提供 Beta 版本的開發工具,只能夠用模擬器模擬運作,一切都還不穩定的狀況下,我們想要先了解 WatchKit 的架構,必須把 Watch App 加到一個沒有 Run Script Phase 的專案中,或是可以把原本專案的 Run Script Phase 砍了,或是開一個新的測試專案。

Continue reading

iOS 8 一些跟 Audio 相關的改變

iOS 8 裡頭 Audio API 的底層有一些改變,但是蘋果改了這些地方,也沒有在文件裡頭說清楚,一開始也不會注意到這麼微小的改動。所以你原本寫的程式在升到 iOS 8 之後,就會出現一些奇怪的行為。

蘋果改動了 Audio Session 的行為。Audio Session 是一套在 iOS 裝置上用來描述、管理你的 App 使用的是哪一種 Audio 的方式,以及因為使用某種類型(Audio Session Category)的 Audio 所產生的對應行為。

Continue reading

捷運轉乘

前陣子花了點時間寫了一個簡單的免費 iOS App,叫「捷運轉乘」,現在可以直接在 App Store 下載,也可以在 Github 上取得程式碼

這個 App 做的事情很簡單,就是幫你計算兩個台北捷運站之間經過車站最少、或是轉乘次數最少的路徑。由於裡頭包含了松山線的資料,在捷運松山線通車、台北捷運路網變得複雜之後,如果你也開始有不知道應該怎麼轉搭捷運的困擾,希望這個 App 可以有些幫助。

Continue reading

Swift 會不會取代 Objective-C?

說到 Swift 會不會完全取代 Objective-C,目前看起來是,在 iOS 8 推出之後,應該不少應用程式會使用 Swift 開發,但是 Framework 這一層還是要用 Objective-C 來寫。

我們還是要回來看 Objective-C 與 Swift 的 run time 是怎麼實作的。無論是在 Objective-C 或 Swift 中,一個 class 有哪些 method,都是儲存在 virtual method table (以下簡稱 vtable)中,但是實作方式不一樣。

Objective-C 的 vtable 是個像是 dictionary 的實作,table 中每一筆資料都是 C 字串當 key(又稱 selector),對應到相對的 C Function pointer,所以每次呼叫某個 Objective-C 物件的某個 method,就是透過一個叫做 objc_msgSend 的 function,在表格中根據字串當 key,尋找對應該執行的 function—如果找不到,還會去問這個 Class 是否有實作 forwardInvocation: 這個 method,還是沒有的話,就會丟出找不到 method 的 exception,這部份可以參考蘋果自己的官方文件

至於 Swift 的 vtable 則是一個 array,對某個物件呼叫某個 method 時,相當於要求執行這個 function array 當中的第幾個 function(參見 Mike Ash 的文章)。

如此就會造成以下影響:在 Swift 中,尋找要呼叫的 method 的速度,理論上就會比 Objective-C 來得快,因此同樣功能的程式,用 Swfit 寫,整體上應該會比用 Objective-C 來得快。但同時,Swift 的 vtable 中每個 function 的順序就不能改變,在編譯的時候,vatble 裡頭是什麼順序,在執行的時候就得要是什麼順序,如果是執行的時候載入了不同的 runtime,順序不對,那就會呼叫到錯誤的 function。

蘋果是怎麼確保 compile 時用到的 runtime 與執行時的 runtime 是同一份呢?就是,在編譯應用程式的時候,Xcode 會自動把一份 Swift runtime 複製到應用程式的 bundle 中;所以,你的裝置中有多少個 Swift 應用程式,就會有多少份 Swift runtime。Swift 的 runtime 本身不大,這麼做還沒什麼問題,但是你寫一個 iOS 應用程式還會用到 Foundation、UIKit…一大堆的 Framework,如果要把每個 Framework 都複製一份,聽起來就很不對,照裡說不會換成 Swift 才對,Objective-C 當初用字串當 key,某方面來看,也就是為了處理像 DLL Hell 這樣的問題。

外部開發者比較沒有機會寫到比較底層的 Framework,如果只是寫一個 iOS 應用程式的話,按照蘋果的宣稱,全都用 Swift 寫看來不是什麼問題。

而在 iOS 8 之後,蘋果也終於開放在應用程式 bundle 中,放置自己寫的、或別人包好的 Framework(Mac OS X 從一開始就開放了)。如果是自己寫的 Framework,而且這個 Framework 與主要應用程式的 Target 是在同一個 Xcode project 中,跟著主應用程式 Target 一起編譯,那應該還不會有什麼問題,但如果用的是別人已經編譯好的 Framrwork,那就相當危險—你不能夠保證別人的這個 Framework,與你現在的開發環境用的是同一個版本的 Swift runtime。

iOS 8 同時也開放了一些系統 extension,這些 extension 感覺起來原理就是 Mac OS X 上的 plug-in bundle,透過 dynamic loading 讀入外部的 library。感覺起來 extension 用 Swift 寫似乎也頂危險的—一個應用程式載入一堆 plug-in,每個 plug-in 可能相依於不同的 Swift runtime,看起來就會出亂子。不過目前還沒看到蘋果自己在這方面有什麼文件。