2013年2月25日 星期一

Mobile Game App 開發者交流會


Mobile Game App 開發者交流會

時間:2/25 9:30 ~ 12:00 A.M.
地點:Apple Taiwan


第三次的交流會,重點是放在 Mobile Game 的開發,可以利用 Corona SDK 這個工具很簡單快速地開發 iOS 和 Android 的 App 只要寫一次程式碼可以應用在多個裝置上。

這次很高興地邀請到 Wei Wei 來和我們分享他的人生歷程和開發歷程。從 Corona SDK 的使用方法

到 Hello World
和 Wei Wei 為了這個會議特地打造的 Game App
可見 Wei Wei 對於這個會議的用心並讓我們了解到 Corona SDK 的簡單和強大。
最後 Wei Wei 讓我們了解到 Corona SDK 並不是只能開發 Game 一般的 Application 也是可以辦到的。



雖然 Corona SDK 目前還有一些缺點,比如直接在 Device 上面 Debug 等,但是就 Game 而言,硬體的 Sensor 等等的支援不是這麼的必要。好玩最要緊。
當天的投影片,已放到網路上。http://www.slideshare.net/scentsome/superstar-dj-pdf
想跟著 Wei Wei 一起學習 Game App 的開發嗎?最新的課程 http://www.zencher.com/#game

花絮:
等待中的大家

聽課中的大家

2013年2月21日 星期四

局部畫面是要用 View 來呈現,還是要用 View Controller + View ?

我們先來看一下這個例子,預設的Yahoo 的股票軟體如下

這次討論的主角是在下半部,也就是大家看到的折線圖這個區塊。如下,這篇文章討論的是局部的畫面切換。

這個區塊如果要 Michael 來寫的話,是用 View 去呈現還是要再多寫一個 View Controller 呢?在下決定之前不能只看這個區塊,要再觀察之後的畫面,和使用者互動的過程,怎麼說呢?在這個 App,下方這個區塊,不是只可以呈現折線圖,還可以左右滑動來看其他的資訊,如下。

或者是如下

簡單畫一個Flow char 就是如下


好我們知道整個操作的流程之後,我們來分析一下。比較複雜和比較單純的畫面
就我理解,比較複雜的是如下
理由是,左邊要畫線圖還要和使用者互動,右邊要呈現滿多筆資料也要和使用者互動,這兩個畫面是用不同的邏輯思考去操作的。我們暫且稱,左邊的是 Chart View。右邊的是 List View。
比簡單的就是
這個畫面不用和使用者互動(暫不理會,底下的 Yahoo! 和 Information 按鈕,這兩個按鈕是把整個 Yahoo 股票首頁都換掉)。暫說這個為 Info View
看完整個流程,還是沒說要用 View 還是 View + View Controller 呢?
Michael 的看法是這樣

  • 如果只有一個畫面,也不切換,或是切換的畫面和 Info View 這樣比較簡單沒有互動的話,就用 View 就可以了
  • 如果切換過去的畫面,比較複雜如 List View 和 Chart View,這樣就建議用 View Controller + View。

再來就是說說,在 Storyboard 裡面,可以呈現切換局部的,View Controller 的新元件。叫 Container View 。如下
把這個元件的拉到某一個 View 上面會看到如下的畫面。
自動地產生一個 View Controller 在右邊,代表著這個 View Controller 的 View 就是會被畫在左邊 Container 的區塊。

2013年1月2日 星期三

Git : 動手做看看 - Xcode 裡的 Git

繼上篇我們了解檔案在 Git 管理的資料夾裡面的角色之後,來看一下 Xcode 是如何和 git 互動的。
首先開啟一個 Xcode project 選擇 Single View Application 如下圖。命名為 GitPractice 

選擇下一步,記得不要存在任何 git init 過的資料夾底下,要存在其他的資料夾,然後會有一個 source control 可以勾選。如下圖

