2012年7月29日 星期日

忘了密碼 - Single Mode for Lion

日前學員搬了一台Mac 問說,公司的電腦,之前用的人離職了,不知道密碼是什麼?怎麼辦?
在Unix環境之下,只要機器在手邊,忘了密碼通常會進入 Single Mode。在 Snow Leopard 或是 Lion 一開機的時候同時按著 Command + S 就會進入 Single Mode。
當 shell 跑完時,Snow leopard 輸入
mount -uw /
launchctl load /System/Library/LaunchDaemons/com.apple.DirectoryServices.plist
dscl . passwd /Users/<某個使用者> <新密碼>

就可以更改使用者的密碼

而在 Lion 的時候
mount -uw /
launchctl load /System/Library/LaunchDaemons/com.apple.opendirectoryd.plist

此時可以更改 root 密碼
接著輸入
dscl . passwd /Users/<某個使用者> <新密碼>

就可以更改某個使用者的密碼了
在這個時候會出現 com.apple.DirectoryServices.plist cannot be found 的錯誤
不用理會,重開機後就可以用新的密碼進入

2012年7月26日 星期四

Xcode 4.4 之旅 - LLVM 4.0

今天是 Mountain Lion 出閘的日子。 而對於開發者來說, Xcode 4.4 才是我們關注的焦點, 接下來讓麥克帶領大家, 來一場 Xcode 4.4 之旅。
首先要從 Mac App Store 下載 Xcode 4.4。 如圖。
安裝好之後,打開 Xcode, 先確定一下版本。為下圖。Version 4.4 (4F250)

二話不說先來開啟一個 Project 選 Master-Detail Application 如下圖
大致上和 4.3 沒什麼改變。眼尖的讀者應該會看到, 左邊 iOS 部分 cocos2d 的 Template
 Project 保留下來了。  因為 Template 資料夾在 ~/Library/Developer/Xcode/Templates/  而不在Xcode 執行的資料夾裡, 不會受到更新 Xcode 而影響。
選擇 Next 之後看到的視窗也和 4.3 差不多,如下,給個名字。 Hello4Table。
注意,這個 Project 的 Class Prefix 我是寫 GL。 選擇一個路徑之後按下 Create。 如下。
選擇 Project 設定 -> Build Setting 的搜尋欄填上 compiler 下方按鈕要選 all 。 如下圖就會看到主角出現了。 Apple LLVM  Compiler 4.0.
來看看 source coe 有什麼改變。 先看看 AppDelegate.h 和 AppDelegate.m 如下圖。
左邊的 .h 有 @property 右邊的 .m 卻沒有 @synthesize ? 聰明的大家猜到了吧, 是的。 在 Interface 的 property 不需要寫 synthesize 了, compiler 自動會幫大家補上。 《需要換 Xcode 4.4 理由加一》
再來把鏡頭轉到 GLMasterViewCotnroller.m 的 line 46 insertNewObject: 這個 method 身上。 如果沒看到 Line Number 可以在 Xcode Preference 的 Text Editor 打勾 如下

回到程式碼,看下方截圖。

紅色框起來的部分是 @[indexPath] 對照 4.3 寫的應該是 [NSArray arrayWithObject:indexPath]. 好的,究竟 @的作用是什麼呢?讓我們繼續看下去。
有看到之前文章 LLVM 新語法的朋友們,就會猜到了。@[@"one"] 指的就是 [NSArray arrayWithObject:@"one" ]。此文中還有提到 NSNumber 還有 NSDictionary 都可以用 @ 來改寫。這篇文章要做更深入的探討。首先來看

NSNumber 

Integer 


NSNumber * intNum = [NSNumber numberWithInt:10];
     intNum = @10; 
 

Float


NSNumber * floatNum = [NSNumber numberWithFloat:100.5];
      floatNum = @100.5;

Bool


NSNumber * boolNum = [NSNumber numberWithBool:YES];
        boolNum = @YES; 

More


NSNumber *piOverTwo = @(M_PI/2);

