2011年12月27日 星期二

Android - Bluetooth API

  • 掃描Bluetooth裝置
  • 查詢配對Bluetooth裝置
  • 建立RFCOMM頻道
  • 與Bluetooth裝置連結
  • 與Bluetooth裝置傳輸數據
  • 管理多個Bluetooth連結

Permission -----

  • android.permission.BLUETOOTH
  • android.permission.BLUETOOTH_ADMIN

-----

Android Bluetooth API -----
  • BluetoothAdapter
    • Bluetooth接頭
    • 取得配對的device
    • 實體化bluetooth裝置 - BuletoothDevice
      • 請求連結 - BluetoothSocket
        • 與bluetooth裝置交換資訊
        • 透過InputStream和OutputStream傳輸資料
      • 裝置的相關資訊
  • BluetoothServerSocket
    • 等待buletooth連接請求
-----

2011年12月15日 星期四

iOS - SQLIte - FMDB

FMDB為一個方便使用iOS裡的sqlite框架,主要物件為:
  • FMDatabase 提供方法來透過SQL與DB溝通
  • FMResultSet 與Java的Cursor物件類似

產生DB
    // 設定Label元件在文字內容超過框架時的樣式
    content.lineBreakMode = UILineBreakModeWordWrap;
    // 設定Label元件最多顯示的行數,0為不限
    content.numberOfLines = 0;
    // 透過NSFileManager取得Document的路徑
    NSURL* url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    // Document下新增DB檔案
    NSString* dbPath = [[url path] stringByAppendingPathComponent:@"myDB.db"];
    
    // 透過FMDatabase物件與DB溝通
    db = [FMDatabase databaseWithPath:dbPath];
    
    if(![db open])
    {
        NSLog(@"Could not open database.");
    }
    if(![db executeUpdate:@"CREATE TABLE IF NOT EXISTS info (id INTEGER PRIMARY KEY, name TEXT, tel TEXT)"])
         {
             NSLog(@"Could not creat table (%@)", [db lastErrorCode]);
         }

插入資料
// VALUES後的格式需使用範例這樣的方法,否則會出錯

    if(![db executeUpdate:@"INSERT INTO info (name, tel) VALUES (?, ?)",@"Vince",@"9988765"])
    {
        NSLog(@"Could not insert");
    }

取得資料
FMResultSet* rs = [db executeQuery:@"SELECT * FROM info"];

    
    // 印出所有Query到的資料
    while([rs next])
    {
        int _id = [rs intForColumn:@"id"];
        NSString* name = [rs stringForColumn:@"name"];
        NSString* tel = [rs stringForColumn:@"tel"];
        
        NSMutableString* strTemp = [NSMutableString stringWithString:content.text];
        if([strTemp compare:@"Label"])
        {
            [strTemp appendFormat:@"%d-%@-%@\n", _id, name, tel];
            content.text = strTemp;
        }else
        {
            content.text = [NSString stringWithFormat:@"%d-%@-%@\n", _id, name, tel];
        }
    }

2011年12月14日 星期三

iOS - 指定不使用ARC機制的程式

Q:在iOS 5之後的版本新增了ARC機制來讓系統自動回收記憶體,但遇到需要自行管理記憶體時怎麼辨?


A:可以在TARGETS > Build Phases > Compiler Sources中,在想要自行管理記憶體的程式上點兩下,並加入“-fno-objc-arc”參數即可


2011年12月12日 星期一

iOS - Training (13) - 修飾詞

static, public -----
  • "+": 與Java的static相同,執行完後面的行為後隨時會被回收
  • "-": 與Java的public類似(但private方法的前面也是使用此符號),執行完後面的行為後因為有實體的記憶體位置,故會放入release pool裡等待釋放

@interface TEST: NSObject 
// 公開方法
- (void)publicMethod;

// 靜態方法
+ (void)staticMethod;
@end

使用公開方法
TEST* test = [TEST alloc] init];
[test publicMethod];
[test release];

使用靜態方法
[TEST staticMethod]
-----