接下來就會出現 Xcode 編輯的主畫面。如下 
看起來沒什麼特別的,我們用 Terminal 來檢視一下這個資料夾。
用 Terminal 移到這個 Xcode Project 的根目錄。
然後輸入
ls -al
會看到如下
total 16
drwxr-xr-x   6 chronoer  staff   204  1  2 19:20 .
drwx------+ 78 chronoer  staff  2652  1  2 19:18 ..
-rw-r--r--@  1 chronoer  staff  6148  1  2 19:20 .DS_Store
drwxr-xr-x  13 chronoer  staff   442  1  2 19:20 .git
drwxr-xr-x  13 chronoer  staff   442  1  2 19:17 GitPractice
drwxr-xr-x   5 chronoer  staff   170  1  2 19:17 GitPractice.xcodeproj
Xcode 自動對這個資料夾做了 git init 的動作了。我們再用
git log
來看看 Xcode 做了什麼事,會得到
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit 
Xcode 己經幫我們把 Single View Application 的檔案都加入給 git 管理並 commit 目前狀態為歷史的節點了。
接下來我們要看一下git 的狀態用
git status
會得到如下的結果

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# GitPractice.xcodeproj/project.xcworkspace/
# GitPractice.xcodeproj/xcuserdata/
nothing added to commit but untracked files present (use "git add" to track)
原來 Xcode 預設沒有把這兩個資料夾加入 git 管理。那到底我們需不需要這兩個資料夾裡面的東西加入呢?當然是不需要,這些都是 Xcode 的衍生物和源始碼沒有太大的關係。好,那就這樣放著不管嗎? untracked files,如果之後有新增的 file 是想要加入 git 管理,又忘了加入,這樣就會和這兩個資料夾被列在 git status 的結果,一旦檔案多了,就會把真的想要加入和不想加入的搞混了,好像不怎麼好。git 有沒有方式可以設定,不想要 git 管理又不要出現在 untracked files 這邊的方法?有。要新增一個檔案名為 .gitignore。
所以我們新增 .gitignore 和 .git 同一個目錄下。內容如下

*.xcworkspace/
xcuserdata/
對應到上方紅色的兩個目錄。接著我們要把新增的 .gitignore 加入 git 管理然後 commit 做一個歷史記錄如下輸入
git add .gitignore
然後 commit
git commit .gitignore -m "add ignore file"
這樣一來,再做一次
git status
就會看到
# On branch master
nothing to commit (working directory clean)
這樣 git 穩定的狀態
除了這兩個資料夾,還有沒有要忽略的?有的。
那是哪些?其實我也是從 github 裡找到比較有名的幾個 project 來參考的。如下列出來給大家參考

.DS_Store
.localized
# Build directory
build/
# XCode user specific files
xcuserdata/
*.xcworkspace/
*.mode1v3
*.mode2v3
*.perspectivev3
*.pbxuser
output
可以當成一個 Xcode project 用 Git 要忽略的範本了。請加到 .gitignore 。然後再一次 git add ,git commit。
加了 ignore 之後,我們來看Xcode 如何處理 modified file 。首先在 AppDelegate.m 的 application:didFinishLaunchingWithOptions: 新增程式碼。如下

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    NSLog(@"first line");
    return YES;
}
我們新增一行 code 在上面綠色之處。存好檔之後會在 Xcode 左邊 project navigator 欄看到在 AppDelegate.m 旁邊有一個小 m 的符號。如下圖。
代表這個 AppDelegate.m 有被修改過。此時,我們在 Terminal 輸入以下指令
git status
會看到

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   GitPractice/AppDelegate.m
#
no changes added to commit (use "git add" and/or "git commit -a")
和之前用 Terminal 改變 file 的一樣情況。AppDelegate.m 變成了 unstaged file。所以我們要怎麼做?git add or 直接 git commit 是吧?那是在 Terminal 的情況下,如果用了 Xcode 這種比較方便的 IDE 都會整合起來,比如在現在的情況下,只要在 AppDelegate.m 按下右鍵然後選 source control -> commit selected files 如下圖
然後就會跳出另一個視窗讓我們輸入此次歷史節點的註解。如下圖。
主要分幾個部分,最左邊是有修改過的檔案,中間是目前修改過的程式碼,右邊是之前最後一次的 commit 記錄。還可以往下拉看看有什麼其他的地方不一樣的。藍色的框框是小紅槓,標示著目前和最近 commit 兩個檔案不同之處,底下的紅色框框,就是寫註解的地方。如果按下右下 commit 1 file 這個按鈕,就會看到 Xcode 裡 AppDelegate.m 這個旁的小m 不見了,代表是己經 commit 的穩定狀態。如下圖
再把鏡頭轉到 Terminal,目前為止我們利用 Xcode 很方便的工具做了 git commit 的動作,用 Terminal 檢視一下,輸入
git log
出現

commit 47454d43e92257d81a3a26ed1e8c69a5b4cbafbcAuthor: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:53:58 2013 +0800
    add first line