看到 @ 就是看到物件,直接把數值寫在後面,@100 就是一個 NSNumber 的物件,非常的合理和簡明。

NSArray 


1. NSString * str = @"4.4";
2. NSArray *  array = [NSArray arrayWithObjects:[NSNumber numberWithInt:2],@"Xcode",str,[NSDate date], nil];
2.1 NSArray * array = @[@2, @"Xcode",str, [NSDate date]];
2. 的寫法可以改成 2.1 用 @[, , ,] 來取代一堆的文字,變得多麼簡單一目瞭然。要注意的是 @[@"one"] 等同於 [NSArray arrayWithObject:@"one"] 並不是 [[NSArray alloc] initWithObject:@"one"] ,如果不是用 ARC 來管理記憶體的話,要多加小心,@[] 一開始就會被放到 autorelease pool 上,method 結束記憶體就沒了。

也許有讀者會好奇了,那 mutable 怎麼辦?@[] 是 NSArray 那 NSMutableArray 呢?有沒有另一個寫法?答案是,用 mutableCopy 如下

NSMutableArray * mArray = [@[@"one", @"two", @"three"] mutableCopy];
或是

[NSMutableArray arrayWithArray:@[@"one", @"two", @"three"]];
這樣一來 @[] 就會轉成 mutable array 了。
存取的時候非常方便,如下。

mArray[2] = @"four"; // write
    
NSLog(@"%@", mArray[2]); // read 

對變數直接用 [] 就可以存取某個 index 的值了,不只初始化好用,存取的時候更是方便。

NSDictionary


1. NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:@"value",@"key",@"Michael",@"name", nil];
2. NDictionary dict = @{@"key":@"value", @"name":@"Michael"}; 
dictionary 就是用 @{} 來表示,@[] 是 array,要注的是用 dictionaryWithObjectsAndKeys 的時候是先寫 object 再寫 key ,用  @{} 來表示的時候是先寫 key 再寫 value。
至於 mutable 的部分也是用 mutableCopy


NSMutableDictionary * myDict = [@{@"Name":@"Michael" } mutableCopy];
 myDict = [NSMutableDictionary dictionaryWithDictionary:@{@"Name":@"Michael"}];
存取 key 值的時候也很方便直接把 key 物件丟到 [] 裡。如下


myDict[@"Name"] = @"morning"; // write
    
NSLog(@"%@", myDict[@"Name"]); // read
就和 Javascript 的 associative array 一樣。
綜合 array 和 dictionary 來看初始化的時候用 @[] 和 @{} 來區別,但是存取值的時候都用 [],來操作,只是 array 的 [] 放的是整數值,dictionary 的 [] 放的是物件。

用新的語法還有什麼好處呢?來看下方的程式碼

-(id) getNil{
    return nil;
}

- (IBAction)insertNil:(id)sender {
    NSLog(@"%@", @[ [self getNil], @"hello",]);  // line a
    NSLog(@"%@", [NSArray arrayWithObjects:[self getNil], @"hello", nil]); // line b
} 
因為在 LLVM 4.0 之前的寫法 nil 在 array 或是 dictionary 裡面是當成結束,也就是說,萬一一開始就是 nil 那之後的元素就不理會,而新的語法可以在 compile 的時候找出奇怪的地方,因為新的語法裡不會有 nil 出現。如上方程式碼,[self getNil] 故意回傳 nil ,用新語法,line a 可以在 compile 時候就提出錯誤,而 line b 在執行的時候才會有可能被找到錯誤。
提筆至此,其實又可以增加一個 《需要換 Xcode 4.4 理由加一》
不過筆者不肯就此罷休,再提出一個問題來。自訂的 Class 想使用 [] 這個操作?

自訂 Class 使用 [] 

首先要分清楚,[] 裡面要放的東西,就我們所知有兩種,整數和物件。(從
array 和 dictionary 得知) 比如我想支援以下操作。

