วันนี้ก็ยังต่อเนื่องเกี่ยวกับเรื่องของ table view เหมือนเดิมนะครับ สืบเนื่องจากครั้งที่แล้วที่ผม ได้เขียน tutorial ในแบบลักษณะการเขียนย่อลง เอาแต่ส่วนที่สำคัญทำให้ผู้อ่านหลายๆคน บอกว่าน่าจะเอาแบบเดิม ( คือเริ่มตั้งแต่ สร้าง project ) เพราะ ยังประสบการณ์น้อย อ่านแล้วไม่เข้าใจ โอเค ครับ งั้นผมจะ พยายาม เขียน ในทุกๆขั้นตอนเลยละกัน ( แต่ในอนาคจะ ค่อยๆ ปรับลดลงนะครับ )
อย่างที่บอกไปว่าวันนี้ยังอยู่ในเรื่องของ table เหมือนเดิม วันนี้จะมาต่อในเรื่องของ Section ครับ
โดยปกติแล้ว Table View น้ันจะประกอบไปด้วย cell และ cell เหล่านี้สามารถแยกเป็นหมวดๆได้ เรียนกว่า section ดูรูปประกอบ จะเข้าใจ
จากรูปจะเห็นชื่อที่ขึ้นต้นด้วย ตัวอักษรเดียวกันนั้นจะถูกจับรวมกันเป็นกลุ่ม ( section ) งั้นเรามาเริ่มเลยดีกว่าครับ
โปรแกรมที่เราจะเขียนกันในวันนี้ก็ไม่มีอะไรมากครับ คือเราจะเขียน โปรแกรม ไว้เก็บรายชื่อของสัตว์ต่างๆ แล้วก็แยกตามหมวดหมู่เท่านั้นเอง แต่ก่อนที่จะเริ่มดูภาพประกอบกันก่อนครับว่า โครงสร้างของโปรแกรม เราเป็นแบบไหน จะได้เข้าใจกันก่อนสักนิดว่า เรากำลังจะทำอะไร
ตามแผนภาพ ผมจะแบ่งหมวดหมู่ของสัตว์ออกเป็น 3 ประเภทคือ Mammal , Bird , Fish แล้วแต่ละประเภท นั้นก็จะมีรายชื่อของ สัตว์ต่างๆ การออกแบบ คลาสต่างๆ ก็จะเหมือนดังแผนภาพ ครับ นั่นก็คือ ผมมี class ที่ชื่อ Animal เป็น ทั้ง datasource , delegate ( NSTableView ) เมื่อดูภาพประกอบคร่าวๆ เรียบร้อยแล้ว ต่อไปก็เริ่มโปรเจคกันเลย
Start New Project
เราก็เลือก view based application ครับ แล้วหลังจากนั้นก็ตั้งชื่ออะไรก็ได้ ในตัวอย่างนี้ผมจะใช้ชื่อว่า AnimalDemo เสร็จแล้วก็จะได้โปรเจคออกมาดังรูปแบบนี้ครับ
เมื่อเรียบร้อยแล้ว ลำดับต่อไป เราก็จะออกแบบหน้าตาของโปรแกรมเราก่อน ก็ทำการเปิด AnimalDemoViewController.xib ขึ้นมา แล้วก็ลาก Table View เข้ามาดังรูปครับ
ก็เป็นอันเสร็จ การออกแบบหน้าตาของโปรแกรม หลังจากนี้ ลำดับต่อไปก็คือ เขียน class ที่เป็น datasource และ delegate นั่นเอง
เราจะทำการเพิ่ม class เข้ามายัง project ของเราโดยการ เลือกไปที่เมนู File > New File… แล้วก็เลือก ชนิดของ File ดังรูปครับ
หลังจากนั้นก็ตั้งชื่อว่า Animal ก็เป็นอันเสร็จเรียบร้อย ต่อไปเราก็จะมาเขียน code กัน
Implement Delegate & Data Source
อย่างที่เห็นในแผนภาพ ไปแล้ว ว่าเรามี class ที่ชื่อ Animal ที่ประกอบไปด้วย Array ที่เก็บรายชื่อของ สัตว์ต่างๆ เวลาเขียน code ออกมาก็จะได้ประมาณนี้ครับ
#import "Animal.h" @implementation Animal @synthesize m_animal; -(id) init { self = [super init]; m_animal = [[NSMutableDictionary alloc] init]; NSMutableArray* mammal= [[[NSMutableArray alloc] initWithObjects: @"Dog",@"Cat",@"Rabbit",@"Tiger",nil] autorelease] ; NSMutableArray* bird = [[[NSMutableArray alloc] initWithObjects: @"Eagle",@"Hawk",@"Parrot",nil] autorelease]; NSMutableArray* fish = [[[NSMutableArray alloc] initWithObjects: @"Shark",@"Barrachuda",@"Gold Fish"] autorelease]; [m_animal setObject:mammal forKey:@"Mammal"]; [m_animal setObject:bird forKey:@"Bird"]; [m_animal setObject:fish forKey:@"Fish"]; return self; } // Total Section -(NSInteger) numberOfSectionsInTableView:(UITableView*) table { NSInteger totalSection = [self.m_animal count]; return totalSection; } // Number of row in each section -(NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger) section { NSArray* key = [self.m_animal allKeys]; NSString* keyValue = [key objectAtIndex:section]; NSInteger rowCount = [[self.m_animal objectForKey:keyValue] count]; return rowCount; } // Name of each section -(NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteger) section { NSArray* allKeys = [self.m_animal allKeys]; NSString* name=[allKeys objectAtIndex:section]; return name; } -(UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath { static NSString *sampleIndentifier = @"My Identifier"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier: sampleIndentifier]; if ( cell == nil ) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:sampleIndentifier] autorelease]; } NSUInteger row = [indexPath row]; NSUInteger section = [indexPath section]; NSArray* key = [self.m_animal allKeys]; NSString* keyValue = [key objectAtIndex:section]; NSArray* animalList = [m_animal objectForKey:keyValue]; cell.textLabel.text = [animalList objectAtIndex:row]; return cell; } -(void) dealloc { [m_animal release]; [super dealloc]; } @end
Explain
ดู code แล้วอาจจะค่อนข้างจะยาวนิดหนึ่งนะครับ ค่อยๆทำความเข้าใจกันในแต่ละส่วนก่อนดีกว่า
-(id) init { self = [super init]; m_animal = [[NSMutableDictionary alloc] init]; NSMutableArray* mammal= [[[NSMutableArray alloc] initWithObjects: @"Dog",@"Cat",@"Rabbit",@"Tiger",nil] autorelease] ; NSMutableArray* bird = [[[NSMutableArray alloc] initWithObjects: @"Eagle",@"Hawk",@"Parrot",nil] autorelease]; NSMutableArray* fish = [[[NSMutableArray alloc] initWithObjects: @"Shark",@"Barrachuda",@"Gold Fish"] autorelease]; [m_animal setObject:mammal forKey:@"Mammal"]; [m_animal setObject:bird forKey:@"Bird"]; [m_animal setObject:fish forKey:@"Fish"]; return self; }
ฟังก์ชั่นนี้ ไม่ได้มีอะไรมากนอกจาก ประกาศ array ที่ประกอบไปด้วยรายชื่อของสัตว์ต่างๆ และนำมันไปใส่ไว้ใน dictionary ( m_animal ) จริงๆแล้วเราจะใช้ array ทั้งหมดก็ได้นะครับ
// Total Section -(NSInteger) numberOfSectionsInTableView:(UITableView*) table { NSInteger totalSection = [self.m_animal count]; return totalSection; } // Number of row in each section -(NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger) section { NSArray* key = [self.m_animal allKeys]; NSString* keyValue = [key objectAtIndex:section]; NSInteger rowCount = [[self.m_animal objectForKey:keyValue] count]; return rowCount; } // Name of each section -(NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteger) section { NSArray* allKeys = [self.m_animal allKeys]; NSString* name=[allKeys objectAtIndex:section]; return name; }
สองฟังก์ชั่น ข้างบน นั้น เป็นการบอกว่า ตารางนี้ประกอบไปด้วย section ทั้งหมดเท่าไหร่ และแต่ละ section นั้นมีแถวจำนวนเท่าไหร่
ซึ่งจำนวน section ของเราทั้งหมดนั้นมี จะมีเท่ากับ จำนวน array ที่ได้เก็บไว้ใน m_animal นั่นก็คือ 3 และจำนวน แถวของแต่ละ section นั้นก็หามาจาก จำนวนชื่อของสัตว์ในแต่ละ array ที่ได้เก็บไว้นั่นเอง
และฟังก์ชั่นสุดท้าย ก็คือ ชื่อของแต่ละ section ในตัวอย่างผมได้ให้ ชื่อของแต่ละ section น้ันเป็นชื่อของ key ที่ผมได้ใส่ไปใน dictionary ตอนสร้างครั้งแรกนั่นเอง
หมายเหตุ ใน Dictionary เราไม่สามารถจะขอข้อมูลที่เราได้ใส่ไปถ้าหากไม่มี key ดังนั้นแล้ว ผมจึงใช้ ** [NSDictionary allKey] เพื่อที่จะได้ key ทั้งหมดกลับมาซึ่งจะเป็น array ** หลังจากนั้นแล้วค่อยไปไล่หาค่าต่างๆตามลำดับ index ใน array อีกที
ส่วนสุดท้ายก็คือ
-(UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath { static NSString *sampleIndentifier = @"My Identifier"; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier: sampleIndentifier]; if ( cell == nil ) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:sampleIndentifier] autorelease]; } NSUInteger row = [indexPath row]; NSUInteger section = [indexPath section]; NSArray* key = [self.m_animal allKeys]; NSString* keyValue = [key objectAtIndex:section]; NSArray* animalList = [m_animal objectForKey:keyValue]; cell.textLabel.text = [animalList objectAtIndex:row]; return cell; }
เราได้ implement delegate เพื่อที่ตารางจะได้รู้ว่าควรนำอะไรไปแสดง ในแต่ละ section , row
จาก code ข้างบน อธิบายคร่าวก็คือ เมื่อเรา ได้ index path มาแล้วเราหากลุ่มจาก section เมื่อเรารู้กลุ่มแล้ว หลังจากนั้นก็ไปหา ชื่อของสัตว์ตามลำดับของแถว ที่ควรจะแสดง
ก็เป็นอันจบในส่วนของ Animal Class
แต่ยังเหลือในส่วนของ View Controller ที่เรายังไม่ได้เขียนเพิ่มครับ เราต้อง เพิ่ม Animal เข้าไปยัง View Controller ของเรา ก็เปิด File ที่ชื่อ AnimalDemoViewController.h ขึ้นมาครับ
หลังจากนั้นก็เพิ่ม code เข้าไปดังนี้
#import "Animal.h" @interface AnimalDemoViewController : UIViewController { IBOutlet Animal *m_animalDataSource; } @property (nonatomic,retain) Animal* m_animalDataSource; @end
แล้วส่วน implement ก็จะเป็นประมาณนี้ครับ
#import "AnimalDemoViewController.h" @implementation AnimalDemoViewController @synthesize m_animalDataSource; - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; } - (void)dealloc { [m_animalDataSource release]; [super dealloc]; } @end
ก็เป็นอันเสร็จ อธิบายกันสักนิด ที่เราได้เพิ่มเข้าไปก็คือ Animal ( m_animalDataSource ) แต่เราได้ประกาศให้เป็น Outlet เพื่อที่ว่าจะได้นำไป link กับตารางที่อยู่ interface builder ครับ
Link Object
กลับไปยัง interface builder ครับ เรายังเหลือสิ่งที่ต้องทำอีก อย่างสองอย่าง นั่นก็คือ สร้าง instance ของ Animal ก็เริ่มจาก เปิด AnimalDemoViewController.xib ขึ้นมา หลังจากนั้นก็เพิ่ม Object เข้าไปดังรูปครับ
จากรูป เมื่อ ลาก Object เข้ามาแล้ว เราก็เปิด หน้าต่าง inspector ขึ้นมาครับ แล้วตรง indentity จะเห็น Class เราก็เปลี่ยนให้เป็น Animal ก็เรียบร้อย เพียงเท่านี้เราก็มี Animal Instance เรียบร้อย หลังจากนั้นก็เชื่อมมันเข้ากับ m_animalDataSource ของเรา ดังรูป
และลำดับสุดท้ายครับ เราต้อง set datasource ให้กับตารางของเรา เราก็ click ขวาไปยังตาราง แล้วก็ลาก เชื่อมเข้ากับ Animal Instance ดังรูปครับ
ก็เป็นอันเสร็จทุกๆอย่างครับ Compile แล้วก็ Run จะเห็นโปรแกรมมีหน้าตา แบบนี้ครับ
ครั้งหน้าเดี๋ยวมาต่อกัน ในเรื่องของ ตารางต่อนะครับ
ตัวอย่าง Source Code ก็กด Download ได้เลยครับ