commit 00544060eb268857bda27c13f392feaeb3d9ed09
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:12:51 2013 +0800
    add ignore file
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit
最上方就是最新的,也就是剛剛用 Xcode commit 的結果。
如果修改了很多個檔案才 commit ,比如我們在 AppDelegate.m 和 ViewController.m 都加一些程式碼如下,我們看到有兩個小m。


commit 的時候可以選擇多個檔案之後,再用剛剛的做法,或是在 menu 上面 File -> Source Control -> Commit 也可以一次把所有有修改的檔案列出來。如下圖
然後會出現寫註解的畫面,最左邊也會列出有多少個 File 需要被 commit 如下圖。


可以勾選,也可以一一檢查改變的地方。Commit 之後我們用 Terminal 來檢查狀態如下輸入。
git log
會看到

commit e5f66ee471d2944f6faabfaac8256e748c5df3b9
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 22:07:06 2013 +0800
    add code in appDelegate.m and ViewController.m
commit 47454d43e92257d81a3a26ed1e8c69a5b4cbafbc
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:53:58 2013 +0800
    add first line
commit 00544060eb268857bda27c13f392feaeb3d9ed09
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 21:12:51 2013 +0800
    add ignore file
commit 823888353b2d6d19426b56658b90db86f2f2ab8a
Author: chronoer <scentsome@gmail.com>
Date:   Wed Jan 2 19:17:17 2013 +0800
    Initial Commit
然後再輸入
git status
會看到

# On branch master
nothing to commit (working directory clean)
這樣又回到常態了。
在編輯程式碼的時候隨時都可以和之前 commit 過的版本做個比較,要用到 Xcode 右上的按鈕,如下圖
比如我們選定 AppDelegate.m 然後按下上面的按鈕就會看到如下畫面

中間編輯區有兩大塊,左邊就是目前的狀態,右邊就是最近 commit 的狀態,因為剛剛 commit 完沒有修改所以兩邊看起來一樣,而且還可以比較目前的和之前 commit 的狀態,可以按下上圖紅色地方,會長出一條黑黑的有很多間格。如下

然後可以變動圖中右邊的白色三角形,上圖紅色處,就可以看到之前 commit 版本和現在不一樣,移動到如下圖
如紅色所框左邊的 line 17 是和之前不一樣的地方。
還記得我們曾用 Terminal 利用
git checkout <commit id> <file name>
回到之前 commit 的版本吧?目前 Xcode 4 還沒支援直接 checkout 到舊的版本,不過可以從上圖看到某個版本的一些資訊包含 commit id ,然後再回到 Terminal 來 checkout 到舊的版本。
如下圖,mouse 移到中間白色橫槓,就會變大,然後出現資訊。
這就是 Xcode 的 Git 對檔案的基本操作,目前為止我們把所有檔案版存在 .git 檔裡,之後會再討論怎麼和 Server 溝通。我們下次見。


2012年12月29日 星期六

Git : 動手做看看 - 基本觀念

版本控制在管理源始碼的時候非常重要,可以讓開發者了解目前進度,共同開發時候也可以幫助開發者整合不同的源始碼。
日前因為 GitHub 的火紅帶領了 Git 這個工具的流行,而大部分的開發 IDE 也都支援 Git 的功能,這篇文章透過筆者的觀點來解釋 git 的運作方式,進而利用 Xcode 來說明圖形介面的操作和其相對應底層的機制是如何。

首先是

安裝 Git 


  1. 可以從最新的 Xcode 安裝或
  2. 到這裡下載 http://code.google.com/p/git-osx-installer/ (雖然檔案寫的是 snow leopard 但是 lion, mountain lion 都也可以用。)

1. 用 Xcode 安裝非常簡單,打開 Xcode 的 Preferences。如下

看到視窗後選 Downloads 的 Tab 然後安裝 Command Line Tools 如下。
這樣就好了在終端機輸入
git --version
會看到如下,那就是安裝成功了
git version 1.7.10.2 (Apple Git-33)
可以直接跳過下面,到 Git - 基本操作。

用 2. 的方法安裝的話 Mountain Lion 的朋友要注意一下,不是從 Apple Mac App 下載的安裝程式會被預設的安全機制給拒絕安裝,這時候就要打開,系統偏好設定。從左上方的蘋果圖示按下。

接著選擇安全性與隱私
看到如下畫面如果左下的鎖是鎖起來,點選,然後輸入密碼打開它
然後允許任何來源
這樣就可以安裝 Git。安裝好之後,把終端機(Terminal),打開輸入
git --version
一樣要看到如下
git version 1.7.10.2 (Apple Git-33)
安裝完成後,就來操作一下 git。
在終端機輸入
mkdir gitpractice

