หลังจากที่ได้ลองใช้งาน Framework ไปบ้างแล้ว วันนี้ก็มาดูตัวอย่างการใช้งาน String กันบ้าง
โดยปกติแล้วเราจะมี Class เพื่อใช้ในการจัดการเกี่ยวกับ string อยู่ด้วยกัน 2 class นั่นก็คือ
- NSString
- NSMutableString
สอง class นี้มี method ที่คล้ายกัน เพราะว่า NSMutableString นั้นเป็น Child-Class ของ NSString
NSString
NSString นั้นเป็น class ที่เอาไว้จัดการ string ทั้งหลายไม่ว่าจะเป็นการ copy , compare , substring แต่มีข้อจำกัดคือ มันไม่สามารถที่จะแก้ไขได้หลังจากการ initial ไปแล้ว
เรามาดูตัวอย่างการใช้งานของ NSString กัน
#import <Foundation/Foundation.h> int main(int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Init String NSString *szResult; NSString *szStr = @"Hello "; NSString *szStr2 = @"Macfeteria"; NSString *szStr3 = [[NSString alloc] initWithCString:"Welcome to "]; NSString *szStr4 = [[NSString alloc] init]; printf("szStr1: %s\n",[szStr cString]); printf("szStr2: %s\n",[szStr2 cString]); printf("szStr3: %s\n",[szStr3 cString]); // Copy String szStr4 = [NSString stringWithString:szStr]; printf("szStr4: %s\n",[szStr4 cString]); // Compare if( szStr == @"Hello") printf("Equal hello\n"); if( [szStr isEqualToString:szStr2]) printf("Equal szStr2\n"); // Append string szResult = [szStr3 stringByAppendingString:szStr2]; printf("Append 1: %s\n",[szResult cString]); // Uppercase printf("Upper: %s\n",[[szStr3 uppercaseString] cString]); // Extract first 4 char szResult = [szStr3 substringToIndex:4]; printf("Substring: %s\n",[szResult cString]); szResult = [[szStr3 substringFromIndex:2] substringToIndex:3]; printf("SubString from-to: %s\n",[szResult cString]); int length = [szStr3 length]; printf("Length szStr3: %d\n",length); [pool release]; }
จาก ข้างบน จะเห็นว่าประกาศตัวแปรเป็น NSString* ทั้งหมด 5 ตัวแปร แต่การประกาศนั้นต่างกันออกไป โดยที่
-
NSString *szResult;
ก็ทำการประกาศตัวแปรขึ้นมาแบบเป็น pointer ไว้เฉยๆ
-
NSString *szStr = @"Hello ";
-
NSString *szStr2 = @"Macfeteria";
ประกาศตัวแปรขึ้นมาโดยกำหนดให้เป็นคำว่า Hello และ Macfeteria สังเกตุว่าจะมีเครื่องหมาย @ นำหน้าก็เพื่อบอกว่า “Macfeteria” เป็น Constance String Object
-
NSString *szStr3 = [[NSString alloc] initWithCString:"Welcome to "];
การประกาศแบบนี้น่าจะคุ้นน่ะเพราะว่า เราได้ทำการ alloc และแบบนี้เราก็สามารถ นำเอา char* มาแปลงให้เป็น NSString ได้ ยกตัวอย่างเช่น
char *text = "Welcome to "; NSString *szStr3 = [[NSString alloc] initWithCString:text];
-
NSString *szStr4 = [[NSString alloc] init];
ประกาศและจองพื้นที่ไว้แต่ยังไม่ได้เอาไปใช้งาน
หลังจากประกาศตัวแปรก็มีการเรียกการใช้งาน Function ของ NSString ก็มีตั้งแต่การ copy , compare , concatenate , substring ที่จะขออธิบายก็ที่เห็นบ่อยๆจากตัวอย่างคือ
cString สำหรับ cString จะเป็นการ return string ในรูปแบบของ char* กลับมา แบบนี้เราก็สามารถนำไปใช้ได้กับ printf หรือ function ของภาษา C ได้
และก็จะมี การเปรียบเทียบ เราอาจจะเปรียบเทียบโดยใช้ == แบบปกติ (แต่ต้องอย่าลืม @ นำหน้าด้วย) หรืออาจจะใช้ function isEqualToString ก็ได้
เมื่อทำการ compile และ run program เราจะได้เห็นผลลัพธ์แบบนี้
ในระหว่าง ที่ compile หลายคนอาจจะเห็นว่า มันจะขึ้น warning ในลักษณะแบบนี้
ก็ไม่ต้องไปตกใจอะไรนะครับ จริงๆมันก็ทำงานได้แต่ที่มันขึ้น warning “cString” is deprecated แบบนี้มาก็เนื่องจากว่า cString ที่เราได้เรียกใช้นั้น SDK 10.5 ไม่ได้ใช้แล้วและในอนาคตก็คงจะเอาออก ก็แปลได้ง่ายๆว่า cString มันจะใช้ไม่ได้ในอนาคต ถ้าหากว่าเรามีแผนการต้องเปลี่ยน ไปใช้ SDK ที่ใหม่กว่าในอนาคต ก็ควรจะเลิกใช้ cString เปลี่ยนไปใช้ อย่างอื่นแทน ในกรณีนี้ เค้าแนะนำว่า ให้ไปใช้ cStringUsingEncoding: แทน ฉนั้นแล้ว เราก็อาจจะเขียน ใหม่ได้ว่า
printf("szStr1: %s\n",[szStr cStringUsingEncoding: NSUTF8StringEncoding]); printf("szStr2: %s\n",[szStr2 cStringUsingEncoding: NSUTF8StringEncoding]); printf("szStr3: %s\n",[szStr3 cStringUsingEncoding: NSUTF8StringEncoding]);
ในส่วนของ NSUTF8StringEncoding นี้ก็เป็น parameter ที่บอกว่าให้ encode string ออกมาเป็นแบบไหน คือเนื่องจากว่า char ปกติแล้วมันเก็บข้อมูลในลักษณะ 1 byte ฉนั้นแล้วก็จะมีตัวอักษรทั้งหมดแค่ 256 เท่านั้น ต่อมาเมื่อภาษาต่างๆเริ่มมีความสำคัญ เค้าก็เลยเปลี่ยนไปเก็บ string ในรูปแบบที่ไม่ใช่ char แต่เป็น ลักษณะแบบอื่นแทน อาทิเช่น multiple byte , wide char และด้วยเหตุนี้เอง เราจำเป็นต้องระบุว่า จะให้มัน encode string ออกมาเป็นอะไร
NSMutableString
เป็น class ที่เอาไว้จัดการ string เหมือนกัน แต่ต่างกันตรงที่ มันสามารถแก้ไขได้ ภายหลัง ดูตัวอย่างการใช้งาน NSMutableString
#import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Init String NSMutableString *muString = [NSMutableString stringWithString:@"Hello "]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); // Init String [muString appendString:@"Macfeteria"]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); // Insert String [muString insertString:@"I'm Ter " atIndex:6]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); // Delete Character in Range [muString deleteCharactersInRange:NSMakeRange(9, 4)]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); // Replace Character in Range [muString replaceCharactersInRange:NSMakeRange(6,4) withString:@"this is "]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); // Set new String [muString setString:@"Welcome to Macfeteria"]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]); [pool release]; }
เมื่อทำการ compile และ run ก็จะได้ผลลัพธ์ดังตัวอย่าง
ดูจากตัวอย่าง code แล้วคิดว่าไม่น่าจะยากนะครับ
NSMutableString VS NSString
ข้อที่แตกต่างระหว่าง NSMutableString และ NSString นั้นนอกจากเรื่องที่แก้ไข string ได้และไม่ได้ ยังคงมีข้อควรระวังอยู่ ยกตัวอย่างเช่น
NSMutableString *muString = @"Hello "; [muString appendString:@"Macfeteria"]; printf("%s\n",[muString cStringUsingEncoding:NSUTF8StringEncoding]);
ดูจากตัวอย่าง code ข้างบนแล้วแทบจะไม่น่าจะผิดอะไรเลย compile ก็ผ่านปกติ แต่ว่าเวลาที่ run จริงๆ มันจะไม่ผ่านครับ จะเห็นเกิด error แบบนี้
ด้วยเหตผลก็เพราะว่า จริงอยู่ว่าเราประกาศ NSMutableString ขึ้นมาใช้ แต่ตอนที่เรา init มันเรากลับ init ให้มันเป็น NSString ( string ที่ประกาศด้วยเครื่องหมาย @ จะถือว่าเป็น NSString หรือพูดง่ายคือเป็น Constance ไม่สามารถแก้ไขได้ )
และอีกตัวอย่าง ลองดู code ต่อไปนี้
NSString ns = [[NSString alloc] initWithString:@"Hello"]; ns = [ns stringByAppendingString:@"Macfeteria"]; NSMutableString muString = [[NSMutableString alloc] initWithString:@"Hello"]; [muString appendString:@"Macfeteria"];
จะเห็นว่า code ทั้งสองอย่างไม่ว่าจะเป็น NSMutableString และ NSString นั้นก็สามารถ append string ได้เหมือนกัน
แล้วมันต่างกันยังไง ?
จาก code นะครับ NSString
- ns ชี้ pointer ไปยัง memory เพื่อทำการจอง string “Hello”
- หลังจากนั้นจะเห็นว่า ns ต้องการ append string “Macfeteria”
- แต่สิ่งที่ ns ทำจริงๆคือ การย้าย pointer ชี้ไปยังตำแหน่งของ memory ใหม่ที่ได้จากการสร้าง string โดย append
ส่วน NSMutableString
- muString ชี้ pointer ไปยัง memory เพื่อทำการจอง string “Hello”
- muString ทำการ append string “Macfeteria” ยังตำแหน่ง memory เดิม
ฉนั้นแล้ว การ Append ในกรณี NSString นั้นจะเกิด Memory Leak ครับ เพราะ s ได้ย้าย pointer ไปชี้ยัง memory ส่วนใหม่ (Hello Macfeteria) ส่วนตำแหน่งเดิม (Hello) ก็ไม่ได้ release จึงเกิด Memory Leak ขึ้น
ถ้าหากต้องการ แก้ไข code ที่ถูกต้องควรจะเป็น
ns = [[s autorelease] stringByAppendingString:@"Macfeteria"];
ก็เพิ่ม autorelease เข้าไปเพื่อให้มัน release memory หลังจากไม่ได้ใช้แล้วโดยอัตโนมัติ
ก็ลองศึกษาเพิ่มเติมการใช้งานได้จาก web ของ apple ได้เองที่ http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
ส่วน source code ก็นี่เลย Download Foundation Framework II (NSString) Soure Files