@property -----
  • 默認屬性
    • readwrite 自動生成存取器setter、getter
    • assign 處理基礎類型,如int、float...
  • 修飾屬性
    • natomic 與Java的synchronized類似,在多執行緒時保護參數的同步
    • readonly 只生成getter不會有setter方法
    • copy 與Java的clone類似,複製一個與原物件不同記憶體位置的新物件
    • retain 自動retain物件
TEST.h
@interface TEST: NSObject {
    NSString* param;
}
@property  (nonatomic, retain) NSString *param;
@end
TEST.m
@implementation TEST


@synthesize param;


- (id)init{}
@end
-----

參數的@public, @protected, @private -----


@interface TEST: NSObject {
    @public
        NSString* publicString;
   
    @protected
        NSString* protectedString;
   
    @private
        NSString* privateString;
}
@end

-----

方法的private宣告 -----
  • 寫在實現的文件中,此範例為TEST.m
  • 需在@implementation上描述
#import "TEST.h"

@interface TEST (private)
- (void) privateMethod
@end

@implementation TEST

- (id)init
{
  ...
}

- (void)privateMethod
{
  ...
}
@end
-----

2011年12月11日 星期日

iOS - Xcode 4 加入 Library 的方法

與原來Xcode 3的方法不大一樣,步驟如下:

這個範例目的要加入sqlite3的library。

1. 點選Project中的TARGETS選項

2. 在右邊的顯示中選擇"Build Phases",點擊"Link Binary With Libraries“下方的”+“,會出現很多library,這裡選取了libsqlite3.0.dylib。

2011年12月7日 星期三

iOS - Training (12) - UITableView

繼承UIScrollView。適用在要list出清單時。


屬性說明
  • 風格上分為Plain與Grouped。Plain較為方正,Grouped較為圓滑。
  • Table view由多個section組成,section包含多個cell。
  • NSIndexPath物件用來指引點擊的cell在哪個section中的第幾個cell。
TableView.m
- (void)viewDidLoad

{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    myTable.dataSource = self;
    myTable.delegate = self;
    
    dataArray = [[NSArray alloc] initWithObjects:@"one", @"two", @"three", @"four", @"five", nil];
}

// 決定section的個數,return 1表示只有一個section
- (NSInteger)numberOfSectionInTableView:(UITableView *)tableView
{
    return 1;
}

// 因為只有一個section,故直接回傳dataArray count,若有多個section要加if-else
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [dataArray count];
}

// 決定所要回傳的cell
- (UITableView *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 定義一個名稱,供reuse queue使用
    static NSString* CellIdentifier = @"Cell";
    
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // 一開始還沒有queue時,會initial一個新的queue
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = [dataArray objectAtIndex:indexPath.row];
    
    return cell;
}

// 取得使用者所按到的cell
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"Selected %@", [dataArray objectAtIndex:indexPath.row]);
}

UITableViewCell 樣式-----
AccessoryType = UITableViewCellAccessoryDisclosureIndicator

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    myTable.dataSource = self;
    myTable.delegate = self;
    
    dataArray = [[NSArray alloc] initWithObjects:@"one", @"two", @"three", @"four", @"five", nil];
    subArray = [[NSArray alloc] initWithObjects:@"1", @"2", @"3", @"4", @"5", nil];
}


// 決定所要回傳的cell