Git - 基本操作


來產生一個資料夾,這只是一個資料夾沒有什麼特別的,
再輸入
cd gitpractice
進入剛剛產生的 gitpractice 之內
這個裡面就是空的,沒有任何東西輸入
ls -al
來確認一下,得到

total 0
drwxr-xr-x   2 chronoer  staff    68 12 29 16:30 .
drwxr-xr-x+ 52 chronoer  staff  1768 12 29 16:30 ..
這樣的結果。現在要把這個資料夾轉成 git 可以處理的資料夾,輸入
git init
會得到如下
Initialized empty Git repository in /Users/chronoer/gitpractice/.git/
再用
ls -al
來看看這個資料夾有什麼變化,得到如下
total 0
drwxr-xr-x   3 chronoer  staff   102 12 29 16:31 .
drwxr-xr-x+ 52 chronoer  staff  1768 12 29 16:30 ..
drwxr-xr-x  10 chronoer  staff   340 12 29 16:31 .git
多了一個 .git 這個資料夾,這個 .git 就是存放和 git 的操作相關所有的在這個 gitpractice 底下所有檔案改成的歷史資料都存在這。而這個資料夾的存在,就代表,gitpractice 這個資料夾是受到 git 控管的,任何的檔案結構的改變都可以記錄下來,存放在 .git 這個資料夾裡面。有兩點要注意
Git 控管的資料夾只有根目錄會有 .git 不是每個子目錄都有。這個和 svn 做法不同
比如說 gitpractice 底下還有個 src 和 doc,架構如下
gitpractice/
                src/
                doc/
只有 gitpractice 裡面會有 .git/ 這個資料夾,src 和 doc 裡不會有,雖然 src 和 doc 這兩個也都受 git 控管,裡面檔案的變化也會記錄在其 git 根目錄 gitparctice 的 .git 之下。換言之如果把 .git 整個移除,那麼就無法得知 gitpractice 底下所有檔案變化,gitpractice 就回到一般目錄的身份。
另一個要注意的是
Git 不會自動控管檔案,而要手動加入。用 git add <fileName> 來把 <fileName> 加入 git 管理的隊伍中。
那我們就來動手加入一個檔案試。首先新增一個文字檔在 gitpractice/ 裡。輸入
echo "first line" > sample.txt
然後用
ls -al
看是不是多了一個文字檔如下

total 8
drwxr-xr-x   4 chronoer  staff   136 12 29 16:57 .
drwxr-xr-x+ 52 chronoer  staff  1768 12 29 16:30 ..
drwxr-xr-x  10 chronoer  staff   340 12 29 16:31 .git
-rw-r--r--   1 chronoer  staff    11 12 29 16:57 sample.txt

再用
cat sample.txt 
把這個文字檔的內容呈現在螢幕上
first line
這樣子我們新增一個檔案在 gitpractice/ 裡面,那這個檔案有被 git 所管理了嗎?NO 當然沒有,我們可以下
git status
來看 git 管理的檔案目前的狀態。如下
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# sample.txt
出現 untracked files: 然後有一個檔案就是剛剛新增的叫 sample.txt。
先插開一下話題,設定一下 git,如果要讓 git 的一些常用的輸出有顏色出現比較好看的話,可以做如下設定。可以參考這個網頁
git config --global color.diff auto # git diff 要顯示顏色
git config --global color.status auto # git status 要顯示顏色
git config --global color.branch auto
git config --global color.log auto
OK 回到正題,我們新增一個檔案但是不被 git 所管理,那這種檔案叫 untracked file 。那怎麼變成 tracked 呢?就要如下輸入
git add sample.txt
然後再輸入
git status
就會得到如下
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
# new file:   sample.txt
#
沒有出現 untracked 字樣,這樣就是表示這個檔案 sample.txt 已為 git 所管理。
接下來我們要把這個檔案目前的樣子,記錄在 git 的歷史裡面,做為一個歷史的截圖,要輸入以下指令
git commit sample.txt -m "add first line"
其中用了 -m 這個 option 指的是對這個歷史節點,一定要留下註解,就是寫在 -m 之後的字串。然後會得到如下回應
[master (root-commit) 56f3cf3] add first line
 1 file changed, 1 insertion(+)
 create mode 100644 sample.txt
然後再用 
git log 
把歷史記錄呈現出來,如下
commit 56f3cf35c041a80f71393649cab87bbcab5d40bb
Author: chronoer <scentsome@gmail.com>
Date:   Sat Dec 29 21:56:25 2012 +0800
    add first line
