2010年5月10日 星期一

iOS 開發教學 - 兩個 UITableViewController 共用一個 dataSource

UILog

有時候呈現多個 View 時,用的資料會有相關性,此例以兩個 UITableViewController 為例,他們的 dataSource 是同一個來源,當透過底下的 TabBar 進行接換時,會自動增加 dataSource 的資料,接著呈現最新的清單列表,並且在 Console 上印出從哪個 View 新增的資料,以及目前 dataSource 的個數。此作法是共用記憶體資料,另一種作法是每次讀資料都從 databases 或 file 更新。

程式碼:

DataConnectAppDelegate.h

#import <UIKit/UIKit.h>

@interface DataConnectAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    NSMutableArray *dataSource;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@end

DataConnectAppDelegate.m

#import "DataConnectAppDelegate.h"
#import "MyTableViewController.h"

@implementation DataConnectAppDelegate

@synthesize window;

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

    // Override point for customization after application launch
    dataSource = [[NSMutableArray alloc] init];
  
    MyTableViewController *a = [[MyTableViewController alloc] init];
    a.dataSource = dataSource;
    a.title = @"View A";
  
    MyTableViewController *b = [[MyTableViewController alloc] init];
    b.dataSource = dataSource;
    b.title = @"View B";
  
    UITabBarController *tabBar = [[UITabBarController alloc] init];

    tabBar.viewControllers = [NSArray arrayWithObjects:a, b, nil];
    [window addSubview:tabBar.view];
    [window makeKeyAndVisible];

  
    return YES;
}

- (void)dealloc {
    [dataSource release];
    [window release];
    [super dealloc];
}

@end

 MyTableViewController.h

#import <UIKit/UIKit.h>

@interface MyTableViewController : UITableViewController {
    NSMutableArray *dataSource;
}

@property (nonatomic ,assign) NSMutableArray *dataSource;


@end

 MyTableViewController.m

#import "MyTableViewController.h"

@implementation MyTableViewController

@synthesize dataSource;
#pragma mark -
#pragma mark Initialization

#pragma mark -
#pragma mark View lifecycle

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog( @"In,%3@, %d" , self.title , [self.dataSource count]);
    [self.dataSource addObject:[NSString stringWithFormat:@"%d) %@" , [self.dataSource count] , self.title ]];
    [[self tableView] reloadData];

}

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    if( dataSource == nil )
        return 0;
    return [dataSource count];

}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  
    static NSString *CellIdentifier = @"Cell";
  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
  
    // Configure the cell...
    cell.textLabel.text = (NSString*)[dataSource objectAtIndex:indexPath.row];
    return cell;
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     [detailViewController release];
     */
}

#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
  
    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}

- (void)dealloc {
    [super dealloc];
}

@end

成果:

UI1 UI2
左邊一開始執行程式時,由於預設是進入 View A ,故一開始是新增一筆 View A 資料,接著點選下方的 TabBar 切換到 View B 時,則會新增另一筆資料 View B ,接著再 Table View 就會呈現出兩筆資料,最後,不斷掉交替切換到 View A 或 View B 那則會呈現以下的資料列表

UI3

此例在 UITableViewController 中的 - (void)viewWillAppear:(BOOL)animated; 進行實作的,要記得呼叫 [[self tableView] reloadData]; 才會更新 Table View 的資料,否則不斷地切換就只會顯示上面兩個小圖而已,那就是因為沒有叫 tableView 更新資料。

2010年5月6日 星期四

iOS 開發教學 - Regular Expression 之使用 RegexKitLite

處理字串很容易就會用到 Regular Expression 啦!在 iPhone SDK 中雖然可以用 regex ,但卻少了物件導向的方便性。所幸,有方便的 library 可以用,那就是 RegexKitLite - Lightweight Objective-C
Regular Expressions for Mac OS X using
the ICU Library
囉!

