Posts Tagged ‘Objective-C’

การบันทึก State ของ iPhone App ด้วย NSUserDefaults

Monday, June 14th, 2010

การบันทึก State ของ iPhone App คืออะไร?

มันคือการบันทึกค่าต่างๆ เพื่อที่ว่าเมื่อ user ปิด app แล้วเปิดขึ้นมาใหม่ก็จะได้ค่าเดิม เทียบได้กับ INI file ของ Windows นั่นเอง

สื่งที่ต้องทำมีสองส่วนคือ ตอน Save กับตอน Load ค่า

1. การ Save state ควรเรียกทุกครั้งที่มีการยืนยันการเปลี่ยนแปลงค่า บางท่านชอบ save ตอนจะปิดโปรแกรมทีเดียว (ใน applicationWillTerminate) ซึ่งมักจะเจอปัญหาว่าถ้าเครื่อง hang ค่าก็จะไม่ทันได้ save

1
2
3
NSUserDefaults *defaults =  [NSUserDefaults standardUserDefaults];
[defaults setInteger:myValue forKey:@"myKey"];
[defaults synchronize];

จากตัวอย่างข้างต้นเป็นการ save ค่า integer ของตัวแปรชื่อ myValue ด้วยชื่อ key ว่า myKey
จะเห็นว่ามีการเรียก [defaults synchronize] ด้วย เป็นการบอกว่าให้ save ค่านี้ทันที

2. การ Load state ควรจะเรียกครั้งแรกครั้งเดียวตอนเปิดโปรแกรม

1
2
3
4
5
NSUserDefaults *defaults =  [NSUserDefaults standardUserDefaults];
int myValue = [defaults integerForKey:@"myKey"];
if(myValue) {
	//set default value for myValue
}

จากตัวอย่างข้างต้นเป็นการ load ค่าจาก key ที่ชื่อว่า myKey มาใส่ตัวแปรชื่อ myValue
โดยหากหากไม่มีค่า (เช่น เปิดใช้โปรแกรมเป็นครั้งแรก) ก็จะให้ใช้ค่า default แทน

นอกจาก integer ตามตัวอย่างข้างต้นแล้ว เรายังสามารถบันทึกค่าประเภทอื่นๆได้อีก แนะนำให้อ่านที่ NSUserDefaults Class Reference ครับ

ทุกอย่างที่คุณควรรู้กับ Java เมื่อกษัตริย์คืนบัลลังก์

Wednesday, June 9th, 2010

ไม่มีอะไรมากครับ ตั้งชื่อล้อหัวข้อข่าวของ mk ณ Blognone เท่านั้นเอง

เรื่องของเรื่องคือ แม้ว่าความนิยมของ Java จะลดลงเรื่อยๆ ถึงขนาดเมื่อเดือนก่อน (May 2010) ก็หล่นจากบัลลังก์มาอยู่อันดับ 2
แต่เดือนนี้แม้ % ความนิยมจะยังลดลงต่อเนื่อง แต่เมื่อเทียบกับคู่แข่งแล้วก็ยังสามารถกลับมาอยู่อันดับ 1 ได้
และคาดว่าคงจะขึ้นๆลงๆแบบนี้อีกหลายรอบซะด้วย

สำหรับคนที่ใช้ Java อยู่ไม่ต้องกังวลนะครับ ว่าภาษาจะล้มหายตายจากไปในเร็ววันนี้
Java ยังคงได้รับความนิยมอยากมากในงาน Enterprise เนื่องจากการพลักดันของยักษ์ใหญ่ในวงการ ไม่ว่าจะเป็น IBM, Oracle, SAP เป็นต้น
หรือวงการ Open source ก็ยังมีการใช้ Java อีกมากเช่น Apache, Eclipse, Spring, หรือแม่กระทั่ง Google
หรือแม้แต่ Mobile App อย่าง Android หรือ Blackberry ก็ยังใช้ Java เป็นหลักในการพัฒนา App

ที่น่าสนใจนอกจาก Java แล้วก็ยังมี Objective-C ที่ขึ้นเอาขึ้นเอาไม่ยอมหยุด
ล่าสุดหลังจากที่ขึ้นมาติด top 10 ได้แล้ว ก็ยังขึ้นต่อจนตอนนี้ อันดับ 9 แล้ว
ต้องดูกันต่อครับว่าจะแรงได้นานแค่ไหน

ดูอันดับที่เหลือทั้งหมดได้ที่นี่ครับ
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

How to use autorelease in Objective-C and iPhone SDK

Sunday, June 6th, 2010

จากคราวที่แล้วที่ผมพูดเกี่ยวกับ Memory Management in Objective-C and iPhone SDK ด้วยการใช้ alloc และ release

วันนี้เราจะมาดูกันว่าวิธีการใช้ autorelease นั้นดีกว่ายังไง

เดิมนั้นในการสร้าง instance จาก Class นั้นเราจะเขียน code ประมาณนี้

1
2
3
MyClass *myObj = [[MyClass alloc] init];
//Do something with myObj
[myObj release];

โดย alloc เป็น class method (เทียบได้กับ static method ใน Java/C++) ทำหน้าที่สร้าง instance เปล่าๆขึ้นมา
ส่วน init เป็น instance method ทำหน้าที่กำหนดค่าเริิ่มต้นให้กับ instance นั้น