記得 git log 只會呈現 git commit 之後的狀態,沒有 commit 的檔案是不會出現在 git log 列表裡的。
稍微看一下歷史記錄的內容,第一個 row 看到一堆奇怪的編碼如下
commit 56f3cf35c041a80f71393649cab87bbcab5d40bb
這個代表 git 把 sample.txt 的整份檔案做一個 HASH 的動作,然後存成一個 40 character 的字串,就代表了那個時候的檔案狀態 (讀者產生的 40 字元的字串會因內容不同而產生不同的字串)。接下來看到的是
Author: chronoer <scentsome@gmail.com>
這個就是作者和 e-mail ,可以從這兩個指令設定

git config --global user.name "chronoer"
git config --global user.email "scentsome@gmail.com"
接下來就是記錄的日期
Date:   Sat Dec 29 21:56:25 2012 +0800
和當初 commit 時候的註解

add first line
接著我們再用
git status
來看一下git 的狀態
會得到
# On branch master
nothing to commit (working directory clean) 
表明目前工作的目錄沒什麼改變是一個常態。
那我們就來改變一下 sample.txt 的內容
輸入
echo "second line" >> sample.txt  
注意是兩個">" 意思是把 "second line" 接到 sample.txt 的最後一行後面一行。用
cat sample.txt 
就會看到如下 sample.txt 的內容

first line
second line
此時我們改變了 sample.txt 然後用
git status
來查看目前 git 所管理的檔案的狀態,得到如下反應
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   sample.txt#
任何被 git add 加入的檔案有改變,而還沒 commit 之前,都會如上表示,為 modified 代表有被修改。
這邊還有一個 Changes not staged for commit 的敘述,是什麼意思呢,之後再解釋,現在我們要把 sample.txt 變成 staged 或是 index 如下輸入
git add sample.txt
再一次把修改中或是 unstaged 的檔案加入到 git 系統
然後我再用
git status
來看檔案的狀態會得到如下的回應

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   sample.txt
#

就不是 unstaged 狀態了。
為了把目前修改的 sample.txt 內容當成一個歷史的節點存下來,要用
git commit sample.txt -m "second line"
就會得到如下的回應

[master c1c905f] second line
 1 file changed, 1 insertion(+)
再次用
git status 
看一下目前的狀態,會得到

# On branch master
nothing to commit (working directory clean)
把剛剛修改的 sample.txt 再一次加入到了歷史的節點,工作目錄底下也就回到常態。到目前為止我們 commit 了兩次,用
git log
就可以看到兩個 commit 的記錄,就有兩個 HASH 之後的 40 個字元的字串。如下

commit c1c905f0d0f19a3ba750c3571d845bcc967c9ae6
Author: chronoer <scentsome@gmail.com>
Date:   Sat Dec 29 23:33:35 2012 +0800
    second line
commit 56f3cf35c041a80f71393649cab87bbcab5d40bb
Author: chronoer <scentsome@gmail.com>
Date:   Sat Dec 29 21:56:25 2012 +0800
    add first line
比較新的放在上方。就有兩筆 commit log。
到目前為止的動作整理一下

  1. 新增資料夾 - mkdir gitpractice
  2. 進入資料夾 - cd gitpractice
  3. 把資料夾轉成 git 可以管理的 - git init 
  4. 新增檔案 - echo "first line" > sample.txt
  5. 加入 git 管理 - git add sample.txt
  6. 記錄歷史節點 - git commit sample.txt -m "first line"
  7. 修改檔案 - echo "second line" >> sample.txt
  8. 變成 staged 檔案 - git add sample.txt 
  9. 記錄歷史節點 - git commit sample.txt -m "second line" (若沒做 8. 會一起執行)
以上就是基本用 git 來做版本控管的方式,每一個 commit log 都可以視為一個版本。
如何檢視各個版本就是用 
git log
會得到如下的結果
commit c1c905f0d0f19a3ba750c3571d845bcc967c9ae6Author: chronoer <scentsome@gmail.com>
Date:   Sat Dec 29 23:33:35 2012 +0800
    second line
commit 56f3cf35c041a80f71393649cab87bbcab5d40bbAuthor: chronoer <scentsome@gmail.com>
Date:   Sat Dec 29 21:56:25 2012 +0800
    add first line