用法不難,網路上也滿多相關文章的,簡單筆記:


  • 下載 RegexKitLite-4.0.tar.bz2 (139.1K)

  • 把裡頭兩個檔案 RegexKitLite.h 和 RegexKitLite.m 拉到你的專案下,並且增加編譯程式的參數

    • [Xcode]->[Project]->[Edit Project Settings]->[Linking]->[Other Linker Flags]-> 增加 '-licucore' 即可

簡單的範例

片段程式碼:

NSString *list    = @"<a href='t1.html'>t1</a><a href='t2.html'>t2</a><a href='t2.html'>t2</a>";
NSArray *listItems = [list arrayOfCaptureComponentsMatchedByRegex:@"href=['\"](.*?)['\"]"];
  
NSLog( @"%@" , listItems );

輸出:

(
        (
        "href='t1.html'",
        "t1.html"
    ),
        (
        "href='t2.html'",
        "t2.html"
    ),
        (
        "href='t2.html'",
        "t2.html"
    )
)

剩下的使用可以參考 RegexKitLite-4.0.pdf

2010年5月4日 星期二

遠端桌面 登入 Mac OS X (Remote Desktop) @ Windows 7

由於我的 Mac 是用我 Windows 機器分出去的 IP 享用網路的,也就是 Private IP 啦,雖然已經有 KVM switch 但剛剛突然想要試試從 Windows 7 遠端登入 Mac OSX 囉!找了一下相關文章,結果竟然沒成功:[教學] XP跟Mac互相遠端桌面遙控


原來是少設定密碼了,記錄一下:


[Mac OS X 10.6.2]->[系統偏好設定]->[共享]->[遠端管理]


"電腦設定"


勾選 "VNC 檢示程式可以使用密碼來控制螢幕" ,並且填寫一下密碼吧


"選項"


可以全勾看看(我在Private IP比較無憂無慮XD)


接著下載 TightVNC (VNC-Compatible Free Remote Control Software) ,就可以輸入 Mac OS 的 IP 登入囉!原先也有試著用 RealVNC 免費版,但一直不成功,最後才看到這張表 http://www.realvnc.com/vnc/features.html,才發現只有 Enterprise Edition 才有支援 Mac OSX (x86 and PPC) 囉


TightVNC


只不過有一些好奇的問題,假設我沒有勾選 "VNC 檢示程式可以使用密碼來控制螢幕" ,結果會登入不了,錯誤訊息:


Server did not offer supported security type


原先是想用內建帳密的,但看來不適合(不會用)這個情境下,其他的方式有的在 Mac OS 上架設 VNC Server ,目前還沒有那種需求囉。測試的心得,連上線後,擺一陣子不動就會斷線了?不知是不是我沒設定好,暫時僅用來 Demo 用而已。


最後一提,反而是 Windows 與 Mac 的資料共享還滿重要的,請參考 [分享]Windows & Mac Mini的雙向網路磁碟共享之經驗分享(圖文並茂版)


2010年5月3日 星期一

機車 排氣檢驗 二行程


騎車的經驗差不多有半年了!我機車的車齡已經超過 15 年了!是一台可以自己加機油的二行程機車。


今天有補假,下午就騎車到附近的檢測站,大概只花 3 分鐘就到了!測試的結果 -- 有兩項不合格!


一氧化碳(CO)


數值 5.xx / 排放標準 4.5


碳氫化合物(HC)


數值 1xxxx / 排放標準 9000


二氧化碳(CO2) 


數值 3.30 / 排放標準 3.00


其中只有第三項 (CO2) 是有合格的。機車老闆就說我這車老了,要換東換西,什麼化油器還啥的,大概要兩千多吧!當下我心裡也有個底,好吧!那就去大家推薦的機車行問一下價錢吧!騎了 20 來分,終於到了,也跟老闆聊聊我的問題,原本想問他換東西要多少錢,結果他馬上幫我拆下板子調整一下,還問我有沒有印出檢測的單子借他看一下,沒幾下,他就跟我說,請我去附近一家的檢測站,報他的車行名字去。


