(通車的路上寫blog最討厭碰到網路出狀況呀!) KVO (Key Value Observing) 是用來監控一個變數是否有改變的技巧, 在做UI的data binding來說是蠻有用的, 舉個例子, 如果有個Label是一直顯示網路蒐集過來的讀數會一直變化, 一般的作法是收到這讀數再直接去操作設定這個label, 缺點是會把這類的資料邏輯跟UI邏輯綁死, 而且如果是有多個以上要跟這資料連動, 較不易擴充 (還沒完全醒, 例子舉得很爛), KVO提供一個比較好的方式利用監控數值變化來處理這件事

網路上找到一篇文章, 或許這篇解釋的比我好: 了解 Objective-C 上的 KVO(Key-Value Observing) 機制

不過這篇主要是針對Objective C的, 觀察者利用實作observerValueForKeyPath來得到狀態, 而被觀察者利用了addObserver加入觀察者

當數值變動時, 必須要透過willChangeValueForKey 和 didChangeValueForKey 來通知觀察者, 這點算比較麻煩, Swift則不需要自己去呼叫, Swift在語言本身來說就已經設計了監看變數變化的特性, 最簡單的方式是透過willSet和didSet, 例如:

  var myVar:Int {
     willSet {   
       ....
     }
     didSet {
       ....
     }     
  }

不過這樣其實還沒達到KVO的效果, 只算是一個hook來處理數值變化時要做的事, 在Swift中也是透過addObserver和observerValueForKeyPath, 唯一不同的是不需要willChangeValueForKey 和 didChangeValueForKey, 基本上只要把變數宣告成dynamic就好

dynamic var myVar: String = "ssss"

這邊很重要的是一定要宣告成dynamic, 不然會沒效果喔!

(剛好到站, 寫完下車)

想說既然打定主意想玩一下iOS上的開發, 就從一些最夯的東西開始, 使用Swift自是不用說(另一個原因是我還是不喜歡看Objective-C), 另外想說最近FRP (Functional Reactive Programming), 搭配Swift也剛剛好, 因此想說就從ReactiveCocoa來上手吧….

似乎在iOS流行著用CocoaPods來做相依性管理(dependency management), 如果用Objective-C, ReactiveCocoa 2.x版就已經夠用了, 用CocoaPads也非常簡單沒啥問題, 只要在Podfile裡加入即可:

pod ‘ReactiveCocoa’, ’~> 2.4.4’

但根據下面這篇

“MVVM, SWIFT AND REACTIVECOCOA - IT’S ALL GOOD!”

但2.x跟swift不搭,如果要在Swift上使用2.x版的ReactiveCocoa,就必須要使用這個分支 但使用這個分支的話, 就沒辦法透過CococaPods來管理了

不過所幸, ReactiveCocoa打算在3.0之後直接支援swift, 那如果, 把pod改成:

pod 'ReactiveCocoa’, ’~> 3.0’

不就應該搞定了嘛?代誌當然不是我這笨蛋想的那麼簡單, 首先, 把這些library含進swift project裡要使用dynamic frameworks而不是static library, 這在iOS是iOS8之後才支援的, 而CocoaPods要到0.36才有支援, 針對這個, 就必須要在Podfile裡加上一行

use_frameworks!

但…這樣還沒結束, CocoaPods的repository裡的ReactiveCocoa 3的版本其實只有到 3.0.0 alpha 1, 那是相當早期的版本, swift版本的ReactiveCocoa正在積極開發中, 因此這版本舊到如果是用最新的XCode是會編譯不過的, 問題會出在LlamaKit, LlamaKit版本在CocoaPods上是0.1.0, 但最新的則是0.6.0, 在最新版已經解掉這問題了

那這樣表示我得放棄方便相依管理系統轉向手動了嗎? 還好還有Carthage, 這個跟ReactiveCocoa都是同一個作者做的(好像是Github的員工), Carthage跟CocoaPods的概念不同, CocoaPods的採取的是傳統的中心化的管理, 但Carthage的套件則沒有中心的repository, 而是分散在各個git(github project)中, 相對來說比較簡單單純(感覺就像做git clone後再用xcodebuild去build成framework而已), 不過我在這反而碰到更多的陷阱

像CocoaPods的Podfile一樣, Carthage也有一個設定檔Cartfile, Cartfile的內容跟Podfile很像, 像是要加入ReactiveCocoa 3的話只要加入一行:

github “ReactiveCocoa/ReactiveCocoa” ~> 3.0

這邊跟CocoaPods不一樣的地方是, 它的版本管理部分完全靠git, 因此這行它會去github抓tag是v3.0的最新版本(以現在來說最新的是v3.0-beta.1), 它也可以接某個git branch, 比如說github “ReactiveCocoa/ReactiveCocoa” “swift-development”, 寫好Cartfile後只要執行:

carthage update

它應該…理論上啦…就會把相關的porject抓回來build成framework, 然後去General settings把這些framework”手動”含進來(它不像CocoaPod那麼自動):

不過, 我為什麼說"理論上", 原因是我又碰到問題了!在build到LlamaKit(又是它)時我發生以下的問題!

“project has no shared schemes” error

所以ReactiveCocoa並沒被build出來(X的)

看來幾個對這issue的討論, 似乎是執行xcodebuild -list過久timeout, 導致抓不到build target, 而根據commit的log, 0.6.5似乎解決了這問題, 我原本是用brew install carthage裝的, 所以版本是0.6.4, 所以有抓了package來裝0.6.5