把各個 commit 版本呈現出來。每個版本的代號就是 40 個字的字串。如果想要比較兩個不同版本的差異可以用
git diff <commit id> <commit id>
其中<commit id> 可以用原本的 40 字的前 7 個來代表比如上面的例子,要比較
c1c905f0d0f19a3ba750c3571d845bcc967c9ae656f3cf35c041a80f71393649cab87bbcab5d40bb
可以用  c1c905f  56f3cf3 寫成
git diff c1c905f 56f3cf3
得到如下結果
diff --git a/sample.txt b/sample.txt
index 06fcdd7..08fe272 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1,2 +1 @@
 first line
-second line 
也就是  a/sample.txt, c1c905f 比 b/sample.txt 56f3cf3 少了一行 second line
如果把比較的檔案位子交換成
git diff 56f3cf3 c1c905f
就會得到

diff --git a/sample.txt b/sample.txt
index 08fe272..06fcdd7 100644
--- a/sample.txt
+++ b/sample.txt
@@ -1 +1,2 @@
 first line
+second line
也就是 56f3cf3 比 c1c905f 多了一行 second line
有了版本,就會想到要之前的版本,在 git 可以這麼做
git checkout <commit id> <file name>
<file name> 就會回到 <commit id> 的狀態,比如在這個例子,我們這麼做
git checkout 56f3cf3 sample.txt
然後再用
cat sample.txt
看看 sample.txt 的內容得到
first line
回到了 56f3cf3 的狀態了
很方便的版本管理可以任意回到之前的版本。
最後筆者來整理一下檔案在 git 資料夾裡的狀態。
剛剛我們用 git checkout <commit id> <file name> 之後會回到之前 commit 狀態,此時如果用
git status 
來看狀態會是如下

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   sample.txt
#

是回到一個 staged 的 sample.txt,如果再對這個檔案修改。比如用 vi 存完檔
就會發生一個很有趣的狀況

git status 
來看會看到

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   sample.txt#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified:   sample.txt#
同一個檔案有兩個狀態,一個是 staged 另一個是 unstaged 可以直接 commit 或是先把 unstaged 用 git add 變成 staged
之後如果 commit 就會再多出一個 commit log。
以上是 git 的簡介,下一篇會來探討Xcode 的 GUI 和 git 運作的相關功能。








2012年12月2日 星期日

Objective-C naming convention 的重要性 - ARC class 呼叫 non-ARC Class method

Michael 上課的時候都會和學員提到命名的習慣,每個語言都有其命名的習慣。了解習慣可以幫助初學者很快的進入這個環境想要傳答的意圖是什麼。
命名的範圍很廣,從 Source Code 的檔案名稱到 Class 的名稱,Variable 的命稱,Method 的名稱等等都有其命名的習慣。 打個比方,在寫 Java 時,Java 的 Class 如下定義
class Car {
}
產生一個 Car class 其第一個字大寫是 Java 的命名習慣,而相對應這個 Source code 的檔案,也常命名為 Car.java,習慣就是 Java 的檔案名稱和其內容的第一個 Class 命稱一樣,大寫字開頭,這個是 Java 語言中的習慣。
習慣指的是,即使語法沒有強制說不行,但是大家都這樣做。
而 Objective-C 沒有這樣的習慣。

上述的 class 在 Objective-C 是這樣命名


@interface Car
@end

@implementation Car
@end

Class 的定義在 Objective-C 是分開的分為

@interface Car
@end


@implementation Car
@end
兩個部分。
再來看看另一個語言  C# 是如下定義
 
class Car{
} 
看起來和 Java 有點像,也沒有檔案名稱要和 class 命稱一樣命名的習慣。
我們再來看看 Class 的內部命名習慣。
把剛剛的 class 加上 ivar 和 method.
Java 部分
 
class Car {
  String name;
  String getName(){
    return name;
  }
  void setName(String newName){
    name = newName;
  }
}
新增了 name 這個變數 和 getName 還有 setName 這兩個 method。 getName 稱為 getter 而 setName 則為 setter 。
Java 的命名習慣就是,第一個字小寫,不論 variable 或是 method 的名稱。名詞和名詞之間後面接的名詞第一個字大寫,這種命西習慣稱為 CamelCase 駝峰式大小寫
再來看看 Objective-C 的命名習慣。

@interface Car:NSObject{
  NSString * name;
}
@end

@implementation Car
-(NSString *) name{
  return name;
}

-(void) setName:(NSString *) newName{
  name = newName;
}
@end
 
