第一個講解網頁的內容程序員
研究了幾天的數據庫,終於把它給搞出來了。Sqlite是ios上最經常使用的數據庫之一,你們仍是有必要了解一下的。這是仿照網上的一個例子作的,有些部分寫的很差,我稍做了修改,以講解爲主,主要讓你們可以明白如何修改,明白原理,達到觸類旁通的目的。sql
先來看看效果圖數據庫
先來看看數據庫方法類,將各個操做都封裝在一個類裏面,達到代碼重用的目的,這是程序員都應該努力去實現的目標,這樣在下一次用到一樣的方法和類的時候,就能夠直接使用封裝好的類,能夠節約大量的時間。數組
先來看看.h文件函數
#import <Foundation/Foundation.h>#import <sqlite3.h>#define kFilename @"testdb.db"@class sqlTestList;@interface sqlService : NSObject { sqlite3 *_database; } @property (nonatomic) sqlite3 *_database;-(BOOL) createTestList:(sqlite3 *)db;//建立數據庫-(BOOL) insertTestList:(sqlTestList *)insertList;//插入數據 -(BOOL) updateTestList:(sqlTestList *)updateList;//更新數據-(NSMutableArray*)getTestList;//獲取所有數據- (BOOL) deleteTestList:(sqlTestList *)deletList;//刪除數據:- (NSMutableArray*)searchTestList:(NSString*)searchString;//查詢數據庫,searchID爲要查詢數據的ID,返回數據爲查詢到的數據@end@interface sqlTestList : NSObject//從新定義了一個類,專門用於存儲數據{ int sqlID; NSString *sqlText; NSString *sqlname; } @property (nonatomic) int sqlID; @property (nonatomic, retain) NSString *sqlText; @property (nonatomic, retain) NSString *sqlname;@end
再來看看.m文件atom
//// sqlService.m// SQLite3Test//// Created by fengxiao on 11-11-28.// Copyright 2011 __MyCompanyName__. All rights reserved.//#import "sqlService.h"@implementation sqlService@synthesize _database;- (id)init { return self; }- (void)dealloc { [super dealloc]; }//獲取document目錄並返回數據庫目錄- (NSString *)dataFilePath{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSLog(@"=======%@",documentsDirectory); return [documentsDirectory stringByAppendingPathComponent:@"data.db"];//這裏很神奇,能夠定義成任何類型的文件,也能夠不定義成.db文件,任何格式都行,定義成.sb文件都行,達到了很好的數據隱祕性 }//建立,打開數據庫- (BOOL)openDB { //獲取數據庫路徑 NSString *path = [self dataFilePath]; //文件管理器 NSFileManager *fileManager = [NSFileManager defaultManager]; //判斷數據庫是否存在 BOOL find = [fileManager fileExistsAtPath:path]; //若是數據庫存在,則用sqlite3_open直接打開(不要擔憂,若是數據庫不存在sqlite3_open會自動建立) if (find) { NSLog(@"Database file have already existed."); //打開數據庫,這裏的[path UTF8String]是將NSString轉換爲C字符串,由於SQLite3是採用可移植的C(而不是 //Objective-C)編寫的,它不知道什麼是NSString. if(sqlite3_open([path UTF8String], &_database) != SQLITE_OK) { //若是打開數據庫失敗則關閉數據庫 sqlite3_close(self._database); NSLog(@"Error: open database file."); return NO; } //建立一個新表 [self createTestList:self._database]; return YES; } //若是發現數據庫不存在則利用sqlite3_open建立數據庫(上面已經提到過),與上面相同,路徑要轉換爲C字符串 if(sqlite3_open([path UTF8String], &_database) == SQLITE_OK) { //建立一個新表 [self createTestList:self._database]; return YES; } else { //若是建立並打開數據庫失敗則關閉數據庫 sqlite3_close(self._database); NSLog(@"Error: open database file."); return NO; } return NO; }//建立表- (BOOL) createTestList:(sqlite3*)db { //這句是你們熟悉的SQL語句 char *sql = "create table if not exists testTable(ID INTEGER PRIMARY KEY AUTOINCREMENT, testID int,testValue text,testName text)";// testID是列名,int 是數據類型,testValue是列名,text是數據類型,是字符串類型 sqlite3_stmt *statement; //sqlite3_prepare_v2 接口把一條SQL語句解析到statement結構裏去. 使用該接口訪問數據庫是當前比較好的的一種方法 NSInteger sqlReturn = sqlite3_prepare_v2(_database, sql, -1, &statement, nil); //第一個參數跟前面同樣,是個sqlite3 * 類型變量, //第二個參數是一個 sql 語句。 //第三個參數我寫的是-1,這個參數含義是前面 sql 語句的長度。若是小於0,sqlite會自動計算它的長度(把sql語句當成以\0結尾的字符串)。 //第四個參數是sqlite3_stmt 的指針的指針。解析之後的sql語句就放在這個結構裏。 //第五個參數是錯誤信息提示,通常不用,爲nil就能夠了。 //若是這個函數執行成功(返回值是 SQLITE_OK 且 statement 不爲NULL ),那麼下面就能夠開始插入二進制數據。 //若是SQL語句解析出錯的話程序返回 if(sqlReturn != SQLITE_OK) { NSLog(@"Error: failed to prepare statement:create test table"); return NO; } //執行SQL語句 int success = sqlite3_step(statement); //釋放sqlite3_stmt sqlite3_finalize(statement); //執行SQL語句失敗 if ( success != SQLITE_DONE) { NSLog(@"Error: failed to dehydrate:create table test"); return NO; } NSLog(@"Create table 'testTable' successed."); return YES; }//插入數據-(BOOL) insertTestList:(sqlTestList *)insertList { //先判斷數據庫是否打開 if ([self openDB]) { sqlite3_stmt *statement; //這個 sql 語句特別之處在於 values 裏面有個? 號。在sqlite3_prepare函數裏,?號表示一個未定的值,它的值等下才插入。 static char *sql = "INSERT INTO testTable(testID, testValue,testName) VALUES(?, ?, ?)"; int success2 = sqlite3_prepare_v2(_database, sql, -1, &statement, NULL); if (success2 != SQLITE_OK) { NSLog(@"Error: failed to insert:testTable"); sqlite3_close(_database); return NO; } //這裏的數字1,2,3表明上面的第幾個問號,這裏將三個值綁定到三個綁定變量 sqlite3_bind_int(statement, 1, insertList.sqlID); sqlite3_bind_text(statement, 2, [insertList.sqlText UTF8String], -1, SQLITE_TRANSIENT); sqlite3_bind_text(statement, 3, [insertList.sqlname UTF8String], -1, SQLITE_TRANSIENT); //執行插入語句 success2 = sqlite3_step(statement); //釋放statement sqlite3_finalize(statement); //若是插入失敗 if (success2 == SQLITE_ERROR) { NSLog(@"Error: failed to insert into the database with message."); //關閉數據庫 sqlite3_close(_database); return NO; } //關閉數據庫 sqlite3_close(_database); return YES; } return NO; }//獲取數據- (NSMutableArray*)getTestList{ NSMutableArray *array = [NSMutableArray arrayWithCapacity:10]; //判斷數據庫是否打開 if ([self openDB]) { sqlite3_stmt *statement = nil; //sql語句 char *sql = "SELECT testID, testValue ,testName FROM testTable";//從testTable這個表中獲取 testID, testValue ,testName,若獲取所有的話能夠用*代替testID, testValue ,testName。 if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) != SQLITE_OK) { NSLog(@"Error: failed to prepare statement with message:get testValue."); return NO; } else { //查詢結果集中一條一條的遍歷全部的記錄,這裏的數字對應的是列值,注意這裏的列值,跟上面sqlite3_bind_text綁定的列值不同!必定要分開,否則會crash,只有這一處的列號不一樣,注意! while (sqlite3_step(statement) == SQLITE_ROW) { sqlTestList* sqlList = [[sqlTestList alloc] init] ; sqlList.sqlID = sqlite3_column_int(statement,0); char* strText = (char*)sqlite3_column_text(statement, 1); sqlList.sqlText = [NSString stringWithUTF8String:strText]; char *strName = (char*)sqlite3_column_text(statement, 2); sqlList.sqlname = [NSString stringWithUTF8String:strName]; [array addObject:sqlList]; [sqlList release]; } } sqlite3_finalize(statement); sqlite3_close(_database); } return [array retain];//定義了自動釋放的NSArray,這樣不是個好辦法,會形成內存泄露,建議你們定義局部的數組,再賦給屬性變量。}//更新數據-(BOOL) updateTestList:(sqlTestList *)updateList{ if ([self openDB]) { sqlite3_stmt *statement;//這至關一個容器,放轉化OK的sql語句 //組織SQL語句 char *sql = "update testTable set testValue = ? and testName = ? WHERE testID = ?"; //將SQL語句放入sqlite3_stmt中 int success = sqlite3_prepare_v2(_database, sql, -1, &statement, NULL); if (success != SQLITE_OK) { NSLog(@"Error: failed to update:testTable"); sqlite3_close(_database); return NO; } //這裏的數字1,2,3表明第幾個問號。這裏只有1個問號,這是一個相對比較簡單的數據庫操做,真正的項目中會遠遠比這個複雜 //綁定text類型的數據庫數據 sqlite3_bind_text(statement, 3, [updateList.sqlname UTF8String], -1, SQLITE_TRANSIENT); sqlite3_bind_text(statement, 2, [updateList.sqlText UTF8String], -1, SQLITE_TRANSIENT); sqlite3_bind_int(statement, 1, updateList.sqlID); //執行SQL語句。這裏是更新數據庫 success = sqlite3_step(statement); //釋放statement sqlite3_finalize(statement); //若是執行失敗 if (success == SQLITE_ERROR) { NSLog(@"Error: failed to update the database with message."); //關閉數據庫 sqlite3_close(_database); return NO; } //執行成功後依然要關閉數據庫 sqlite3_close(_database); return YES; } return NO; }//刪除數據- (BOOL) deleteTestList:(sqlTestList *)deletList{ if ([self openDB]) { sqlite3_stmt *statement; //組織SQL語句 static char *sql = "delete from testTable where testID = ? and testValue = ? and testName = ?"; //將SQL語句放入sqlite3_stmt中 int success = sqlite3_prepare_v2(_database, sql, -1, &statement, NULL); if (success != SQLITE_OK) { NSLog(@"Error: failed to delete:testTable"); sqlite3_close(_database); return NO; } //這裏的數字1,2,3表明第幾個問號。這裏只有1個問號,這是一個相對比較簡單的數據庫操做,真正的項目中會遠遠比這個複雜 sqlite3_bind_int(statement, 1, deletList.sqlID); sqlite3_bind_text(statement, 2, [deletList.sqlText UTF8String], -1, SQLITE_TRANSIENT); sqlite3_bind_text(statement, 3, [deletList.sqlname UTF8String], -1, SQLITE_TRANSIENT); //執行SQL語句。這裏是更新數據庫 success = sqlite3_step(statement); //釋放statement sqlite3_finalize(statement); //若是執行失敗 if (success == SQLITE_ERROR) { NSLog(@"Error: failed to delete the database with message."); //關閉數據庫 sqlite3_close(_database); return NO; } //執行成功後依然要關閉數據庫 sqlite3_close(_database); return YES; } return NO; }//查詢數據- (NSMutableArray*)searchTestList:(NSString*)searchString{ NSMutableArray *array = [NSMutableArray arrayWithCapacity:10]; //判斷數據庫是否打開 if ([self openDB]) { sqlite3_stmt *statement = nil; //sql語句 NSString *querySQL = [NSString stringWithFormat:@"SELECT * from testTable where testName like \"%@\"",searchString]; const char *sql = [querySQL UTF8String];// char *sql = "SELECT * FROM testTable WHERE testName like ?";//這裏用like代替=能夠執行模糊查找,原來是"SELECT * FROM testTable WHERE testName = ?" if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) != SQLITE_OK) { NSLog(@"Error: failed to prepare statement with message:search testValue."); return NO; } else { sqlTestList *searchList = [[sqlTestList alloc]init];// sqlite3_bind_int(statement, 1, searchID); sqlite3_bind_text(statement, 3, [searchString UTF8String], -1, SQLITE_TRANSIENT); //查詢結果集中一條一條的遍歷全部的記錄,這裏的數字對應的是列值。 while (sqlite3_step(statement) == SQLITE_ROW) { sqlTestList* sqlList = [[sqlTestList alloc] init] ; sqlList.sqlID = sqlite3_column_int(statement,1); char* strText = (char*)sqlite3_column_text(statement, 2); sqlList.sqlText = [NSString stringWithUTF8String:strText]; char *strName = (char*)sqlite3_column_text(statement, 3); sqlList.sqlname = [NSString stringWithUTF8String:strName]; [array addObject:sqlList]; [sqlList release]; } [searchList release]; } sqlite3_finalize(statement); sqlite3_close(_database); } return [array retain]; }@end@implementation sqlTestList//剛纔.h文件裏定義的類在這實現@synthesize sqlID;@synthesize sqlText;@synthesize sqlname;-(id) init { sqlID = 0; sqlText = @""; sqlname = @""; return self; };-(void) dealloc { if ((sqlText != nil) && (sqlname != nil)) { [sqlText release]; [sqlname release]; } [super dealloc]; }@end
這就是封裝好的類,能夠重用哦!spa
下面是添加數據頁面.net
這也是一個類,來看.h文件指針
#import <UIKit/UIKit.h>#import "sqlService.h"@interface operateSqlViewController : UIViewController { UITextField *idValue; UITextField *textValue; UITextField *textName; int oprateType;//區分數據插入與更新 sqlTestList *sqlValue; } @property (nonatomic, retain) IBOutlet UITextField *idValue; @property (nonatomic, retain) IBOutlet UITextField *textValue; @property (nonatomic, retain) IBOutlet UITextField *textName; @property (nonatomic, retain) sqlTestList *sqlValue; @property (nonatomic) int oprateType;@end
再來看看.m文件
#import "operateSqlViewController.h"@implementation operateSqlViewController@synthesize idValue;@synthesize textValue;@synthesize oprateType;@synthesize sqlValue;@synthesize textName;- (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc. that aren't in use.}- (void)viewDidLoad{ UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleBordered target:self action:@selector(dismiss:)]; UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:@"保存" style:UIBarButtonItemStyleBordered target:self action:@selector(saveValue:)]; [[self navigationItem] setLeftBarButtonItem:backButton]; [[self navigationItem] setRightBarButtonItem:saveButton]; [backButton release]; [saveButton release]; if (oprateType == 0) { [self.navigationItem setTitle:@"數據插入"]; } else if(oprateType == 1){ [self.navigationItem setTitle:@"數據更新"]; idValue.text = [NSString stringWithFormat:@"%d", sqlValue.sqlID]; textValue.text = sqlValue.sqlText; textName.text = sqlValue.sqlname; } }- (void)viewDidUnload { idValue = nil; textValue = nil; textName = nil; sqlValue = nil; [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil;}- (void)dealloc { [idValue release]; [textValue release]; [sqlValue release]; [textName release]; [super dealloc]; }- (void)dismiss:(id)sender{ [[self parentViewController] dismissModalViewControllerAnimated:YES]; }- (void)saveValue:(id)sender{ if (idValue.text.length == 0) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請輸入ID" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } if (textValue.text.length == 0) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請輸入電話" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } if (textName.text.length == 0) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請輸入姓名" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } //初始化數據庫 sqlService *sqlSer = [[sqlService alloc] init]; //數據庫插入 if (oprateType == 0) { sqlTestList *sqlInsert = [[sqlTestList alloc]init]; sqlInsert.sqlID = [idValue.text intValue]; sqlInsert.sqlText = textValue.text; sqlInsert.sqlname = textName.text; //調用封裝好的數據庫插入函數 if ([sqlSer insertTestList:sqlInsert]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"插入數據成功" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"插入數據失敗" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; } [sqlInsert release]; } //數據庫更新 if(oprateType == 1){ sqlTestList *newValue = [[sqlTestList alloc]init]; newValue.sqlID = [idValue.text intValue]; newValue.sqlText = textValue.text; newValue.sqlname = textName.text; //調用封裝好的更新數據庫函數 if ([sqlSer updateTestList:newValue]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"更新數據成功" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"更新數據失敗" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; } [newValue release]; } }@end
代碼寫的有些囉嗦,不過不難容易看懂,很少解釋了,要在xib文件中添加3個UITextField和ULabel,要記得連線。
在主界面的.h文件
#import <UIKit/UIKit.h>#import "sqlService.h"@interface SQLite3TestViewController : UIViewController<UITableViewDelegate,UITableViewDataSource> { UITableView *utableView; NSArray *listData; UISearchBar *searchBar;//搜索欄 } @property (nonatomic, retain) IBOutlet UITableView *utableView; @property (nonatomic, retain) IBOutlet UISearchBar *searchBar; @property (nonatomic, retain) NSArray *listData;- (IBAction)insertValue;- (IBAction)updateValue;- (IBAction)getAllValue;- (IBAction)deleteValue;- (IBAction)searchValue;@end
.m文件
//// SQLite3TestViewController.m// SQLite3Test//// Created by fengxiao on 11-11-28.// Copyright 2011 __MyCompanyName__. All rights reserved.//#import "SQLite3TestViewController.h"#import "operateSqlViewController.h"@implementation SQLite3TestViewController@synthesize utableView;@synthesize listData;@synthesize searchBar;- (void)viewDidLoad{ sqlService *sqlSer = [[sqlService alloc] init]; listData = [sqlSer getTestList];//先初始化那個專門用於存數據的類,才調用類獲取數據的方法}- (void)viewDidAppear:(BOOL)animated{//在這裏寫是爲了等待時間縮短一點,數據若是不少的,在這裏寫可讓數據提早加載 sqlService *sqlSer = [[sqlService alloc] init]; listData = [sqlSer getTestList]; [sqlSer release]; [utableView reloadData]; }- (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use.}- (void)viewDidUnload { utableView = nil; listData = nil; searchBar = nil; [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil;}- (void)dealloc { [utableView release]; [listData release]; [searchBar release]; [super dealloc]; }- (IBAction)insertValue{ [searchBar resignFirstResponder];//觸發這個insertValue方法時隱藏鍵盤 operateSqlViewController *operateController = [[operateSqlViewController alloc] init ]; UINavigationController *theNavController = [[UINavigationController alloc] initWithRootViewController:operateController];//這裏若是不初始化一個UINavigationController類的對象來存放operateSqlViewController類的UIViewController,就不會有最上面的導航欄了。 operateController.oprateType = 0;//optrateType爲0時爲數據插入 [operateController release]; theNavController.navigationBar.tintColor = [UIColor blackColor]; [self presentModalViewController:theNavController animated:YES]; [theNavController release]; }- (IBAction)updateValue{ [searchBar resignFirstResponder]; NSIndexPath *indexPath = [utableView indexPathForSelectedRow]; if (indexPath == nil) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請選擇要更新的項" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } NSUInteger row = [indexPath row]; sqlTestList *sqlList = [[sqlTestList alloc]init]; sqlList = [listData objectAtIndex:(row - 1)];//在這裏面獲取點擊的行,由於table的第一行沒顯示數據,因此這裏要減1。 operateSqlViewController *operateController = [[operateSqlViewController alloc] init ]; UINavigationController *theNavController = [[UINavigationController alloc] initWithRootViewController:operateController]; operateController.oprateType = 1;//optrateType爲1時爲數據更新 operateController.sqlValue = sqlList; theNavController.navigationBar.tintColor = [UIColor blackColor]; [self presentModalViewController:theNavController animated:YES]; [sqlList release]; [operateController release]; [theNavController release]; }- (IBAction)getAllValue{ [searchBar resignFirstResponder]; sqlService *sqlSer = [[sqlService alloc] init]; listData = [sqlSer getTestList]; [utableView reloadData]; [sqlSer release]; }- (IBAction)deleteValue{ [searchBar resignFirstResponder]; NSIndexPath *indexPath = [utableView indexPathForSelectedRow]; if (indexPath == nil) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請選擇要刪除的項" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } NSUInteger row = [indexPath row]; sqlTestList *sqlList = [[sqlTestList alloc]init]; sqlList = [listData objectAtIndex:(row - 1)]; sqlService *sqlSer = [[sqlService alloc] init]; if ([sqlSer deleteTestList:sqlList]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"刪除數據成功" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; //刪除成功後從新獲取數據更新列表 listData = [sqlSer getTestList]; [utableView reloadData]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"刪除數據失敗" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } [sqlList release]; [sqlSer release]; }- (IBAction)searchValue{ if ([searchBar.text isEqualToString:@""]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"請輸入要查詢數據的ID" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } else {// int idNum = [searchBar.text intValue]; NSString *str = searchBar.text; sqlService *sqlSer = [[sqlService alloc] init]; listData = [sqlSer searchTestList:str]; if ([listData count] == 0) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"sorry,未查詢到數據,請查看name是否有誤" delegate:self cancelButtonTitle:@"好" otherButtonTitles:nil]; [alert show]; [alert release]; return; } [searchBar resignFirstResponder]; [utableView reloadData]; [sqlSer release]; } }#pragma mark -#pragma mark Table View Data Source Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [listData count] + 1;//從第二行開始,第一行不顯示數據}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *CustomIdentifier = [NSString stringWithFormat:@"cell%d",indexPath.row]; //cell不重用 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomIdentifier]; if (indexPath.row == 0) cell.selectionStyle = UITableViewCellSelectionStyleNone; if ( cell == nil ) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CustomIdentifier] autorelease]; cell.backgroundColor = [UIColor clearColor]; } if (indexPath.row > 0) { NSUInteger row = [indexPath row]; sqlTestList *sqlList = [[sqlTestList alloc] init] ; if (listData != nil) sqlList = [listData objectAtIndex: (row - 1)];//讀取數據的時候也要減一行,從第二行開始 UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(0+40, 10, 70, 30)]; UILabel *IDLabel = [[UILabel alloc]initWithFrame:CGRectMake(90+40, 10, 70, 30)]; UILabel *valueLabel = [[UILabel alloc]initWithFrame:CGRectMake(180+40, 10, 70, 30)]; nameLabel.text = sqlList.sqlname; IDLabel.text = sqlList.sqlText; valueLabel.text = [NSString stringWithFormat:@"%d",sqlList.sqlID]; [cell.contentView addSubview:nameLabel]; [cell.contentView addSubview:IDLabel]; [cell.contentView addSubview:valueLabel]; [nameLabel release]; [IDLabel release]; [valueLabel release]; } else { for (int i = 0; i < 3; i ++) { UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(90 * i + 40, 10, 70 , 30)]; NSArray *array = [NSArray arrayWithObjects:@"姓名",@"ID",@"電話", nil]; label.text = [array objectAtIndex:i]; label.backgroundColor = [UIColor clearColor]; [cell.contentView addSubview:label]; [label release]; } } return cell; }- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { [searchBar resignFirstResponder]; if (indexPath.row == 0) { return nil;//讓第一行不能點擊 } else return indexPath; }@end