Car * car = [Car new];  // Any Class
car[1] = @"name";      // scalar write
NSLog(@"%@", car[0]);  // scalar read
就必需在自己的Class 覆寫,這兩個 mehtod。就可以用 [] 裡面放 NSInteger 了

- (id) objectAtIndexedSubscript: (NSInteger) index{
    return @"Car";
}
- (void) setObject: (id) thing  atIndexedSubscript: (NSInteger) index{
    NSLog(@"setting index %d with %@",index, thing);
}
如果 [] 要放的是物件,如下的操作

Car * car = [Car new];  // Any Class
car[@"dict"] = @"value"; // object write
NSLog(@"%@", car[@"good"]); // object read
就要覆寫以下兩個 method

- (id) objectForKeyedSubscript: (id) key{
    return [@"dict-like " stringByAppendingFormat:@"%@", key];
}
- (void) setObject: (id) thing forKeyedSubscript: (id<NSCopying>) key{
    NSLog(@"set %@ with %@", key, thing);
}
有沒有看到 setObject: forKeyedSubscript: 傳入的參數型別是 id<NSCopying> 。也就是說想用 myClass[key] = obj; 的時候,key 的 class 要有實作 <NSCopying> 提到的 required method 也就是 - (id)copyWithZone:(NSZone *)zone 。

好了,此次 Xcode 之旅就先暫時到這邊了,咱們下次再會,期待下次的 Xcode 之旅也會讓讀者們有所收獲。

最後請注意一下,筆者在寫這篇文章的時候,Xcode 4.4 (4F250) 上面的程式碼是可以執行的,但是換到 Xcode 4.4.1 (4F1003) 在幾個地方會有問題,@YES,@NO,或是 dict[@"key"], array[1] = @5 這種 subscript 的存取方式,可以參考 Apple 官方網頁,不過這些問題,"做夢夢到" 會在 Xcode 4.5 解決。


2012年3月26日 星期一

讓 Xcode 與 Git 合作愉快

一般而言用 git add 加入一個專案的時候,git 會自動把整個資料夾裡面全部的資料都加入
就會看到如下的圖
而一般的我們,看到這麼多檔案,就直接按確定加入了。但其中有一個是不能加入的,等等來看看。
接著就開發程式,寫到一個部分就 commit,看起來 Project Navigator 也很乾淨,如下

但在 Push 的時候經常性的會發生像下圖一樣的錯誤
到底什麼是 uncommitted ?從 Xcode 跟本看不到,於是打開 Terminal 下指令來看看
各位看倌可能看不清楚,把紅色的貼在下方:
modified:   PlayGround/PlayGround.xcodeproj/project.xcworkspace/xcuserdata/chronoer.xcuserdatad/UserInterfaceState.xcuserstate
原來在有一個叫 UserInterfaceState.xcuserstate 檔案也被改變了,但是在 Xcode 完全看不到?所以一開始的時候 UserInterfaceState.xcuserstate 不要加入 Git Repository 因為它是 Xcode 產生暫時性的 Binary 檔。如下圖,git add 時候不要勾選。
但如果已加入怎麼辦?
在還沒 commit 之前 可以用 git rm --cache  fileName 來當成 undo git add
再者用指令,將其排除在 git控制外
在根目錄輸入
vi .gitignore
gitignore 的內容是
*.xcuserstate
再加入 .gitignore 用  git add .gitignore
然後 commit 此時如果之前不小心也 commit 了 UserInterfaceState.xcuserstate
就用 git rm PlayGround/PlayGround.xcodeproj/project.xcworkspace/xcuserdata/chronoer.xcuserdatad/UserInterfaceState.xcuserstate
將 UserInterfaceState.xcuserstate 從 Git 移掉
之後  UserInterfaceState.xcuserstate 再來不會來亂了
Xcode 和Git 就可以相處得很愉快。



2012年3月14日 星期三

LLVM 支援新的語法?

小道消息,Apple 的 LLVM 有出現新的語法了,目的還是想讓 Developer 可以寫少一點的Code
是從這邊傳出來的。