Objective-C 的命名習慣和 Java 差不多,但是 getter 的地方不一樣,在 Objective-C getter 的名稱和要讀的變數名稱一樣。在這個例子兩者都叫 name。
我們再來看看類似的 class 在 C# 如何表現?
 
class Car{
  string name;
  public string GetName(){
    return name;
  }
  public void SetName(string newName){
    name = newName;
  }
} 
在 C# 中新增了 name 這個變數和 GetName 還有 SetName 這兩個 method。在這邊可以注意到 C# 的變數名稱是小寫開頭而 method 的名稱習慣用大寫字開頭。
三種語言都有其個自的習慣,雖然不按照這個習慣,大部分情況下程式也是可以執行,但是在 Objective-C 如果不照者命名的習慣會造成一些奇怪的問題產生。
就讓我們來進入這篇文章的主題,開啟一個 ARC enable 的 Project 再加入一個 none ARC 的 class 就用上述的 Car 再加上兩個 method,讓我們一步一步來。
首先開啟一個 Single View Application 的專案如下
記得要勾選 Automatic Reference Counting
新增一個 Class 名為 Car 繼承 NSObject 如下是 Car.h
 
@interface Car : NSObject
-(id) newName;
-(id) newname;
@end
Car.m 如下
 
@implementation Car
-(id) newName{
    return [NSString stringWithFormat:@"Honda"];
}

-(id) newname{
    return [NSString stringWithFormat:@"Honda"];
}
@end
新增兩個 method 這兩個 method 的名稱很像,一個叫 newName 一個叫 newname 差別在於一個 name 有大寫的 N 另一個沒有。換句話說,newName 是有依照習慣命名,newname 是沒有的。 接下我們要把這個 Car.m 設定為不使用 ARC。
如下設定。
再新增一個 Button 在 畫面上,然後 Button 按下去 action 如下
 
- (IBAction)testCar:(id)sender {
    Car * car = [Car new];
    NSLog(@"Car name %@", [car newName]);
}
我們先使用這個 newName method。一執行,發現馬上就 crash。 但是如果換成 newname 這個 method 就是正常執行。 為什麼呢? 因為對於 non-ARC 的 method,
ARC 會看其 method 的開頭是不是 alloc, new 或 copy (所謂開頭指的是符合 CamelCase 的第一個詞)
或是
第一個是 mutable 第二個是 copy ,也就是寫成 mutableCopy 。
此時 ARC 會自動認為這個 method 是會產生一個沒有加到 autorelease pool 的物件,然後就自行決定加上 release 在這個例子使用 newName 就 crash 是因為 newName 回傳的是
[NSString stringWithFormat:@"Honda"] 
這個有加到 autorelease pool 的物件。而 ARC 自動多 release 一次了。這個例子是要提示大家,在寫 method 的時候要注意 CamelCase 第一個字,這個就是 ARC 的習慣。

2012年11月19日 星期一

Objective-C 如 printf() 或是 NSLog() 不定參數的寫法


參考
http://www.numbergrinder.com/2008/12/variable-arguments-varargs-in-objective-c/

準備 interface
 
@interface Car : NSObject {
}
-(void)addCars:(NSString * ) title, ... ;

@end
 


addCars: 這個 method 有一個 NSString 的參數,第二個參數是 ...

也就是 variable arguments 重要語法

先要確定 addCars: 怎麼用

我們假設是如下使用

[car addCars:@"Toyota", @"Honda", @"BMW", nil ];


可以輸入多個 NSString 但是要 nil 結束。
再來就是 implementation
 
@implementation Car
-(void) addCars:(NSString *)title, ...{

 va_list args;
 va_start(args, title);
 NSLog(@"%@", title);

 NSString * car;
 while ((car = va_arg(args, NSString *))) {

  NSLog(@"%@",car);
 }
 va_end(args);
}

@end
 

在上方的 addCars: 裡我們用到了

va_list 這個型別,用來代表 ... 的所有內容

用 args 指向 ... 的內容

再來看到 va_start(args, title)

明確告知 args 放的內容是 title 之後的內容

然後把每一個 args 都用 NSString * 來表示, 轉型成 NSString *

用 car = va_arg(args, NSString *) 把位置給 car 變數

到 car 是 nil 為止,所以用 while

最後是用 va_end(args); 結尾。


在 main 就可以如下輸入
 
Car * obj = [Car new];

[obj addCars:@"Toyota",@"Honda",@"Benz",@"BMW",nil];
 
Console 結果是

Toyota
Honda
Benz
BMW

用 nil 結尾主要是可以知道 ... 何時結束

也可以用參考提到的,

