發佈日期:

簡易記帳APP範例

source code在此:範例檔案下載AppPrototype

難得周日在家,就把昨天老師說的練習做完
老實說其實我弄很久(大概有八~九小時跑不掉= =)
可見真的很不熟悉,debug之類都超級慢的

首先就是在跳去圖表的地方,
原本在實作實際功能前可以正常出現圖表,後來不知為何會當掉,
光這個無聊的bug就找了兩三小時(遮臉)

後來發現是因為下面這段程式碼

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        InputViewController * inputCon = segue.destinationViewController;
        inputCon.delegate = self;
}

因為只要是storyboard控制的頁面切換,都會呼叫prepareForSegue
我同時用storyboard去切換新增資料和圖表頁面,
所以圖表的segue.destinationViewController不是InputViewController就會跳錯誤。

在這邊也要說,老師說的inputCon.delegate等於setDelegate是很重要的
因為錯誤訊息一直說沒有setDelegate這個方法
結果我還一直傻傻看不懂是什麼意思~>”<~
(老師上課有說!妳有沒有在聽阿!)

然後第二個遇到的困難,就是我要在轉圖表畫面時,需要把現有資料傳至圖表畫面
一開始我還傻傻的在那又把CostViewController弄一個@protocol
想說要實作一個delegate機制,又是一方面要實作別人的delegate,又要是別人的protocol,
搞得我好混亂阿~

後來才發現delegate似乎是被呼叫者,要把資料傳給呼叫者時才需使用(不確定,有錯請指正)

後來為了要傳遞資料,我不去使用storyboard的切換頁面方式,改使用程式去自行切換頁面
以下為傳送列表資料的程式碼

- (IBAction)showPieChart:(id)sender {
    PieChartViewController * pieController = [[PieChartViewController alloc] init];
    [self.navigationController pushViewController:pieController animated:YES];
    [pieController showPieChart:self record:self.record];
}

【附記一下切換viewController的相關方式】

最後要做的是實作修改和刪除資料的功能
第一步是先將CostViewController實作UITableViewDelegate

@interface CostViewController : UITableViewController<inputViewControllerDelegate,UITableViewDelegate>

本來我還很害怕實作完還要設什麼delegate,或還要自己去呼叫該方法,
結果太令人開心了,只要實作了tableView,按table cell時他就會自己呼叫(灑花)

-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    //修改該筆資料
    InputViewController *inputCon = [self.storyboard instantiateViewControllerWithIdentifier:@"inputCon"];
    [self.navigationController pushViewController:inputCon animated:YES];
    [inputCon modifyData:self.record[indexPath.row] forKey:indexPath.row];
    inputCon.delegate = self;
}

不過這樣子我還是遇到了一個問題,就是叫出來的畫面是一片黑。
百思不得其解也找不出原因,
後來嘗試的把原本在storyboard裡InputViewController和CostViewController的連接關係拿掉,
突然畫面就又跑出來了。

初步推論是或許一個畫面若用storyboard來切換就會無法自己寫程式碼去切換,
所以當有一個畫面有兩個按鈕都可以連接到時,就需要都自己用程式碼去做掉切換的動作。

剩的就把功能實作完就大功告成囉!

畫面介紹:一進入APP時的畫面
螢幕快照 2013-08-18 下午2.56.15
新增/修改記帳資料的畫面
螢幕快照 2013-08-18 下午2.56.32
帳目總計圖表
螢幕快照 2013-08-18 下午2.56.38

source code在此:範例檔案下載AppPrototype

發佈日期:

上課筆記(四) – Naming Convention、記憶體管理

