Archive
Objective-C Note ภาคต่อ 3
ใกล้หมดแล้วครับมาต่อกันเลย
ความเข้าใจในการใช้ nil [ Calling methods on Nil]
ใน Objective-C นั้น nil object นั้นมี การทำงานเหมือน NULL pointer ในหลายๆ ภาษาที่แตกต่างไปก็คือเราสามารถ เรียก method ของ nil object โดยไม่ทำให้โปรแกรมล่มหรือทำให้เกิด exception ได้ [” จิงดิ “]
เทคนิคนี้ถูกนำไปใช้ใน Frameworks หลากหลายวิธีการ แต่ความหมายที่ต้องการให้ทราบก็คือในขณะนี้ก็คือเราไม่จำเป็นต้องตรวจสอบ object ก่อนการเรียกใช้ method ว่า object นั้น จะเป็น nil หรือไม่ หากเราเรียก method ของ nil object จะได้ค่า nil เป็นค่า return
เราลองมาดูการปรับปรุง dealloc ให้ดีขึ้นอีกนิส
-(void) dealloc { self.caption = nil; self.photographer = nil; [super dealloc]; }
code ส่วนนี้ทำงานได้เนื่องจากเมื่อเรากำหนดค่า nil ให้ instance variable setter จะทำการ retain ค่า nil (แปลว่าว่างเปล่า)และreleaseค่าเก่าออกด้วยวิธีการนี้จะทำให้ variable หมดโอกาสที่จะชี้สุ่มไป เรื่อยเปื่อย
การที่เราใช้ รูปแบบ self. ก็หมายถึงเรากำลังใช้ setter และให้ memory management ของระบบ จัดการเรื่องการคืน memory ถ้าหากเราใช้แบบกำหนดค่าให้โดยตรง(ตัวอย่าง codeด้านล่าง) จะทำให้เกิด memory leak ได้
// incorrect. Causes a memory leak. // use self.caption to go through setter caption = nil;
Categories
categories เป็น คุณลักษณะที่สำคัญอีกอันหนึ่งของ Objective-C โดยที่ Categories นั้นจะทำให้เราสามารถที่จะเพิ่ม method ให้กับ class ที่มีอยู่โดยที่ไม่ต้องทำ sublassing หรือ รู้รายละเอียดเกี่ยวกับการ implementation ของ class นั้น ๆ เลย
ถือว่ามีประโยชน์มากเนื่องจากเราสามารถที่เพิ่ม method ให้กับ built-in object( object ของ class ใน framework ของ cocoa เอง ) เช่นหากเราต้องการเพิ่ม method ให้กับ instance ของ NSString ใน application ที่เรากำลังทำอยู่ เราแค่เพิ่ม category. เราไม่จำเป็นต้องรู้ทุกอย่างเพื่อทำ subclass ขึ้นมา
ตัวอย่าง ถ้าต้องการเพิ่ม method ให้กับ NSString เพื่อใช้ตรวจสอบว่า string ที่กำหลดให้ขณะนั้นเป็น URL หรือไม่ หน้าตาของมัน จะประมาณนี้ครับ
#import @interface NSString (Utilities) -(BOOL) isURL; @end
จะเห็นว่าหน้าตาเหมือนการประกาศ class จะต้องบอกสักนิสว่า method นี้ใช้แสดงให้เห็นการทำ category เท่านั้นให้ดูเท่านนั้นไม่ใช้ method สำหรับการตรวจสอบ URL ที่ดีเลยไม่ควรเอาไปใช้จิงนะครับ
ครับมาดูว่าเราจะ implement อย่างไร
#import “NSString-Utilities.h” @implementation NSString (Utilitites) -(BOOL) isURL { if([Self hasPrefix:@”http://”]) return YES; else return NO; } @end
ครับตอนนี้เรามาลองดูการใช้งานว่าเป็นอย่างไร
NSString* string1 = @”http://pixar.com/”; NSString* string2 = @”Pixar”; if([string1 isURL]) NSLog(@”string1 is a URL”); if([string2 isURL]) NSLog(@”string2 is a URL”);
ต่างกับ subclass นะครับ category ไม่สามารถ เพิ่ม instance variable ได้ อีกอย่างหนึ่งที่สามารถทำได้คือเราสามารถใช้ category ในการ override method ที่มีอยู่ได้ แต่ต้องทำอย่างระมัดระวังอย่างมากมาย
จะบอกว่าเนื้อหาในเรื่อง Obective-c Mynote จบลงตรงนี่ครับ เรื่องที่กล่าวมาทั้งหมดนั้นอ้างอิง หรือ แปลจาก http://www.cocoadevcentral.com เพื่อน ๆ สามารถหาอ่านเพิ่มเติมได้ที่นี่และ ค้นหาได้ใน internet
ในเรื่องของการเขียนโปรแกรมกับ Objective-c นั้นส่วนต้วผมเป็นเรื่อสนุกและท้าทายนะครัย ที่กล่าวมาทั้งหมดนั้นเป็นพื้นฐานของการเขียนObjective-c เรายังต้องเรียนรู้เพิ่มอีกในเรื่องของ cocoa (เขาออกเสียงว่า โกโก้ หรือปล่าวไม่รู้นะ) และ cocoa graphic
Cocoa นั้นเป็นกลุ่มของ Framework ซึ่งประกอบด้วย Foundation, AppKit และ CoreData เป็นต้น จะช่วยให้เราพัฒนา application ให้กับ MAC OS X ซึ่งเป็นที่ทราบกันว่าเทคโนโลยีบางส่วน นั้นสืบทอดมากจาก NeXTSTEP operating system ครับค่อยพูดกันในรายละเอียดใน บทความ ต่อ ๆอีกก็แล้วกันนะครับ
ธีระพงษ์ สนธยามาลย์
s.teerapong@gmail.com
Objective-C Note ภาคต่อ 2
ยังไม่หมดนะครับเรายังมีหัวข้อที่หน้าสนใจและควรรู้เป็นพื้นฐานต่ออีก สำหรับผู้ที่สนใจใฝ่เรียนรู้หรือต้องการนำไปใช้จริงจังกับการพัฒนางาน โปรแกรมใช้บน MAC OS หรือ IOS ก็ตามนะครับ แล้วแต่ความสะดวก
การจัดการ Memory Management เพิ่มเติมจากเดิม
การจัดการ memory ของ Objective-C เรียกว่า reference counting สิ่งที่เราต้องทำก็คือติดตาม reference ของเรา และในระหว่าง runtime จะต้องมีการทำ free memory
พูดให้ง่ายก็คือ เราทำการจอง (alloc) memory ให้ object และเก็บค่าไว้ระหว่างใช้งาน (retain) แล้วทำการ คืนกลับ (release) หลังจากเลิกใช้แล้ว ให้ทำทุกการทำ alloc และ retain
หมายความว่า หาก เราทำการ alloc ครั้งหนึ่ง retain ครั้งหนึ่ง เราจะต้องทำการ release ถึง 2 ครั้งตามภาพ
ภาพจาก http://www.cocoadevcentral.com/
ที่กล่าวมาเป็นทฤษฎีของ reference counting ในทางปฏิบัติ เรามีเหตุผลในการสร้าง object อยู่ 2 เหตุผลก็คือ
1. เพื่อใช้งานเป็น instance variable
2. ใช้งานภายใน function หรือภายใน method ของ object
โดยมากแล้ว setter ของ instance variable ควรจะทำแค่การ กำจัดค่าเก่า แบบ autorelease และ retain ค่าใหม่ เพื่อความมั่นใจเราควรที่จะทำการ release มันใน dealloc อีกที ด้วย
งานที่ต้องทำจริง ๆ คือการจัดการกับ local references ใน method หรือ function และก็มีกฏเพียงข้อเดียวเท่านั้นก็คือ ถ้าหหากเราสร้าง object ด้วย alloc หรือ copy ให้ทำ release หรือ autorelease ที่ท้าย function แต่ถ้าหากเราสรา้ง object ด้วยวิธีอื่น ๆ ที่ไม่ได้พูดถึง ไม่ต้องทำอะไร
ตัวอย่างนี้ สำหรับกรณีในข้อ 1 (instance variable )
-(void) setTotalAmount:(NSNumber *)input { [totalAmount autorelease]; totalAmount = [input retain]; } -(void) dealloc { [totalAmount release]; [super dealloc]; }
จะเห็นว่าเรามี totalAmount เป็น instance variable และมีการ กำหนดค่าด้วยการ retain เราทำการ release มันอีกครั้ง ใน dealloc ถึงแม้เราจะกำหนด autorelease ให้มันก็ตาม
ตัวอย่างต่อไปก็คือกรณีถัดมาในข้อ 2 การจัดการกับ local reference สิ่งเดียวที่เราต้องทำก็คือ release object ที่ถูกสร้างด้วย alloc
NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75]; NSNumber*value2 = [NSNumber numberWithFloat:14.78]; // only release value1 , not value2
และตัวอย่างนี้ แสดงให้เห็นการใช้ local reference กำหนดค่าให้กับ instance variable ของ object
NSNumber* value1 = [[NSNumber alloc] initWithFloat:875]; [self setTotal:value1]; NSNumber*value2 =[NSNumber numberWithFloat:14.78]; [self setTotal:value2]; [value1 release];
สังเกตุวิธีการใช้กฏ สำหรับการ จัดการกับ local reference นั้นเหมือนกัน ไม่ต้องใส่ใจว่าเราใช้มันกำหนดค่าให้กับ instance variable หรือไม่ และเราก็ไม่ต้องสนใจว่า setter นั้นมีหน้าตาเป็นอย่างไร
ถ้าเราเข้าใจจุดนี้เราก็จะเข้าใจ 90% ของสิ่งที่ควรรู้ เกี่ยวกับการบริหารจัดการ memory ใน Objective-C จบปะ
Properties
อย่างที่เราได้ทำการ เขียน accessor method ให้กับ caption และ author ก่อนหน้านั้น เราอาจจะสังเกตุได้ว่า code นั้นค่อนข้างตรงไปตรงมาน่าจะสามารถทำให้เป็นรูปแบบที่ generalized ได้
Properties คือคุณลักษณะที่มีอยู่ใน objective-C ที่จะทำให้เราสามารถสร้าง accessor ได้อัติโนมัติ และนอกจากนี้ยังมีประโยชน์ข้างเคียงอืนๆอีก เรารองมาแปลง Photo class ให้ใช้ properties กันดู
ก่อนหน้ามีหน้าตาแบบนี้
#import @interface Photo : NSObject { NSString* caption; NSString* photographer; } -(NSString*) caption; -(NSString*) photographer; -(void) setCaption:(NSString*) input; -(void) setPhotographer:(NSString*)input; @end
ซึ่งเมื่อแปลงแล้วจะได้หน้าตาแบบนี้
#import @interface Photo : NSObject { NSString* caption; NSString* photographer; } @property (retain) NSString* caption; @property (retain) NSString* photographer;
@property คือ directive สำหรับการประกาศ property
“retain” ในเครื่องหมายวงเล็บเป็นการกำหนดว่า setter ต้องเก็บค่า input ไว้ และส่วนที่เหลือของบรรทัดนั้นเป็นการกำหนด ชนิด (type) และ ชื่อของ property;
ต่อไป ลองมาดูว่าหากใช้ @property จะต้องimplement class อย่าไร
#import “Photo.h” @implementation Photo @syncthesize caption; @syncthesize phtographer; -(void) dealloc { ; [photographer release]; [super dealloc]; } @end
@synthesize directive จะทำหน้าที่ในการ สร้าง setter และ getter ให้อัตโนมัติ ดังนั้นสิ่งที่เราต้องทำให้ class นี้แค่การ implement dealloc method
สิ่งที่ควรทราบก็คือ accessor จะถูกสร้างขึ้นในกรณีที่มันไม่มีเท่านั้นเราสามารถที่จะ กำหนด @synthesize ให้กับ propertiy ไว้พร้อมกับการ implement setter และ getter ของเราเองได้ ถ้าเราต้องการ หน้าที่ของ compiler คือการเติม ในส่วนที่เราขาดไป ครับ (เป็นทั้งข้อดี และ ข้อเสียนะเนี่ยย)
อย่างไรก็ตาม เรื่องของ property นี้มีรายละเอียดเพิ่มเติมอีกมากครับ ควรจะต้องศษกาาเพิ่มเติมเพื่อการใช้งานที่ดีนะครับ
ถ้าจะให้ดีก็ ว่ากันต่อไปใน คราวหน้านะครับ
ธีระพงษ์ สนธยามาลย์
s.teerapong@gmail.com
[Objective-C myNote] ภาคต่อ 1
หายไปนานแสนนานไม่ได้เข้ามา update เลย นานที่ว่าหน่วยไม่ใช่เป็นเดือนนะครับ หน่วยเป็นปี ฮะ ฮะ สำหรับ Note ที่ทิ้งค้างไว้ ก็จะมาต่อกันให้จบในคราวนี้แหละครับ สำหรับคราวที่แล้วนั้นมาจบตรงที่ การออกแบบ class interface – Designing a Class interface
เริ่มที่ หัวข้อนี้ใหม่เลย ครับ
การออกแบบ class interface – Designing a Class interface
การสร้าง class มี 2 ส่วนคือ
- Class interface เก็บไว้ใน ClassName.h
- Define instance variable and public methods
- Implementation เก็บไว้ใน ClassName.m
- Actual code
- Private method ซึ่ง ใช้ภายใน
ตัวอย่าง class ชื่อ photo
#import <Cocoa/Cocoa.h> @interface Photo : NSObject { NSString* caption; NSString* photographer; } @end
– ใช้ #import directive เพื่อบอก compiler ว่าจะเรียกใช้ library อะไร
– @interface บอกว่าเป็นการ ประกาศ class ชื่อ photo colon บอกว่า photo มี superclass เป็นอะไร
– ใน curly bracket ประกาศ variable 2 ตัว ชื่อ caption, photographer ซึ่งเป็น NSString
– จบด้วย @end
ลองมาเพิ่ม getter ให้กับ instance variable กันครับ
#import <Cocoa/Cocoa.h> @interface Photo : NSObject { NSString* caption; NSString* photographer; } caption; photographer; @end;
จำได้ไหม ครับว่าโดยการปฏิบัติทั่วไปแล้ว method ของ Objective-C นั้นจะไม่ใส่ส่วนนำ หรือ prefix “get” single dash “-” นำหน้าชื่อของ method นั้นหมายถึง ชื่อนั้นเป็น instance method ส่วนเครื่องหมาย “+” หรือ plus นำหน้่า method ก็หมยถึง ชื่อนั้นเป็น class method
lass method หมายถึง class ที่สามารถถูกเรียกใช้ได้ในขณะที่ไม่ได้เป็น object หรือ class method ก็คือ static method
สมมุติ เรามี class ชื่อว่า MathFunc ดังนี้
@interface MathFunc : Nsobject { } +(int) square:(int)num; @end @implementation MathFunc +(int) square: (int)num { return num*num; } @end
ดังนั้นการเรียกใช้จะเป็นดังตัวอย่างครับ โดยที่เราไม่ต้องมีการ instantiate ให้เป็น object เราก็สามารถเรียกใช้ฟังก์ชันได้ ( นี่เป็นการแสดงความหมายและการใช้งาน class method )
value = [[square alloc] num:5] ;
โดย default แล้ว compiler จะกำหนดชนิดของค่าที่ส่งกลับหรือค่าที่ return ของ method ใน Objective-C ให้เป็น ชนิด id จาก code ข้างบนการประกาศ method แบบนั้นในทางเทคนิคแล้วถูกต้องไม่ผิดอะไรแต่มันดูไม่ค่อยปกติ เราควรจะกำหนดชนิดของค่า return ให้เจาะจงไปเลยว่าเป็นชนิดใดดังนี้
#import @interface Photo : NSObject{ NSString* caption; NSString* photographer; } -(NSString*) caption; -(NSString*) photographer; @end;
ลองมาเพิ่ม getter ให้กับ instance variable กันครับ
#import @interface Photo : NSObject{ NSString * caption; NSString * photographer; } -(NSString*) caption; -(NSString*) photographer; -(void) setCaption: (NSString*)input; -(void) setPhotographer:(NSString*)input; @end
setter ไม่มีการ return ค่า เราจึงกำหนดด้วย void เหมือนภาษา C
การ Implement class (Class implementation)
มาทำการ Implementation โดยเริ่มที่ getter กันครับ
#import “Photo.h” @implementation Photo -(NSString*) caption{ return caption; } -(NSString*) photographer{ return photographer; } @end
ในส่วนของการ implementation นั้น กำหนดด้วย @implementation ตามด้วยชื่อ class ลงท้ายด้วย @end ลักษณะการเขียนเหมือนกับ interface method ที่ต้องการ implement ทั้งหมดจะต้องอยู่ระหว่าง 2 statement นี้นะครับ ส่วนของ getter นั้น ก็จะค่อนข้างคุ้น และง่ายต่อการเขียน
ต่อไปดูที่ setter ซึ่งเป็นส่วนที่จะต้องอธิบายเพิ่มเติมจาก code ที่แสดงให้ดู ดังนี้
-(void) setCaption: (NSString*)input { [ccaption autorelease]; caption = [input retain]; } -(void) setPhotographer:(NSString*) input { [photographer autorelease]; photographer = [input retain]; }
setter แต่ละตัวจะเห็นว่าต้องเกี่ยวข้องกับตัวแปร สองตัว ตัวแรกคือ ตัวที่อ้างอิงไปที่ ตัวแปรของ object เอง เช่น caption ส่วนตัวแปรที่ สองเป็น input ใน environment ที่เป็น garbage collected เราสามารถกำหนดค่าใหม่ได้โดยตรง เช่น
-(void) setCaption:(NSString*) input{ caption = input; }
แต่ถ้่หากเราไม่สามารถใช้ garbage collection ได้เราต้องทำการ release ค่าเก่า แล้วกำหนดค่าใหม่ให้ด้วย เครื่องหมาย autorelease และ retain ตามตัวอย่างครับ
การ ปล่อย หรือ free ข้อมูลการอ้างอิง (reference) ไปยัง object นั้นมี 2 วิธีคือ release และ autorelease
สำหรับ release นั้นจะทำการกำจัด reference ทันที ส่วน autorelease นั้นจะทำการกำจัดหลังจาก ระยะเวลาหนึ่ง และจะต้องหลังจากที่ function นั้นจบลงแล้วด้วย นอกจากจะมีการเปลี่ยนแปลงเพิ่มเติม
** autorelease method ใช้กับ setter ดูจะปลอดภัยกว่าเพราะว่าตัวแปรสำหรับค่าเก่าและค่าใหม่นั้นสามารถชี้ไปยัง object เดียวกันได้ หรือ ที่ตำแหน่งเดียวกันเราไม่จำเป็นต้องทำการ release object ที่เราต้องการ retain ค่า ทันทีทันใดก็ได้
ครับดูจะสบสน ในตอนนี้ แต่หลังจากผ่านไปสักระยะหนึ่งก็จะพอเข้าใจขึ้นนะครับ เราไม่จำเป็นต้องเข้าใจทุกสิ่งอย่างทั้งหมดในตอนนี้
Init
เราสามารถ ใช้ Init method สำหรับการกำหนดค่า เริ่มต้นให้กับตัวแปร instance ได้
-(id) init { if( self = [super init]) { [self setCaption:@”Default caption”]; [self setPhotographer:@”Default Photographer”]; } return self; }
code ค่อนข้างจะอธิบายการทำงานได้ดีอยู่แล้ว ยกเว้นในส่วนของ if( self=[super init]) ซึ่งมีลักษณะการใช้เหมือนการ assign ค่า [super init] ให้กับ self ในความรู้สึกมันแปลก ๆ
อธิบายได้ว่า เป็นการร้องขอให้ superclass ทำการ initialization ตัวเอง ส่วน if statement นั้นจะตรวจสอบว่าการ initialization นั้นสำเร็จหรือไม่ก่อนการ กำหนดค่าให้กับ self
Dealloc
Dealloc method นี้จะถูกเรียกเมื่อ object กำลังถูก remove จาก memory ซึ่งเป็นการดีที่จะทำการปล่อย reference ต่าง ๆ ที่อ้าอิงอยู่ออกไปด้วย
-(void) dealloc { ; [photographer release]; [super dealloc]; }
สองบรรทัดแรกนั้นเป็นการปล่อยหน่วยความจำในส่วนของ instance variable เราไม่ใช้การ autorelease ใช้ release จะเร็วกว่า
บบรทัดสุดท้ายนั้นสำคัญมาก เราจะต้องทำการ ร้องขอไปยัง superclass ให้ทำการปล่อยหน่วยความจำในส่วนของตัวเองด้วย หากเราไม่ทำขั้นตอนนี้ object จะไม่ถูกกำจัด ทำให้เกิด memory leak.
Dealloc method นั้นจะไม่ถูกเรียกให้ทำงานหาก garbage collection ทำงาน เราจะทำ finalizeแทน ครับในส่วนของการจัดการ memory นั้นจะขอเพิ่มเติมในรายละเอียดภายหลัง
การบริหารจัดการกับ memory เบื้องต้น [ Basic Memory Management ]
ถ้าหากเรากำลังพัฒนา application บน MAC OS X เราสามารถที่จะเลือกให้ garbage collection ทำงานได้ หมายความว่า จะทำให้เราไม่ต้องมาคำนึงถึงเรื่องการจัดการ memory จนกว่าเราจะเข้าสู่การเขียนแบบที่ซับซ้อนขึ้น เรามาเรียนรู้กันสักนิดหนึ่งนะครับ
ตั้งแต่นี้ไป สำคัญนะครับ
หากเราสร้าง object แบบใช้ alloc เราต้องทำการ release object นั้นหลังจากที่ใช้งานเสร็จแล้ว และสิ่งที่สำคัณอีกอย่างหนึ่งก็คือจะต้องไม่ ไป release object ที่ ถูกกำหนดเป็น autorelease object เพราะว่าจะทำให้ application นั้นล่มเอาง่าย ๆ
// string1 will be release automatically NSString * string1 = [NSString string]; // must release this when done NSString * string2 = [[NSString alloc] init]; [string2 release]
สำหรับ tutorial นี้ให้จำไว้ว่า object แบบ autorelease นั้นจะถูกกำจัดเมื่อจบ funciton นั้น
มีหลายสิ่งที่เราต้องเรียนรู้เกี่ยวกับการจัดการ memory ซึ่ง ความเข้าใจจะมากขึ้นเมื่อเราได้เรียนรู้หรือเข้าใจ concept เพิ่มเติมจากนี้
จบลงตรงนี้ก่อนนะครับ ค่อยต่อกันตอนต่อไปนะครับ
s_teerapong2000@yahoo.com
[Objective-C myNote]
Objective-C เป็น ภาษาที่ใช้เป็นหลักในการพัฒนาโปรแกรมใน MAC และ iPhone
บันทึกนี้เหมาะสำหรับ ท่านที่มีประสบประการณ์ ในการเขียนโปรแกรม แล้วและเข้าใจ object-oriented ดี ไม่เหมาะสำหรับผู้เริ่มหัดเขียนโปรแกรม นะครับ เพราะจะอ่านไม่รู้เรื่อง เอานะครับ ฮะ ฮะ เอิก
เอาว่าถ้า เริ่มศึกษา Objective-C ก็เชิญไปที่นี่ก่อนะครับ Learn Objective-Cหรือว่าที่นี่ก็น่าจะเป็นที่เริ่มต้นได้เป็นอย่างดี ครับ Cocoadevcentrol.com
สำหรับในบทความเล็ก ๆนี้จะ เป็น บันทึกสั้น ๆ ในเรื่องต่าง ของ Objective-C ดังนี้ครับ
- Method
- Accessor
- การสร้าง Objects (Creating Objects)
- การจัดการกับ Memory – Basic Memory Management
- การออกแบบ class interface – Designing a Class interface
- Init
- Dealloc
- การจัดการกับ memory ,Memory Management (เพิ่มเติม)
- Logging
- Properties
- Calling Methods on Nil
- Categories
Method
- การรียกใช้ methods
[ object method];
[ object methodWithInput:input];
- การ return ค่า จาก method
Output = [object methodWithOutput];
Output = [object methodWithInputAndOutput:input];
ข้อสังเกต นะครับการเรียก method คือการส่ง message ให้ object
การเรียก method ของ class เช่น การเรียก string method ของ NSString class ซึ่ง ให้ค่าเป็น
NSString object
id myObject = [NSString string];
id type หมายถึงตัวแปร myObject สามารถอ้างอิงไปยัง object ใด ๆ ประมาณ late binding นะครับ หมายความว่าหากเราเรียก method ที่ NSString ไม่มี ก็ไม่แสดง error ในหว่างทำการ compile
[จากตัวอย่างเป็นวิธีการ สร้าง object ของ Objective-C เขา นะครับ]
NSString* myString = [NSString string];
ครับสำหรับ ตัวอย่างนี้เป็นการ สร้าง object NSString ชี้โดย myString ซึ่งให้เป็น NSString
Compiler จะตรวจสอบได้ หากเรียกใช้ method ที่ไม่มี ใน NSString นะครับ
สังเกตว่า ตัวแปร object ใน Objective-C จะเป็น pointer แต่ id type จากตัวอย่างด้านบนไม่ต้องมี * เพราะมันถูกกำหนดให้เป็น pointer อยู้แล้ว เพราะฉะนั้นไม่ต้องใช้
การเรียก Message แบบ ซ้อน กัน [Nested messages]
[NSString stringWithFormat:[prefs format]];
การเรียก ซ้อนกันก็ไม่ควรเรียกซ้อนกันไม่เกิน 2 message ต่อบรรทัด เพื่อให้สามารถอ่านได้ง่าย
Methods แบบ หลาย Input
เหมือนทั่วไปครับ method สามรถ รับค่าได้ มากกว่า 1 ค่า ใน Objective-C ก็เช่นเดียวกันแต่ Objective-C นั้น ใช้การแตก ชื่อ method ให้เป็นหลาย ๆ ส่วนเพื่อรับข้อมูล หรือ argument ดังตัวอย่าง
การประกาศ :
-(BOOL) writeToFile:(NSString *)path atomatically:(BOOL) usAuxilliaryFile;การเรียกใช้ :
BOOL result = [myData writeToFile:@”/tmp/log.txt” automatically:NO];
ชื่อmethod ก็คือ writeToFile: automatically: ครับ ไม่ใช่ ชื่อ argument นะครับ
Accessor
Instance variable โดย default เป็น private ในการ กำหนดค่า (set) หรือการรับค่า จาก variable จะต้องใช้ accessors สามารถทำได้ดังนี้ครับ
Traditional 1.x sytax
[photo setCaption:@”Day at the Beach”];
Output = [photo caption];
ครับเราจะเห็นว่าการ ใช้งาน accessor นั้น ก็คือการเรียกใช้ method นั่นเอง
จำไว้ว่าเมื่อใดก็ตามที่เห็น code อยู่ใน square brackets หมายถึง เป็นการส่ง message ให้กับ object หรือ class นะครับ
จากตัวอย่าง ที่ บรรทัดที่ 2 caption ไม่ได้ นำด้วย get ใน Objective-C โดยมากจะไม่ใส่ prefix ให้กับ getter ครับ
Dot syntax
สำหรับ dot syntax สำหรับ getter และ setter นั้น เริ่มมีใน Objective-C 2.0 Mac OS X 10.5 เป็นต้นมาครับ
photo.caption = @”Day at the Beach”;
output = photo.caption;
เราเลือกใช้แบบใดก็ได้นะครับ เลือกเอาซะแบบหนึ่ง นะครับ
การสร้าง Objects (Creating Objects)
การสร้าง Object ใน Objective-C สามารถทำได้ 2 วิธี
วิธีแรกเป็นวิธีที่เรา แสดงให้เห็นแล้วก่อนหน้านี้
NSString* myString = [NSString string];
วิธีนี้เป็นแบบ automatic style ครับ สร้างโดยการใช้ autoreleased object ซึ่งจะพูดถึงต่อไป หลังจากนนี้ครับ
อีกวิธีหนึ่ง เรียกว่า manual style คือต้อง ทำ release memory เองหลังจากใช้ object แล้ว ครับ
NSString* myString = [[NSString alloc] init];
จาก code เป็นการเรียก method แบบ ซ้อนกัน (nest)
– Alloc เพื่อ จ้อง memory และ สร้าง object
– Init เป็นการ เรียก method ใน object ที่ถูกสร้างขึ้น มักใช้ในการ กำหนดค่าเริ่มต้นต่าง ๆ ในบางกรณี เราใช้ init ที่รับ input ได้ เช่น
NSString* value = [[NSString alloc] initWithFloat:1.0] ;
การจัดการกับ Memory – Basic Memory Management
ถ้าเรา สร้าง object โดยใช้ alloc อย่างที่กล่าวไป เราต้องทำการ release object หลังจาก ใช้เสร็จ ครับ
ตัวอย่างเช่น
// string1 will be released automatically
NSString* string1 = [NSString string];// must release this when done
NSString* string2 = [[NSString alloc] init];
//..
[string2 release];
การออกแบบ class interface – Designing a Class interface
การสร้าง class มี 2 ส่วนคือ
- Class interface เก็บไว้ใน ClassName.h
- Define instance variable and public methods
- Implementation เก็บไว้ใน ClassName.m
- Actual code
- Private method ซึ่ง ใช้ภายใน
ตัวอย่าง class ชื่อ photo
#import <Cocoa/Cocoa.h> @interface Photo : NSObject { NSString* caption; NSString* photographer; } @end
– ใช้ #import directive เพื่อบอก compiler ว่าจะเรียกใช้ library อะไร
– @interface บอกว่าเป็นการ ประกาศ class ชื่อ photo colon บอกว่า photo มี superclass เป็นอะไร
– ใน curly bracket ประกาศ variable 2 ตัว ชื่อ caption, photographer ซึ่งเป็น NSString
– จบด้วย @end
เอาไว้ต่อกันใน ตอนถัดไปดีไหม ครับ ยาวเกินไปแล้ว
s_teerapong2000@yahoo.com
ธีระพงษ์ ส.