第一個參數是數字如下


- (NSNumber *) addValues:(NSNumber *) firstNumber, …


就交給大家試試了

2012年10月27日 星期六

iOS App 開發者交流會 - 2012-10-17 at Apple Inc. Taiwan 會議記錄

致謝

首先當然感謝 Apple 給 Michael 這個機會可以在 Apple 公司裡舉辦 iOS App 開發者的交流會。再來就是感謝極電資訊的幫忙可以促成這次會議的圓滿。

Announcement

一開始由 Apple 的 Kelvin 向大家介紹一下整個 Apple 內的環境,剛搬到這個新的地點,還是第一次舉辦開發者相關的研討會。Kelvin 主要是負責企業和教育市場,有這方面開發需求的開發者或是想要佈署相關設備的企業單位可以寫信給 Michael 幫各位轉介給 Kelvin. 有與會的朋友們己經有 Kelvin 的連絡方式了,就可以自己連絡。

Opening

由小弟我來給大家一個開場,主要是提到 iOS 的現況還有幾個主要的技術分享
  • 使用 Xcode 4.5 在 iOS 5 執行環境,需要注意的地方
  • UIViewController 有關 Rotation 的改變
  • Auto Layout
等等的技術分享,投影片可以在這邊看到。http://slidesha.re/RYkbs5

與創投打交道 - Hoku

(Hoku有交帶,不方便露臉)。
重點節錄
  • 創投不會只想把公司吃掉
  • 不會惡意想要搞垮公司
  • 創投可以在初期就幫助公司,也可以在後期幫助公司上市
  • 誠實的老闆是創投最喜歡投資的對象
  • 請不要太工程師導向或是業務導向
有關更多的資訊,可以參考。http://slidesha.re/RYoq7e

學員成果分享 - Jacky

很高興可以邀請到 Jacky 巨狐資訊科技有限公司 GZFOX, INC. 執行長和大家分享,自行開發 App 的經驗。
其中 Michael 印象比較深的是和公家單位打交道時的過程:
Jacky 有寫一個台鐵的 App,一開始自已去連網站,發現不行,然後寫信給台鐵,一來一往之後,過了很久,才有回覆,才可以拿到比較完整的資料。
還有就是有一個利用 App 可以線上沖洗自己手機裡的照片成真實的像片。
完整的投影片在。http://slidesha.re/RYrpMK

學員成果分享 - Wei Wei

Wei Wei 算是學員中最傳奇的人物了,當過 DJ,出過唱片,書本,會英法德語,還寫了好幾個 App 的 Game。Michael 覺得世上怎麼會有如此厲害的人物。
除了當天就發表一款新遊戲之外,還和大家分享有趣的音樂生成軟體,還有介紹幾本好書。
演講的過程整個充滿熱鬧的氣氛,希望 Wei Wei 不要來搶我的飯碗 orz。
投影片,可以在此下載。 http://slidesha.re/RYsx2V

學員成果分享 - Steven

Steven 寫了二個評價不錯 App 和電子商務有關,也都有廣告商找上門來要配合放廣告,其中比價撿便宜寫下了免費的第二名的佳績,然後呢就決定轉成付費,再來看一下消費者對於定價的觀感,從 90 元 到 30 元的定價比較,來分析如何的定價才是最適當的。
在分享過程中 Kelvin 和 Michael 都各自提過一個 Promote 自己 App 的方法,分享給大家。Promotion 是非常重要的在現在 App 海的社會中。
完整的投影片在此可以下載。http://slidesha.re/RYuEnv

One more thing - Michael


Michael 成立了友教有限公司,專門服務企業內部的訓練和提供專業的 App 開發和整合服務給企業朋友們。有興趣的朋友可以寫信給
Michael - scentsome@gmail.com
除了提供軟體服務外,友教和極電合作,提供好的硬體服務環境給客戶,軟體加硬體的服務希望可以增進企業導入 App 開發和產品合作。
極電資訊 - 20 年的 Apple 授權經銷商 02-2705-6216

ADB - Arthur

除了 App 之外,Michael 向大家推薦 Arthur 最新研發出的產品 ADB 是一個 Module 可以透過耳機孔提供 App 和 UART 的雙向傳輸資料的服務。Square 是一個著名的成功例子,只在信用卡的金流,而 Arthur 的 ADB 可以應用在各式各樣的服務,甚至包含 Android 等有耳機孔的系統,都可以透過 App - ADB - Any Device 溝通。
完整的投影片在- http://slidesha.re/RYvS25