Naming Convention

  1. 命名原則:
    1. 具解釋性
    2. 清楚
    3. 不會混淆
  2. 類別名稱:
    1. 第一個字大寫
    2. 前置namespace(在新增專案時會有Class Prefix,就是在設定這個)
    3. 駝峰式的寫法
  3. 變數名稱
    1. 變數類型不需特別表明,可以用名稱去讓人聯想型別,例:
      BOOL isEditable;
      NSString * accountName;
      NSMutableArray * mailBoxes;
      UIImage * previewPaneImage;
      NSDictionary * messageDict;
  4. 方法名稱:可以清楚表明意思
  5. 參數名稱:避免和ivar同名

 記憶體管理(IOS沒有gc)

  1. 配置記憶體:alloc;清除記憶體:dealloc
  2. zomble:不該用到卻用到(值為nil);memory leak:已沒辦法存取卻未把記憶體清掉
  3. 使用arc比較容易發生zomble,不用arc則容易發生memory leak。
  4. 若是有一段程式碼之中會用到大量的記憶體,則可以用@autoreleasepoll{…}包起來
    缺點:速度會慢一些
    優點:記憶體較好(在ios裡面,記憶體較重要)
  5. strong與weak的差別:變數的宣告值strong代表這個變數會增加retain的值,而weak則不會。
    weak比較像依賴的關係,當今天主要strong的變數被刪除了,weak裡的值也會變為空值。
    而strong則會增加retain的值,主要變數被刪除了,因為retain還是大於1,所以變數的記憶體並不會被釋放。(要小心Memory leak)
發佈日期:

上課筆記(三) – Operation、Delegation、基本類別介紹