對於路況不熟的我,還是上路了,也幸運地找到囉!這次幫我檢驗排氣的是一位熟女,當下我馬上想到 FF7 的 Tifa ,上面那張圖片是 Google 到的 Tifa Cosplay 囉!跟她閒聊後,她跟我說了不少重要的事:



  • 二行程的車子,若溫度不夠高那測試的結果一定是不合格的

  • 可以看 CO2 的指標,若只是剛過 3 的標準,那其實排氣管就還不夠熱

  • 二行程的機車,政府有補助報廢,但要看各縣市的名額還有沒有,有的話有 1500 元,另外,原先都會有環保局 300 元補助,所以最多可以領到 1800 補助費,但各縣市的名額有限,還得去問問就是了


再次測試的結果:


一氧化碳(CO)


數值 0.x / 排放標準 4.5


碳氫化合物(HC)


數值 5xxx / 排放標準 9000


二氧化碳(CO2)


數值 7.xx / 排放標準 3.00


難怪,一開始我覺得幫我測的老闆臉上有一點點奸笑的感覺,再加上我把車子熄火,對我說話有點點不耐煩,不過有一點我也誤會了,像第一位老闆有操我的機車一下,我那時還有點不悅,現在想起來,他大概是要幫我熱車,只是測試失敗時,他竟然沒跟我說一些良心話,在測試過程中就不停囔囔,說這台不會過囉!這也讓我有點起疑心,彷彿還沒測試他早已知道結果了,所幸,還是有碰到好人囉!壞人的存在是基本款,我倒已習慣,更要好好珍惜好人啦~


碰到好店家就是不一樣!當下不是請你花錢買設備,而是很好心地先要幫你調一調!真好!後來我是去展業,體驗好心老闆的服務!但測排氣是到台鈴測試(從寶山路往西大路騎過去,與南大路交界前 50 m 處),不過並不是老闆娘超正啦,只是碰過壞人之後,對於認真的女性,感覺就像看到 Tifa 一樣啦!還有,排測檢驗是要考證照的,在這之前我還以為每一間機車行都行哩


2010年4月30日 星期五

PCMan for Firefox 3.6 ,好用的逛 BBS 工具/Plugin/Extension @ Ubuntu 10.04

pcmanfx


雖然兩年前就知道這個套件,但還是很習慣用 PCMan Lite 而已,只是隨著工作環境的改變,不再只是 Windows 平台,有時是 Linux 或 Mac ,這時候若可以透過瀏覽器幫忙作跨平台,加上只是單純找找資料,也是個不錯的方式!


PCMan 已經有一段時期了,早年跟 KKMan 一樣,透過一個瀏覽介面,提供便利地逛網頁跟逛 BBS 的結合,畢竟台灣最大的地下活動就屬 BBS 了!連現在 2010 年,國外都在用 Web 論壇,台灣現在各大學仍在瘋 BBS 哩!如台灣最大的 BBS 站批踢踢,同時可上線的人數已常常破 10 萬關卡,甚至對岸也會來使用。


關於 Firefox Plugin 的下載,請到這邊:pcmanfx, PCMan Telnet/BBS extension for FIrefox - enable telnet in web browser.


直接下載:pcmanfx-0.1.8.xpi
補充資訊:


By cc 於 2010/04/30 12:59:

pcmanfx 0.1.8版還有一些嚴重的bug,
但是目前開發者似乎沒空處理,
不過有好心人士幫忙修正了,
可以從專案網頁 http://code.google.com/p/pcmanfx/
左上方的Updates進去,再進入issue 27,就可以看到了。
下面是他提供的下載點:
http://cid-2e6c8f3d9767a9d7.skydrive.live.com/browse.aspx/.Public/pcmanfx
抓pcmanfx-0.1.8_r40+_alpha_1.xpi這個回來安裝。


下載後,直接拖拉到 Firefox 瀏覽器上即可安裝,使用上就像另起新頁,用 telnet:// 即可,如 telnet://ptt.cc