Sean's Note: 10月 2014

2014年10月30日 星期四

Object-C 語法摘要

類別、物件及方法

  1. Case Sensitive
  2. C:
    print("Hello %d", 1);
    Object-C:
    NSLog(@"Hello %i", 1); // NSLog 會自動換行
  3. C:
    a.print(2);
    Object-C:
    [ClassOrInstance method : params] -> [a print : 2];
  4. C:
    ClassA* A = new A();
    Object-C:
    ClassA* A = [[ClassA alloc] init];
    ClassA* A = [ClassA new];
  5. Object-C 支援 id 泛型, NSLog 用 "%p"。

迴圈、制定決策

  1. if, while, for, switch 的用法幾乎和 C 沒什麼不同。
    Note: 只有當 if (0) 的時侯為條件不成立,包括 nil 和 NO。
  2. BOOL 是用 YES/NO 表示,而不是 true/false。

類別、繼承

  1. Accessor Method 可以直接用下列語法表示:
    @interface ...
    @property int a;

    @implementation ...
    @synthesize a;   // XCode 4.5 之後 @synthesize 可省略
  2. 宣告於介面區段是屬於 public 的,而實作區段的的變數是屬於 private 的。
  3. 可用 #import "XYPoint.h" 也可用 @class XYPoint; 來引用類別,而使用
    @class 指令比較有效率,因為編譯器不需要處理整個 XYPoint.h。

類目與協定

  1. 多了 category 跟 protocol 的用法。( protocol 類似於 Java 的 interface)

Blocks


  1. 以 ^ 為開頭。
  2. 多當作 callback 來使用。
  3. 宣告在 blocks 之前的區域變數可以在 block 內引用(唯讀),除非在宣告變數時加上 __block。
  4. 在 block 裡引用 self 將會造成 Memory cycles,試著使用 weak reference:
    __weak MyClass *weakSelf self;


Ref: 精通 Object-C 程式設計 第六版

2014年10月24日 星期五

[Android 5.0] Vector Drawables

從 Android 5.0 開始,Drawable 新增了可縮放向量圖形 (SVG) 的用法,

優點是可以任意縮放圖片卻不會失真。

只要在 XML 檔裡定義即可使用,下面是官方所提供的範例(改成紅色的):

<!-- res/drawable/heart.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- intrinsic size of the drawable -->
    android:height="256dp"
    android:width="256dp"
    <!-- size of the virtual canvas -->
    android:viewportWidth="32"
    android:viewportHeight="32">

  <!-- draw a path -->
  <path android:fillcolor="#ff0000" 
           android:pathdata="M20.5,9.5
                             c-1.955,0,-3.83,1.268,-4.5,3
                             c-0.67,-1.732,-2.547,-3,-4.5,-3
                             C8.957,9.5,7,11.432,7,14
                             c0,3.53,3.793,6.257,9,11.5
                             c5.207,-5.242,9,-7.97,9,-11.5
                             C25,11.432,23.043,9.5,20.5,9.5z">
  </path>
</vector>
圖1. Heart


Vector 詳細有哪些屬性可以設定,可以參考新增的 VectorDrawables 類別

pathdata 中語法和 SVG 的語法一樣 M 指的是 moveto,C 是 curveto,z 是 closepath,

大寫為絕對位置,小寫為相對位置,更多 pathdata 的用法可以直接參考 SVG 的文件

畫了個西瓜來當練習:

<!-- res/drawable/heart.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:height="256dp" 
           android:viewportheight="32" 
           android:viewportwidth="32" 
           android:width="256dp" >

  <!-- watermelon-->
  <path android:fillcolor="#ff0000" 
           android:strokecolor="#086D08" 
           android:strokewidth="1"
           android:pathdata="M3,3 
                             C3,13 23,13 23,3"  />
  
  <!-- seed-->
  <path android:fillcolor="#000000" 
           android:strokecolor="#000000" 
           android:strokewidth="0.5"
           android:pathdata="M5,4 
                            a0.2,0.2 0 1,0 0.4,0 
                            a0.2,0.2 0 1,0 -0.4,0"  />
  
  <!-- seed-->
  <path android:fillcolor="#000000" 
           android:strokecolor="#000000" 
           android:strokewidth="0.5"
           android:pathdata="M8,6 
              a0.2,0.2 0 1,0 0.4,0 
              a0.2,0.2 0 1,0 -0.4,0"  />
  
  <!-- seed-->
  <path android:fillcolor="#000000"
           android:strokecolor="#000000" 
           android:strokewidth="0.5" 
           android:pathdata="M12,8 
              a0.2,0.2 0 1,0 0.4,0 
              a0.2,0.2 0 1,0 -0.4,0"  />
    
  <!-- seed-->
  <path android:fillcolor="#000000" 
           android:strokecolor="#000000" 
           android:strokewidth="0.5"
           android:pathdata="M14,5 
                            a0.2,0.2 0 1,0 0.4,0 
                            a0.2,0.2 0 1,0 -0.4,0"  />
    
  <!-- seed-->
  <path android:fillcolor="#000000" 
           android:strokecolor="#000000" 
           android:strokewidth="0.5"           
           android:pathdata="M18,6 
                            a0.2,0.2 0 1,0 0.4,0 
                            a0.2,0.2 0 1,0 -0.4,0"  />
    
  <!-- seed-->
  <path android:fillcolor="#000000" 
           android:strokecolor="#000000" 
           android:strokewidth="0.5"
           android:pathdata="M20,4 
                             a0.2,0.2 0 1,0 0.4,0 
                             a0.2,0.2 0 1,0 -0.4,0"  />


圖2. Watermelon


2014年10月22日 星期三

Use Enum to implement finite state machine

範例:
public enum StateMachine {
 
    INITIAL {
        @Override
        public StateMachine next() {
            return SECOND;
        }
    },
    SECOND {
        @Override
        public StateMachine next() {
            return THIRD;
        }
    }
    // ... other states
    
    public abstract StateMachine next();
    
    // ... other methods
}

2014年10月15日 星期三

How to prevent the view from restoring it's state after restart?

View 有個屬性 android:saveEnabled,預設為 true,只要把它設成 false,
系統就不會幫你回復它的狀態(View.onSaveInstanceState() 不會被呼叫),
另外要注意的是,該 flag 僅對自己有效,不會影響其 childs。

Ref: http://developer.android.com/reference/android/view/View.html#attr_android:saveEnabled


2014年10月1日 星期三

Running C/C++ on Android with NDK [Updated]

需要準備的環境

  1. Eclipse + Android SDK: 基本的 Android 開發環境
  2. Android NDK: 讓 Android 能透過 JNI 去執行 C/C++ 語言的必要套件
  3. Eclipse NDK: Eclipse 的 plugin 套件,方便管理與建立 NDK 的專案
    Work with: https://dl-ssl.google.com/android/eclipse/
    安裝好之後要設定 Android NDK 的路徑:
    Window -> Preferences -> Android -> NDK -> NDK Location:

    如果 NDK Path 擺在 Program Files 或 Program Files (x86) 底下,在 Build Project 時,
    可能會出現以下錯誤:
    "C:\\Program Files (x86)\\Android\\android-ndk-r10b\\ndk-build.cmd" all
    ERROR: NDK path cannot contain any spaces!

    解決方法:
    C:\Program Files -> C:\progra~1
    C:\Program Files (x86) -> C:\progra~2
Note: NDK r9 的版本之後已內建 toolchains,所以不需要另外安裝 Cygwin。

新建一個專案


新增一個  C:\Program Files (x86)\Android\android-ndk32-r10b\samples\hello-jni 專案,

然後在 Project 上按右鍵 -> Android Tools -> Add Native Support...

除錯


除錯時要將 Project -> Properties -> C/C++ Build -> Builder Settings -> Build Command:

加上 ndk-build NDK_DEBUG=1,建置時才會產生除錯所需要的檔案。

在這之後可能會遇到兩個問題:
  1. 無法在 .c 或 .cpp 檔上設置中斷點?
    Run -> Breakpoint Types  -> C/C++ Breakpoints
  2. 設完中斷點後,卻沒有停在中斷點上?
    No symbol table is loaded. Use the "file" command.
    由於 GDB debugger 需要一點時間運算,而 GDB 可能還沒載入 Library 的 Symbol,
    如果中斷點設得太早可能會被忽略,
    解決的辦法請參考:
    http://www.codeproject.com/Articles/493043/Why-your-Android-NDK-breakpoints-might-fail-and-ho