讓我們來看看。
NSNumber :

[NSNumber numberWithInt:50];              =>  @50;
[NSNumber numberWithDouble:5.21]     =>  @5.21;
[NSNumber numberWithBool:YES]        =>  @YES;

推論,在數值前加上 @ 就變成一個 id

NSArray :

@[@"one", @"two", @"three"];

多了 @ 和 []

NSDictionary :

@{ @"key": @"value", @"red": @"apple" };

就是加上 @{} 還有 :來分別 key 和 object ,看起來是先寫 key

到底會不會變這樣呢?無從得知,不過如果是這樣還滿方便的

2012年2月3日 星期五

如何偵測手機是否JB

這篇的討論是用幾個常見 JB 過的行為來偵測是不是 JB 了,而沒辦法提供一個 100% 肯定的解決方法。首先我們來看一下 JB 過的 iOS 會有那幾個特色?
  1. 會有 Cyndia 這個 App
  2. 會需要背景執行
  3. info.plist 的SignerIdentity會被變動
我們就上面三點來假設都是 JB 需要做的行為,如果我們取得這些行為之後留下來的證據,就可以假設此手機是被 JB 了。我必需要再強調一次,這篇文章的行為我都還沒有真正測試過,只是收集網路上和書上的例子寫成,還請大家補充。
如何檢查此手機是不是安裝了 Cydia
NSString *filePath = @"/Applications/Cydia.app";
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
// 檢查是不是有 Cydia 這個程式
}
一般來說 iOS 現在是多工,方便切換程式而不是像 Mac 或 PC 作業系統的背景執行,通常 JB 後會把背景執行這個功能打開就會用到 fork() 這個指令,所以檢查有沒有背景執行的功能(fork())就可以知道有沒有 JB。
int result = fork();
if (result > 0) {
     NSLog(@"JBed");
}else{
     NSLog(@"NO JB");
}
JB 之後,就會有心人士把一些要付費的 App 給破解,從此之後這個 App 就會被放到網路頁讓人任意下載。而有心力在做這個行為的同時會破壞掉這個 App 裡 info.plist 的 SignerIdentity,於是我們就來檢查。
NSBundle *bundle = [NSBundle mainBundle];
NSDictionary *info = [bundle infoDictionary];
if ([info objectForKey: @"SignerIdentity"] != nil)
{
    // 此程式可能被破解
}
以上三種方法提供給大家參考用。但我們寫 App 的人要還要再想清楚,JB 的人是不是有可能也會花錢買我們的 App。此時第三個方法好像比較可以保護我們自己的資產。如果提到破解 App 的問題,一開始 App 免費,然後用 in app Purchase 也許也可以是另一條保護自己 App 的方法。歡迎大家提出來討論。

2012年1月31日 星期二

出版界的大轉變