Operation

  1. 取得class資料的相關變數
    Class me = [obj class];
    NSString * name = [obj className];
    //判斷是否繼承於UIView
    if( [ obj isKindOfClass:[UIView class] ] ){
    NSLog(@"obj繼承於UIView");
    }
    //判斷是否是這個class的實體
    if( [ obj isMemberOfClass: [NSString class] ] ){
    NSLog(@"obj的類別是NSString");
    }
  2. 確認兩個變數指向同一個記憶體位置
    if(obj1 == obj2) {}

    確認兩個實體的值相同

    if([obj1 isEqual: obj2]){//使用者可自行在class裡面新增此一函數,來決定該如何判別兩個類別相同}
  3. 呼叫物件的描述,回傳字串 [obj description];//等於NSLog(@”%@”,obj);

Delegation

  1. 定義:物件要完成某件行為時利用別人定義好的某項功能來完成。
    所以專案第一個被呼叫的應該是Delegate裡的

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  2. xcode專案的main.m
    #import ㄑUIKit/UIKit.h;
    
    #import "AppDelegate.h"
    
    int main(int argc, char *argv[])
    {
      @autoreleasepool {
           //argc:在argv裡元素的個數,通常對應main的參數
           //argv:一串輸入值
           //UIApplication或其子類別實體的class name,如果值是nil則會認為是UIApplication。
           // NSStringFromClass([AppDelegate class] 系統做完事後要通知誰
           return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }

基本類別

  1. NSObject:最基本的物件
    [obj className];//自我檢視
    [obj isEqual:obj2]//物件比較
  2. NSString
    [NSString stringWithFormat:@"It is %@",@"Tom"];//格式化字串
    //常用method
    str=[str stringByAppendingString:"abc"];//加字串在尾端,會回傳str
    str=[str stringByAppendingFormat:"name %@",@"Tom"];//加格式化字串在尾端,會回傳str
    BOOL equ = [str isEqualToString:str2];//字串相同
    //比較兩字串相同的方法
    if([str compare:str2 options:NSLiteralSearch]){}
    if([str idEqualToString:str2]){
    //字串搜尋
    NSRange range = [str rangeOfString:str2];
    NSLog(@"str2位於str1的第%d的位置,長度為%d",range.location,range.length);
  3. NSMutableString:可在原本字串之間插字串(用insertString)
    NSMultableString *str = [NSMultableString string];
    [str appendString:@"test"];
    [str insertString:@"hello" atIndex:1];
    NSLog(str);//ThrlloEST
  4. Set:無順序性的集合,資料有惟一性(物件要比較是否相同須覆寫isEqual和hash)
    NSMutableSet:queue的概念,用在List把移出畫面的東西暫存。
    NSOrderedSet:依照加入的順序排(比起NSMutableSet)
    相關網頁:
    http://stackoverflow.com/questions/6545722/help-with-isequals-and-hash-in-iphone
  5. Array:有順序性的集合,當資料從中間刪除,剩的index會自動往前補。
    NSArray: 不可新增修改的array。
    NSMutableArray:可新增修改,保證是0,1,2,3的index不會跳號。
  6. Dictionary:存在key-value型式資料的集合
    NSDictionaryNSMutableDictionary
  7. 走訪所有元素的寫法
    for(NSString *ele in array){
           NSLog([ele description]);
    }
  8. NSNumber:才可以丟進set或array裡
  9. NSNull:為了要丟進array裡面,因舊式寫法array宣告nil代表尾端,所以要丟空值要改丟NSNull
  10. Scalar:把物件當陣列般存取。例:
    Car * car = [car new];
    
    car[1] = @"name"; //寫入scalar
    NSLog(@"%@",car[1]);//讀取scalar
    
    car[@"dict"] = @"value";//寫入object
    NSLog(@"%@",car[@"dict"]);//讀取object

    要注意的是,如果我們呼叫car[1]代表執行下面兩個函數而不代表真的是array

    - (id) objectAtIndexedSubScript:(NSInteger) index {
      return @"Car";
    }
    -(void) setObject:(id)thing atIndexedSubscript:(NSInteger) index{
       //在此設定index為index的值為thing
    }

    如果果們呼叫car[@”dict”]則是執行下面兩個函數

    -(id) objectForKeyedSubscript:(id)key{
        return @"dict";
    }
    -(void) setObject:(id) thing forKeyedSubscript:(id<nscopying>) key{
         //在此做設定
    }
發佈日期:

Flash時間軸運作相關注意點

遮罩相關:

當圖層在遮罩之下時,影格每次前進,所有的物件都會重新運算並重新產生

  1. 若有一個動態label在遮罩之下,若其原本的顯示的文字為”舊的值“,在影格1時,用script將其值設為”新的值“,當影格前進到下一個影格時,又會變回顯示”舊的值“(沒有關鍵影格也是)。
  2. 同理,如果我們在影格1時,在as裡指定某個MovieClip,當進入下一個影格時,原本在as指定的MovieClip會與當下畫面上的物件不同,而造成無法對其做操作的狀況,這時候應該要到某定點影格時,再在as裡對物件做指定的動作

關鍵影格相關:

每次重新經過一個關鍵影格,其物件都會重新產生。

  1. 若在影格1裡,有元件a b c,然後在影格2裡,有元件d e。當我們用as,在影格1裡指定a b c元件至某個變數裡,當時間軸跑到影格2,再跑回影格1。原本指定的變數裡面所存的影格,會是上一次影格1裡的元件,但會與現在在畫面上影格1顯示的元件不同
  2. 若某MovieClip的第1影格第5影格都是關鍵影格,在關鍵影格上的都有同樣的元件a b c。若我們在影格1時用AS指定元件abc,當影格跑到影格5時,畫面上所顯示的元件也會與影格1的元件不同(若沒關鍵影格的狀況下則會是相同的)。

效能相關:

  1. 形狀或顏色漸變,是每進入一次影格,便會整個圖層做重繪。因此他的漸變對象不能為元件,而需要是向量圖形。(耗效能)
  2. 傳統移動漸變,則是單純對元件的位置或大小做改變,元件本身不會重繪。因此對象一定要是元件。
  3. 重繪效能會與重繪區域大小有關,最耗效能的為向量漸層或色塊,因此若無必要,盡可能將元件改使用bitmap點陣形式。
  4. flv動畫在初始載入時會較花效能,但若是畫面上同時有多個動畫,則flv會較省效能。
發佈日期:

利用ant 構建和部署專案

Ant 可以代替使用 javac 、 java 和 jar 等命令來執行 java 操作,從而達到輕松的構建和部署 JAVA 項目的目的。

1. 利用ant 的javac命令來編譯JAVA程式

Ant 的javac命令用於實現編譯JAVA 程式的功能。下面來看一個簡單的例子:首先我們建立名為 JAVATestPro的JAVA項目,建立src目錄為源代碼目錄,在src目錄下建立HelloWorld.java這個類檔。該類檔的內容如下:

public class HelloWorld {
    public static void main(String[] args) {
       System.out.println("hello world!");
    }
}

同時在JAVATestPro項目的根目錄下建立build.xml 檔,在該檔中編譯sr 目錄下的JAVA檔,並將編譯後的class檔放入build/classes 目錄中,整個項目的目錄結構如下:

|JAVATestPro
|src
|build
|classes
|build.xml

在編譯前,需清除classes 目錄,該檔的內容如下:

<?xml version="1.0" ?>

<project name ="javacTest" default="compile" basedir=".">
<target name="clean">
<delete dir="${basedir}/build"/>
</target>
<target name="compile" depends ="clean">
<mkdir dir ="${basedir}/build/classes"/>
<javac srcdir ="${basedir}/src" destdir ="${basedir}/build/classes"/>
</target>
</project>

在項目根目錄(C:\ThinkInJAVACode\JAVATestPro)執行ant命令後,可在該目錄下發現新生成的build/classes子目錄,編譯後生成的HelloWorld.class檔就在該目錄下。

2. 使用java命令執行JAVA程式

Ant 中可以使用 java命令實現運行JAVA程式的功能。可以在上面的build.xml基礎上做修改來實現:

<?xml version="1.0" ?>
<project name ="javacTest" default="run" basedir=".">
<target name="clean">
<delete dir="${basedir}/build"/>
</target>
<target name="compile" depends ="clean">
<mkdir dir ="${basedir}/build/classes"/>
<javac srcdir ="${basedir}/src" destdir ="${basedir}/build/classes"/>
</target>
<target name="run" depends ="compile">
<java classname ="HelloWorld">
<classpath>
<pathelement path="${basedir}/build/classes"/>
</classpath>
</java>
</target>
</project>

接著,就可以在主控台看見輸出:” hello world!”

3. 使用jar命令生成jar檔

還可以在上例的基礎上更進一步,來生成jar包,可在run 這個 target 下再加上如下 target :

<?xml version="1.0" ?>
<project name ="javacTest" default="jar" basedir=".">
<target name="clean">
<delete dir="${basedir}/build"/>
</target>
<target name="compile" depends ="clean">
<mkdir dir ="${basedir}/build/classes"/>
<javac srcdir ="${basedir}/src" destdir ="${basedir}/build/classes"/>
</target>
<target name="run" depends="compile">
<java classname ="HelloWorld">
<classpath>
<pathelement path="${basedir}/build/classes"/>
</classpath>
</java>
</target>
<target name="jar" depends="run">
<jar destfile="helloworld.jar" basedir="${basedir}/build/classes">
<manifest>
<attribute name="Main-class" value="HelloWorld"/>
</manifest>
</jar>
</target >
</project>

其中,project的default 屬性設置為應設為jar,ant運行完畢後,可看到在項目的根目錄下生成了一個 helloworld.jar的jar包 。可通過運行以下命令來執行該jar包:

java -jar helloworld.jar

4. 使用war命令打包JAVAEE項目

建立一個JAVAEE項目,其中src 為JAVA源代碼目錄,WebContent為各jsp存放目錄,lib 為項目引用的的包的目錄。在WebTest項目目錄下建立了build.xml 檔,該檔為該工程的 Ant 構件檔。

|WebContent
|src
|build
|classes
|WebContent
|META-INF
|MANIFEST.MF
|WEB-INF
|lib
|classes
|HelloJSP.jsp
|build.xml

讀者可以 src 目錄下放入在前續例子中開發的 HelloWorld.java 檔,並在 WebContent下建立 HelloJSP.jsp 檔,其內容很簡單,就是輸出 Hello 資訊,代碼如下所示:

<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "HTTP://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta HTTP-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>war test for ant</title>
</head>
<body>
Hello JSP!Hello Ant!
</body>
</html>

接下來編寫 build.xml 檔,其內容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<project name ="WebTest" default ="war" basedir =".">
<property name ="classes" value ="${basedir}/build/classes"/>
<property name ="build" value ="${basedir}/build"/>
<property name ="lib" value ="${basedir}/WebContent/WEB-INF/lib"/>
<!-- 刪除build 路徑-->
<target name ="clean">
<delete dir ="${build}"/>
</target>

<!-- 建立build/classes 路徑,並編譯class 檔到build/classes 路徑下-->
<target name ="compile" depends ="clean">
<mkdir dir ="${classes}"/>
<javac srcdir ="${basedir}/src" destdir ="${classes}"/>
</target>

<!-- 打war 包-->
<target name ="war" depends ="compile">
<war destfile ="${build}/WebTest.war" webxml ="${basedir}/WebContent/WEB-INF/web.xml">
<!-- 拷貝WebRoot 下除了WEB-INF 和META-INF 的兩個檔夾-->
<fileset dir ="${basedir}/WebContent" includes ="**/*.jsp"/>
<!-- 拷貝lib 目錄下的jar 包-->
<lib dir ="${lib}"/>
<!-- 拷貝build/classes 下的class 檔-->
<classes dir ="${classes}"/>
</war>
</target>
</project>

在C:\ThinkInJAVACode\WebTest目錄下運行ant後,就生成了WebTest.war 檔了,然後可以將其放入Web容器(如Tomcat)的相應目錄下(${Tomcata安裝目錄}\webapps)運行該web項目了。

發佈日期:

ANT常用命令

1. copy 命令

copy主要用來對檔和目錄的複製功能。舉例如下:

eg1. 複製單個檔:

<copy file="original.txt" tofile="copied.txt"/>

eg2. 對檔目錄進行複製:

<copy todir="../dest_dir">
<fileset dir="src_dir"/>
</copy>

eg3. 將檔案複製到另外的目錄:

<copy file="source.txt" todir="../home/philander"/>

2. delete 命令

對檔或目錄進行刪除,舉例如下:

eg1. 刪除某個檔:

<delete file="/home/photos/philander.jpg"/>

eg2. 刪除某個目錄:

<delete dir="/home/photos"/>

eg3. 刪除所有的備份目錄或空目錄:

<delete includeEmptyDirs="true">
<fileset dir="." includes="**/*.bak"/>
</delete>

3. mkdir 命令

創建目錄。 eg :

<mkdir dir="/home/philander/build/classes"/>

4. move 命令

移動檔或目錄,舉例如下:

eg1. 移動單個檔:

<move file="sourcefile" tofile="destfile"/>

eg2. 移動單個檔到另一個目錄:

<move file="sourcefile" todir="movedir"/>

eg3. 移動某個目錄到另一個目錄:

<move todir="newdir"> <fileset dir="olddir"/></move>

5. echo 命令

該任務的作用是根據日誌或監控器的級別輸出資訊。它包括 message 、 file 、 append 和 level 四個屬性,舉例如下

<echo message="Hello,ANT" file="/home/philander/logs/ant.log" append="true">
發佈日期:

上課筆記(二) – Objective-C語言介紹、物件存取

Objective-C語言

  1. @代表物件
    [@”Hello world”] => 方括弧是存取物件裡的方法
    例:

    NSString * str =@"World";
    str = [NSString stringWithFormat:@"Hello"];
    NSLog(@"str is: %@",str);
  2. Class:類別
    Object:物件及實體,包括
    (a) 名字(Name)
    (b) 屬性(State):field, attribute, member, 屬性, 狀態, 成員
    (c) 行為(Behavior):method, action, member function
    Message:使用方來傳遞訊息。例:NSString的StringWithString
    螢幕快照 2013-08-02 下午5.49.59
    PS: 若在#import <Foundation/Fundation.h>下面加上@Class Car;,代表把Car當作class,在.m檔才import。
  3. self(存取自己),只能用在implementation的『{』至『@end』之間。
  4. variable宣告:
    NSString * name = [[NSString alloc] init];
  5. 宣告時,前方的+或-代表是否要透過init alloc來回傳物件。
    +號是不用透過init alloc傳回物件
  6. 要公開(public)的放在.h,不公開的放在.m
  7. NSStrung * name = [[NSString alloc] init];
    等同於 NSString * name = [NSString new];
    =>配置記憶體與初始化是產生物件後的第一個動作
  8. Obj C可以使用id去動態新增method,所有obj c的語言都會被編譯成c語言。

Message Syntax

  1. 『物件.xxx』所存取的不是屬性,而是方法。是存取物件裡面的getter和setter。
    label.text = @"Description"; //等於 [label setText:@"Description"];
    NSString *str = label.text; //等於 NSString*str = [label text];
  2. 自動產生getter和setter
    @property int age; //會自動幫我們產生getter和setter
    @property (strong) NSString * name; //如果是物件,前面要加strong或weak
  3. 如果interface和implementation在同個檔案,在interface裡用@property,在implementation裡需加上@synthesize
    @synthesize age;//自動產生的變數名稱會是_age

    若分開為.h及.m檔,則.h檔宣告後,.m檔裡不用寫就會自動產生。

  4. 動態型別 – id:任何繼承NS Object的物件型別,宣告方式如下
    id someObject; //不用加*號 ( <s>id * someObj</s> )

    用法例子:在apple在view事件觸發時要接收事件,會希望任何class都可以去接收該事件都可以。
    當不知道是誰接收時,就會用id去宣告

  5. 空指標nil,物件型別的空值,等同於NULL。若將nil丟給方法則會像石沉大海一樣什麼都不發生也不會有error。=>經指正會產生空值error
  6. Obj C的BOOL是傳YES(true)及NO(false)。
  7. 要判斷現在的class裡是否有某個函數要用Selector,回傳的型別是SEL。使用範例如下
    -(void)methodWithNoArguments;
    SEL noArgumentSelector = @selector(methodWithNoArguments);
    
    -(void)methodWithOneArgument:(id)argument;
    SEL oneArgumentSelector = @selector(methodWithOneArgument:); // notice the colon here
    
    -(void)methodWIthTwoArguments:(id)argumentOne and:(id)argumentTwo;
    SEL twoArgumentSelector = @selector(methodWithTwoArguments:and:); // notice the argument names are omitted

    Selectors are generally passed to delegate methods and to callbacks to specify which method should be called on a specific object during a callback. For instance, when you create a timer, the callback method is specifically defined as:

    -(void)someMethod:(NSTimer*)timer;

    So when you schedule the timer you would use @selector to specify which method on your object will actually be responsible for the callback:

    @implementation MyObject
    
    -(void)myTimerCallback:(NSTimer*)timer
    {
        // do some computations
        if( timerShouldEnd ) {
          [timer invalidate];
        }
    }
    
    @end
    
    // ...
    
    int main(int argc, const char **argv)
    {
        // do setup stuff
        MyObject* obj = [[MyObject alloc] init];
        SEL mySelector = @selector(myTimerCallback:);
        [NSTimer scheduleTimerWithTimeInterval:30.0 target:obj selector:mySelector userInfo:nil repeats:YES];
        // do some tear-down
        return 0;
    }

    In this case you are specifying that the object obj be messaged with myTimerCallback every 30 seconds.
    假如一個function在該做的事完成後要執行selector callback,可以類似下面這樣寫

    -(void) someMethod:(id)handler selector:(SEL)selector {
        // some codes here...
    
        // execute callback function
        if( handler != nil &amp;&amp; selector != nil &amp;&amp; [handler respondsToSelector:selector] ) {
            [handler performSelector:selector];
        }
    }

    來源:http://stackoverflow.com/questions/297680/how-do-sel-and-selector-work-in-iphone-sdk

  8. 判斷class是否有該函數使用
    if([obj respondsToSelector:action]) { ... }
發佈日期:

ant 腳本編寫 – 關鍵元素

1. project元素

project 元素是 Ant 構件檔的根項目, Ant 構件檔至少應該包含一個 project 元素,否則會發生錯誤。在每個 project 元素下,可包含多個 target 元素。接下來向讀者展示一下 project 元素的各屬性。
  1. name 屬性
    用於指定 project 元素的名稱。
  2. default 屬性
    用於指定 project 默認執行時所執行的 target 的名稱。
  3. basedir 屬性
    用於指定基路徑的位置。該屬性沒有指定時,使用 Ant 的構件檔的附目錄作為基準目錄。
<?xml version="1.0" ?>
<project name ="antPro" default ="getBaseDir" basedir ="C:/ThinkInJAVACode">
<target name="getBaseDir">
<echo message="The base dir is: ${basedir}"/>
</target>
</project>
從上例可以看出,在這裏定義了default 屬性的值為getBaseDir ,即當運行ant 命令時,如果沒有指明待執行的target,則將執行默認的target–getBaseDir 。此外,還定義了basedir 屬性的值為 “C:/ThinkInJAVACode” ,進入”C:/ThinkInJAVACode” 後運行ant 命令,得一下結果:

Buildfile: C:\ThinkInJAVACode\build.xml
sayBaseDir:
[echo] The base dir is: C:\ThinkInJAVACode
BUILD SUCCESSFUL
Total time: 0 seconds

2. target 元素

target為Ant的基本執行單元,它可以包含一個或多個具體的任務。多個target 可以存在相互依賴關系。它有如下屬性:
  1. name 屬性
    指定 target 元素的名稱,這個屬性在一個 project 元素中是唯一的。我們可以通過指定 target 元素的名稱來指定某個 target 。
  2. depends 屬性
    用於描述 target 之間的依賴關系,若與多個 target 存在依賴關系時,需要以「,」間隔。 Ant 會依照 depends 屬性中 target 出現的順序依次執行每個 target 。被依賴的 target 會先執行。
  3. if 屬性
    用於驗證指定的屬性是否存在,若不存在,所在 target 將不會被執行。
  4. unless 屬性
    該屬性的功能與 if 屬性的功能正好相反,它也用於驗證指定的屬性是否存在,若不存在,所在 target 將會被執行。
  5. description 屬
    性該屬性是關於 target 功能的簡短描述和說明。
舉例說明如下:
<?xml version="1.0" ?>
<project name ="targetPro" default="targetB">
<target name="targetA" if ="ant.java.version">
<echo message ="JAVA Version: ${ant.java.version}"/>
</target>
<target name="targetB" depends ="targetA" unless ="philander">
<description>
a depend example!
</description>
<echo message ="The base dir is: ${basedir}"/>
</target>
</project>
從以下結果後可以看到,我們運行的是名為 targetB 的target ,由於它依賴於targetA ,所以 targetA 將首先被執行,同時因為系統配置了JDK,所以 ant.java.version 屬性存在,執行了targetA,輸出資訊:”[echo] JAVA Version: 1.6 “,targetA 執行完畢後,接著執行 targetB ,因為philander不存在,而unless屬性是在不存在時進入所在target 的,由此可知 targetB 得以執行,輸出資訊:

 

[echo] The base dir is: C:\ThinkInJAVACode”。
Buildfile: C:\ThinkInJAVACode\build.xml
targetA:
[echo] JAVA Version: 1.6
targetB:
[echo] The base dir is: C:\ThinkInJAVACode
BUILD SUCCESSFUL
Total time: 0 seconds

 

3. property 元素

property元素可看作參量或者參數的定義,project 的屬性可以通過 property 元素來設定,也可在 Ant 之外設定。若要在外部引入某檔,例如 build.properties 檔,可以通過如下內容將其引入:

<property file="build.properties"/>

property 元素可用作 task 的屬性值。在 task 中是通過將屬性名放在「 ${ 」和「 } 」之間,並放在 task 屬性值的位置來實現的。
Ant 提供了一些內置的屬性,它能得到的系統屬性的清單與 JAVA 文檔中 System.getPropertis() 方法得到的屬性一致,這些系統屬性可參考 sun 網站的說明。同時, Ant 還提供了一些它自己的內置屬性,如下:

  1. basedir:project 基目錄的絕對路徑;
  2. ant.file:buildfile的絕對路徑,上例中ant.file值為C:\ThinkInJAVACode\build.xml;
  3. ant.version:Ant 的版本資訊,本文為1.8.1 ;
  4. ant.project.name:當前指定的project的名字,即前文說到的project的name屬性值;
  5. ant.java.version:Ant 檢測到的JDK版本,本文為 1.6 。

舉例說明如下:

<? xml version="1.0" ?>
<project name ="propertyPro" default ="example">
<property name ="name" value ="philander"/>
<property name ="age" value ="25"/>
<target name ="example">
<echo message ="name: ${name}, age: ${age}"/>
</target>
</project>

上例中用戶設置了名為name 和age的兩個屬性,這兩個屬性設置後,在下文中可以通過 ${name}${age} 分別取得這兩個屬性值。

發佈日期:

上課筆記(一) – 專案運作流程、c語言概論、指標與物件

課程資訊

  1. 上課教師:潘聖文 Michael Pan ( scentsome@gmail.com) > 認真好老師推!
  2. 課程名稱:資策會IPhone應用軟體開發入門篇

運作流程

  1. main function為固定進入點
  2. 在iphone app開發裡面,一個一整頁的畫面是Scene,會有對應一個Controller
  3. 切換不同Scene的叫做View Controller,跳出如輸入框或選取框的這種(非整頁切換),則不需View Controller
  4. Navigation Controller是只有上面的Bar(用以控制頁面切換),會將View Controller塞進裡面。
  5. 所有Object特有的類別都會加上NS開頭(因為是某個縮寫為NS的公司開發的)
  6. Objective-C可以在執行時動態產生Code。
  7. 整個Design Flow圖如下
    螢幕快照 2013-08-02 下午4.18.20

開始之前

    1. 變數:代表記憶體的編號,型別決定占記憶體多大的位置,變數則是存放記憶體起始位置。
      NSLog(@"%d",varA); //只要是OBJ C型別的東西都要加@來存取(物件則用%@)
    2. Function宣告
      cal(int a, int b);
      int main(int argc, const char * argv[]){
        int a=5;
        float b=6;
        cal(a,b); //呼叫函數
        return 0;
      }
      cal(int a,int b){
        printf("a+b=%d",(a+b));
      }
    3. ios程式的基本組成是由三個frameworks:
      (a) UIKit:給特殊樣式的ui
      (b) Core Graphics:畫圖
      (c) Foundation:C和OBJ C用的
      ps:要自己加可以按Target=>Summary=>Linked Frameworks and Libraries=>+
    4. 副檔名:表頭檔.h和內容檔.m及.mm(要用view一定要用.m;要像視訊則可用.mm)

Pointer & Object 指標與物件

  1. Pointer在C裡面代表存放的是一個記憶體位置
    int a = 5;
    int * pa;//因此所有obj c裡面所有的物件,只要他是存放記憶體位置,都需要用指標型態去寫
    pa = &amp;a;//放的是一個記憶體位置
  2. Struct是型別,也就是class(類別)
    struct Date{
       int day;
       int month;
       int year;
       void ( * formatedDate ) (struct Date date);
    }
    void formatedFunction(struct Date date){
       printf("The day is %d, %d/%d",date.year, date.month, date.day);
    }
    struct Date date = {3,10,1970};
    today.formatedDate = formatedFunction;
    today.formatedDate(today);
  3. Function是存放動作,其記憶體是存在stack裡
  4. 所以Objective C程式的記憶體位置配置這樣的
    螢幕快照 2013-08-02 下午5.01.06
    Stack的部份是不用管理的,因為用完就沒了,而在Object C裡需要去做記憶體管理的部份則為Heap的區塊。
    所以當我們在Obj C裡宣告了某個物件,必需用

    a = malloc(sizeof(int));//會產生在heap,產生記憶體位置,可做記憶體管理。
  5. Static variable(靜態變數),會放在Data Segment。
  6. 所有的View Object都會對應到一個型別(Custom Class那邊去設定)
    螢幕快照 2013-08-02 下午5.17.09
發佈日期:

AS3.0小數運算BUG

今天處理帶錢問題時,發現AS3的Number相減的一個問題
討論串如下
http://zengrong.net/post/1186.htm
http://blog.csdn.net/bill1315/article/details/8574109

因此在撰寫程式時,

應盡量避免直接將兩個帶小數點的NUMBER做運算
而應該以整數型態做運算,運算完後再做小數點的位移

或許對一些人而言這是已知的事
但還是希望能夠分享一些自己曾遇到的錯誤以避免大家再發生相同問題~

看下面的代碼:

1
2
3
4
var n1:Number = 0.7;
var n2:Number = 0.4;
trace(n1 - n2);
//輸出 0.29999999999999993

簡單說,就是兩個一位小數相減,差為何不是一位小數?
經測試,乘法也有同樣的問題。

GOOGLE找到了Flex團隊的一個回覆:http://old.nabble.com/Float-number-calculation-in-AS3-td18447329.html

從回覆看,AS3的Number與JAVA或C++的double類似,採用二進制分數而非十進制分數保存浮點部分,因此會導致不夠精確。這是語言的設計思路所致。當然,從另一個思路看,它也是個BUG。