裝了0.6.5就解決了嗎?我這笨蛋真的想的太簡單啦!一樣有問題啦!…沒解嗎? 開了那個commit來看, 原來它所謂的解不過是延長timeout並且把錯誤訊息改成讓人家知道那是因為timeout而不是沒有shared scheme

那怎辦, 該回歸手動了嗎?不!要追根究柢!,但看半天好像也沒啥招, 死馬當活馬醫? cd進去Carthage/Checkouts/ReactiveCocoa/目錄, 發現也有Cartfile, 那就在這邊也來一次carthage update吧….結果有沒問題?有!狀況出現在底下這兩行(Cartfile.private):

github “Quick/Quick” “master” github “Quick/Nimble” “master”

這次它說沒"master"這個object, 但carthage不是有支援用branch name嗎?不管, 拿掉試試, 把"master"都拿掉後, 就成功在這邊build過ReactiveCocoa, 那回到上一層還會出現xcode -list發生timeout的問題嗎?回到上層目錄再試, 正常了, 一次通過! X…該不會是這問題吧?這是什麼情形….那我把github “ReactiveCocoa/ReactiveCocoa” ~> 3.0 改成github “ReactiveCocoa/ReactiveCocoa” “swift-development"呢?果不期然!!一樣的問題!!不是應該有支援用branch name嗎?

(寫太多很累了, 省略發現原因的過程…底下直接寫原因)


原因是我電腦裡面有兩個git, 一個是git 1.7的版本, 一個是macos 10.10幫我裝的git, 那個則是2.3.2的, 因為路徑設的問題, 一直都抓到1.7的版本, carthage認branch name是靠git revparse, 大概1.7跟carthage不相容, 導致了這問題, 改成2.3.2之後….一路順暢….看來來去回報一下好了

但問題不是到這邊為止, carthage還是一個很新的東西, 還有一些像是Facebook/pop並不支援carthage, 現在還沒辦法全用carthage管理, 還好CocoaPods跟Carthage是可以混用的, 所以接下來應該可以讓我順利開始寫東西了吧(希望如此)

後記補充


經多次實驗, Shared scheme跟no object的確是兩個不同的問題, 前者0.6.5的確解決了這問題(我猜是我mac mini太慢所以timeout延到8s還不夠才又碰到, MBPR則沒這問題), 後者的確是git版本造成的

正常來說Github page可以有一個自己的url像是http://julianshen.github.io (使用者名稱.github.io),但如果想用自己申請的domain name取代(例如以我的例子我想改成http://github.jln.co)該怎做呢?

首先, 你要到你domain name的管理那邊(像我是host在godaddy,所以就直接用它的了), 新增一筆CNAME的record指向到你的github page 原本的domain(如把github.jln.co對應到julianshen.github.io), 不過光這樣還不夠, 你會發現連到http://github.jln.co還是會有錯誤

在你page的repository裡新增一個檔案叫做CNAME(全大寫喔), 裡面的內容就是你新指定的domain name(github.jln.co, 注意, 並沒有"http://“)

OK, 完成

收到了一個IE 10會看不到圖片的bug, 昨天看了半天, 本以為在IE10沒正確載入遠端的資料(後來覺得我怎會蠢到這麼想), debug了半天(IE 10也沒很好的tool), 結果後來發現完全不是這麼一回事, 原本的code是這樣的:

<div style="background-image: url({{mydata.getImageUrl()}})"></div>

一開始也沒想到這邊, 看起來都沒問題, 但後來下面這樣的並沒問題:

<img src="{{mydata.getImageUrl()}}"/>

才發現原來AngularJS在IE10底下, 在style裡用{{變數}}會有問題, 解決的方法是要改用ng-style, 例如

<div ng-style="mydata.backgroundStyle()"></div>

而這裡的backgroundStyle是這樣的(不是string喔)

backgroundStyle = function() {
    return {
        backgroundImage: this.getImageUrl()
    }
}

image

在今年Google IO時, Google宣布了m 未來Chrome OS上可以跑Android的應用程式, 可能有人對Chrome OS不以為意, 覺得既然有了Android何必又有一個Chrome OS, 對於沒用過Chrome OS的人可能會有這樣的感覺, 不過我必須說, 兩者設計的導向是不同的, Chrome OS速度快, 輕便, 這也是Android所比不上的, Google這一舉動, 讓Chrome OS又可以補足功能性不足的部分, 雖然不會全部的Android 應用程式都可以適用, 不過這已經足夠開啟另一個可能性了

目前開放放在Chrome App store的還不多, 只有像是Vine, Evernote這些少數Google已經測試過的, 如可以在這邊找到Evernote: https://chrome.google.com/webstore/detail/evernote/dhfolfjkgpeaojbiicgheljefkfbbfkc

但這些以外的呢?除了等Google大神以外, 還有其他管道嗎?所幸還有其他大神放出相關的工具讓你包裝, 還是Open source:

https://github.com/vladikoff/chromeos-apk

使用這工具你首先必須要有安裝node.js, 之後用npm安裝chromeos-apk這個module即可: “npm i chromeos-apk -g”

使用方法也很簡單, 只要:

chromeos-apk xxxx.apk

這樣即可, 就會產生一個Chrome extension的目錄, 然後進到Chome, 用"chrome://extensions"進入安裝extension的畫面, 載入unpacked extension即可

不過, 我在安裝時碰到一個問題, 出現了一個訊息: 

There is no “message” element for key extName

這問題是由於產生的檔案中在_locale/en底下那個檔, extName的部分只有descriiption沒有message這屬性, 補上去就好, 內容可以是你的app name