เราจะดัดแปลงการสร้าง instance ของ MyClass ให้มีประสิทธิภาพมากขึ้นดังนี้
- ไม่ต้องมีการเรียกใช้ alloc และ release
- เปลี่ยนจากการเรียกใช้ init ที่เป็น instance method ไปเป็นการเรียกใช้ class method เพื่อสร้างและกำหนดค่าเริ่มต้นให้กับ instance พร้อมๆกัน

โดย Code ที่จะเรียกใช้จะเป็นดังนี้

1
MyClass *myObj = [MyClass getInstance];

จะเห็นว่าไม่มีการเรียกใช้ alloc, release และเปลี่ยนการเรียก init มาเป็น getInstance แทน (ชื่อ getInstance เป็นชื่อที่เรากำหนดได้เอง)

มาดูในส่วนของ Implementation ของ MyClass บ้างว่าต้องแก้ไขอย่างไร

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#import "MyClass.h"
@implementation MyClass
 
+ (MyClass *)getInstance {
	MyClass *myObj = [[MyClass alloc] init];
	[myObj autorelease];
	return myObj;
}
 
- (id)init {
	if (self = [super init]) {
		//Do init own instances
	}
	return self;
}
 
- (void)dealloc {
	//Do release own instances
	[super dealloc];
}
@end

ส่วนที่เราเพิ่มเข้าไปในบรรทัดที่ 4-8 คือ
- การ implement method ที่ชื่อ getInstance โดยการทำงานคือ encapsulate ในส่วนของการเรียก alloc และ init ที่ก่อนหน้านี้ถูกเรียกอยู่ภายนอก
- แทนการเรียกใช้ release ด้วย autorelease

โดยใน MyClass.h เราต้องมีการประกาศ getInstance ด้วย เนื่องจากเป็น method ใหม่ที่เรากำหนดขึ้นมาเอง

สรุปได้ว่าเราใช้ getInstance ข้างต้นเพื่อ encapsulate การจองและคืนหน่วยความจำนั่นเอง

นอกจากนี้เรายังสามารถกำหนด method ที่หลากหลาย เพื่อที่จะสร้าง instatnce ที่มีคุณสมบัติแตกต่างกันได้ ดังตัวอย่างนี้

1
+ (MyClass *)getInstanceWithName:(NSString *)name;

วิธีข้างต้นเป็น Best Practice ที่ใช้กันอย่างแพร่หลายใน Class มาตรฐานของ Obejctive-C เช่น NSString ที่มี method ที่ใช้สร้าง instance ชื่อ string และ stringWithFormat เป็นต้น

Memory Management in Objective-C and iPhone SDK

Saturday, June 5th, 2010

เนื่องจากข้อจำกับของ iPhone SDK ทำให้ไม่สามารถมี Garbage Collector ได้ ดังนั้นเราจึงต้องมาจัดการในเรื่องการจองและคืนหน่วยความจำเอง

สอง method หลักๆที่เราต้องเรียกในครั้งนี้คือ

1. alloc เทียบได้กับ malloc ใน C

2. dealloc เทียบได้กับ free ใน C โดยเราจะไม่เรียกใช้ตรงๆแต่จะเรียกผ่าน release method

มาดูตัวอย่างกันดีกว่า

1
2
3
MyClass *myObj = [[MyClass alloc] init];
//Do something with myObj
[myObj release];

จากตัวอย่างข้างต้น
- เรามีการจองหน่วยความจำด้วย alloc และเรียก init ของ instance นั้น (เทียบได้กับ contructor ใน Java/C++)
- หลังจากเราใช้งาน instance นี้เสร็จแล้ว เราก็ทำการคืนหน่วยความจำด้วยการเรียก release

มาดูในส่วนของ Implementation ของ MyClass บ้างว่าต้องทำอะไร

MyClass.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import "MyClass.h"
@implementation MyClass
 
- (id)init {
	if (self = [super init]) { 
		//Do init own instances
	} 
	return self;
}
 
- (void)dealloc {
	//Do release own instances
	[super dealloc];
}

จากตัวอย่างข้างต้นเรามี 2 methods คือ
- init ที่ถูกเรียกหลังจากจองหน่วยความจำด้วยการเรียก alloc แล้ว
- และ dealloc ที่จะทำงานเมื่อมีการเรียก release นั่นเอง
ทั้ง 2 methods นั้นเป็นการ override มาจาก Base Class (NSObject) ดังนั้นเราจึงไม่ต้องประกาศใน MyClass.h ส่วน alloc นั้นเราไม่ต้อง implement ครับ

ในคราวหน้าผมจะพูดถึงเกี่ยวกับการใช้ autorelease แทน release ซึ่งจะช่วยลดความสับสนว่าเมื่อไหร่ควรจะเรียก release ครับ

วิธีการเปลี่ยน __MyCompanyName__ ใน Xcode

Friday, June 4th, 2010

ช่วงนี้งานอดิเรกเป็น Objective-C ครับ

สำหรับใครที่เคยเจอว่า new file หรือ new project แล้ว file template แสดงชื่อบริษัทเป็น __MyCompanyName__

วิธีแก้ให้พิมพ์คำสั่งนี้ใน terminal (แทน www.choopong.com ด้วยชื่อบริษัทของคุณ) จากนันก็ restart Xcode ใหม่ก็จะได้ชื่อบริษัทที่ต้องการเวลา new file หรือ new project แล้วละครับ

defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions -dict ORGANIZATIONNAME "www.choopong.com"