Apple 每次一推出新的作品,都造成業界的洗牌效應,App 的推出掌上型的 Game Console 被打在地上趴著,現在可能有些是稍為半蹲的姿態。
這次的 Education - iTunes U + iBooks + iBooks Author 會造成出版界的大洗牌嗎?
首先來看看假設我是出版商會採取什麼樣的手段。
有道是,放下它,接受它,了解它,幹掉它。
有憂患意識的出版界的人員們應該早就會體認到數位出版是遲早的事,問題在於不知道自己應該如何做才不會被這個洪流給沖走?所以,放下它,和接受它,應該是早就有的心理建設。
接下來就是如何了解它了。也就是說應該去學什麼東西?就從 Apple 提出的產品學起。
先來解釋一下出版社是如何和作者(也就是我)互動的。
我先用 iWorks 的 Pages 寫我的書的內容,排版也是用最簡單的幾行字,一張圖。但是後來把內容交給出版社的時候,出版社沒有 Mac 更別提 Pages 了,於是我轉換到 M$ Word 上面寫書的內容,還好我有先把一部分寫完的交給出版社,才可以早點發現這個問題,但是還有問題。我用的是 Mac 的 M$ Word,天知道和 Windows 的 Word 格式還不是完全一樣,orz. 所以還有花一些時間在排版上。這讓我體會到同樣的工具,同樣的格式是多麼的重要,尤其在趕時間的時候。
我就一邊寫,一邊請出版社校稿,原本以為文筆不錯的我,最多就是找一下錯字,沒想到還被修了幾個述敘的文法和語句,坦白說出版社改的語句比較暢通,有專業知識的人,不見得寫得出一般人懂的文語,這樣簡單的道理,總是一直再被驗證無誤。校稿,出版社的人工是少不了的。最後寫的差不多,是要決定書的封面和正式的排版了,我自己當然不會排,排版不是都要用 inDesign 排的嗎?我也知道,就算會用 inDesign 也不見得排得出好看的,還是把美編交給專業的吧。看愛書的我,還在逛二手書店的時候看到一本很舊的書的封面和我的書的封面有點像,還特地找出來和出版社討論,這時不得不讚美一下藍海,竟然在六日的時候和我通 e-mail 討論封面長像。
書一直在校,我一直在寫,到最後出版之後,除了每幾本書送給親人五十之外,出版社還要四處找大學的教授買,發電子報推銷。行銷的工作不會因為電子化而減少,而是要去學另一種方法。很容易產生書,就更要注重行銷,就好像 App 有 50多萬個,放上去之後就好像石沈大海。不行銷,只有死路一條。
如果我們歸納上面的說法,
出版界要學的就是
新的工具 - iBooks Author
如何善用校稿訂正功能
如何排版
在數位的世界怎麼行銷 - SEO, Social Network....
當然一些基本的,怎麼和 Apple 打交道,註冊,放書的內容,拆帳比例等等的知識
不過第一件事應該是
買一台 Mac - 對台灣大部分的出版社來說

2012年1月29日 星期日

iBooks Author - 3D Model

這篇文章是前篇 Apple Education 文章的延續,來探討一下 iBooks Author 中的加入 3D 物件的功能。也就是 Widgets 裡的 3D,請看下圖紅色框框之處。

當我們按下之後,很可能會看到底下的圖面
中間有個像原子軌道的畫面就是 3D 物件要呈現的地方。確定有選好這個物件,接著按下右上方的 inspector。就會出現可以選取的視窗,如下。
當然是選取 3D File 旁的 Choose... 按鈕啦。但先在這等等,我們從那裡生出來 3D File ?看一下這篇 Apple 的教學 我們發現需要一個 3D 的工具來輸出 dae 檔。dae 檔其實是 COLLADA 這個組織規範的檔案格式,也是大部分畫 3D 的工具都會支援的格式,我們查一下 wiki 會列出有那些工具。
Software tool
Application
  • ArcGIS
  • TNTmips
  • Google Earth - (release 4) has adopted COLLADA (1.4) as its native format for describing the objects populating the earth. Users can simply drag and drop a COLLADA (.dae) file on top of the virtual Earth.
  • Google SketchUp Pro (or any version of SketchUp starting with 8.0) can also be used to create .KMZ files: a zip file containing a KML file, a COLLADA (.dae) file, and all the texture images.
  • Mac OS X 10.6's Preview allows opening collada files for viewing in 3D.
  • OpenSimulator
  • Second Life
就請讀者挑自己喜歡的,下手。筆者呢就以 Google SketchUp 當做例子介紹,除了它是免費的之外,它還有 warehouse 可以直接使用很多別人畫好的 3D 物件。它還有很多教學有興趣的朋友不妨試試。畫好自己的 Model 之後可以直接在 SketchUP 輸出成 dae,首先如下選擇 Export -> 3D Model
然後會跳出視窗,選好 dae
之後回到 iBooks Author 選到此 dae,如下。
圖形可能會怪怪的,不過直接透過 Preview 在 iPad 用手指動看看,就會是一個可互動的 3D 物件。如下在 iPad 上的畫面