- (UITableView *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 定義一個名稱,供reuse queue使用
    static NSString* CellIdentifier = @"Cell";
    
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // 一開始還沒有queue時,會initial一個新的queue
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = [dataArray objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [subArray objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
    return cell;
}

AccessoryType = UITableViewCellAccessoryDetailDisclosureButton


// 決定所要回傳的cell

- (UITableView *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 定義一個名稱,供reuse queue使用
    static NSString* CellIdentifier = @"Cell";
    
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // 一開始還沒有queue時,會initial一個新的queue
    if(cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = [dataArray objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [subArray objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    
    return cell;
}

// 當按下藍色按鈕時,呼叫此方法
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"Press %@ button", [dataArray objectAtIndex:indexPath.row]);
}
-----

資料出處《Object-C與iOS開發入門》

2011年12月6日 星期二

iOS - Training (11) - UIScrollView

用於瀏覽內容畫面比Device畫面還大時,可以藉由托拉、放大、縮小的方式調整畫面。
參數:
  • contentSize: 決定UIScrollView可以scroll的範圍,通常UIScrollView的size會比contentSize來的小。
  • contentOffset: UIScrollView左上角的點與content邊界的遍移值。在托拉UIScrollView時,此值會一直變化。
ViewController.h
加入UIScrollView與UIImageView元件
@interface ViewController : UIViewController

{
    IBOutlet UIScrollView *myScroll;
    UIImageView* contentImgView;
}
@end

ViewController.m

- (void)viewDidLoad

{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    int imgWidth = 352;
    int imgHeight = 500;
    
    contentImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minami.jpg"]];
    contentImgView.frame = CGRectMake(0.0, 0.0, imgWidth, imgHeight);
    
    myScroll.contentSize = CGSizeMake(imgWidth, imgHeight);
    [myScroll addSubview:contentImgView];
    
    // 加入放大縮小功能
    myScroll.delegate = self; // 會去調用viewForZoomingInScrollView方法
    myScroll.maximumZoomScale = 1;
    myScroll.minimumZoomScale = myScroll.bounds.size.height / contentImgView.bounds.size.height;
    
    // 畫面起始大小與內容大小一樣
    [myScroll zoomToRect:CGRectMake(0.0, 0.0, imgWidth, imgHeight) animated:YES];
}

// 加入此方法才會被調用放大縮小功能
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return contentImgView;
}

分頁效果 (類似Android的Gallery)-----

- (void)viewDidLoad

{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    int imgNum = 3;
    float imgWidth = 240;
    float imgheight = 240;
    
    myScroll.contentSize = CGSizeMake(imgNum*imgWidth, imgheight);
    
    for(int i = 0;i < imgNum;i++)
    {
        UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"page%d.jpg", i+1]]];
        imageView.frame = CGRectMake(i*imgWidth, 0, imgWidth, imgheight);
        
        [myScroll addSubview:imageView];
    }
    myScroll.pagingEnabled = YES; // 分頁效果
    myScroll.delegate = self; // 調用UIScrollViewDelegate裡的scrollViewDidScroll方法
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGRect bounds = scrollView.bounds;
    NSLog(@"Bounds %f, %f, %f, %f", bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height);
}
-----

資料出處《Object-C與iOS開發入門》

2011年12月5日 星期一

iOS - Training (10) - UITabBarController


新增繼承UIViewController的Controller A和Controller B,並在xib檔裡加入label

在Delegate裡實現

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{
    // Override point for customization after application launch.
    UITabBarController* myTab = [[UITabBarController alloc] init];
    ControllerA* conA = [[ControllerA alloc] initWithNibName:@"ControllerA" bundle:nil];
    ControllerB* conB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil];
    
    conA.tabBarItem.title = @"Controller A";
    conA.tabBarItem.image = [UIImage imageNamed:@"apple.png"]; // 這二段也可寫在ControllerA的viewDidLoad方法裡,範例如下
    conB.tabBarItem.title = @"Controller B";
    
    myTab.viewControllers = [NSArray arrayWithObjects:conA, conB, nil];
    
    self.window.rootViewController = myTab;
    
    return YES;
}

ControllerA.m

- (void)viewDidLoad

{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
//    self.tabBarItem.title = @"Controller A";
//    self.tabBarItem.image = [UIImage imageNamed:@"apple.png"]; // 但如此可能會造成一開始不會顯示出title和image的問題,因為viewDidLoad是當view被讀到時才會動作
}


注意
  • 插入image時,需使用.png,否則會造成圖片成方格的問題,因為TabBar的圖在沒有點擊時會讓有顏色的部份變灰白色,透明部份不變。
  • UITabBar可見Tab為5個,多的會加入more選項中。
  • 若UITabBarController與UINavigationController合用時,以UITabBarController為主,因為在設計上UITabBarController不適合動態新增UIViewController。
資料出處《Object-C與iOS開發入門》