Posts tagged ‘mac’

Magic of NSLog

การ Log ที่ดี ก็มีผลให้การทำงานเราสะดวกรวดเร็วขึ้นนะครับ แน่นอน การใส่สัญลักษณ์ไว้ใน Log ก็เป็นวิธีการแบบลูกทุ่งๆอย่างนึงที่ใช้ง่ายและได้ผล แต่เยอะๆเข้าแทนที่จะช่วยให้เร็วขึ้นมันจะเป็นตรงกันข้าม เพราะลายตากับ Log ไปหมด หรือจะให้ระบุรายละเอียดกันทุกบรรทัด ก็เสียเวลาเกินไป ใน Entry นี้ ผมเอา Trick การ Log ให้มีประสิทธิภาพมากขึ้นมาฝากครับ

Trick #1 : รู้รึเปล่า ว่าการทำงานพร้อมกับการ Log ค่าไปด้วย ทำให้เป็นการลดประสิทธิภาพการทำงานของ App ลงไปเยอะเลย ก่อน  Submit app ขึ้น App store เราควรจะ remove log ของเราออกไปด้วย …จริงอยู่ว่า App ทั่วไปอาจไม่มีผลต่อประสิทธิภาพโดยนัย แต่ถ้าเป็นเกม …มีนัยครับ ดังนั้น เราจะสร้าง Log ของเราเองขึ้นมา ที่ให้ Log ค่า ตอนที่ XCode ตั้งค่าเป็น Debug mode เท่านั้น ใส่โค้ดพวกนี้ในไฟล์ xxx_Prefix.pch ของโปรเจค เพื่อให้มีผลกับทั้งโปรเจคครับ

#ifdef DEBUG
# define JELog(fmt,...) NSLog(@"%@",[NSString stringWithFormat:(fmt), ##__VA_ARGS__]);
#else
# define JELog(...)
#endif

อธิบายโค้ดดังกล่าวได้ว่า เราสร้าง JELog ขึ้นมาเพื่อให้มันทำงานเหมือน NSLog เลย แต่จะพิมพ์ออกทางหน้าจอเมื่อ Preprocessor Macro ถูกเซตคำว่า DEBUG เอาไว้ แต่ถ้าไม่ได้เซตก็ไม่ต้องทำอะไร

ส่วนการเซตค่า  Preprocessor Macro ไปเลือกที่ Project->Edit Project Settings เลือก Debug ในช่อง Configuration และใส่ค่า DEBUG (หรือคำอื่นๆที่นิยามไว้) ใน Preprocessor Macro เซคชั่น GCC 4.2 – Preprocessing

…แค่นี้แหละครับ เสร็จแล้ว คราวนี้เรา Build ในโหมด Release ก็ไม่มี Log มาบั่นทอนประสิทธิภาพ App เราแล้ว

Trick #2: จะดีแค่ไหน ถ้าการ Log ทำให้เรารู้ได้ว่า มันโดน Log มาจาก Function อะไร และบรรทัดไหน เราสามารถเพิ่มมันได้เอง ในรูปแบบที่เราต้องการ และไม่ต้องเหนื่อยมาใส่แบบลูกทุ่งทีละบรรทัดทีละ Log ด้วย ทำได้ง่ายๆแบบนี้ครับ

#define JELog(fmt,...) NSLog((@"%s-%d:" fmt),__PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

เพียงเท่านี้ เราก็ Log สิ่งที่เราต้องการพร้อมชื่อ Function และบรรทัดนั้นได้ง่ายๆแล้วครับ นอกจากนี้ยังมี __FILE__ เพื่อ log ชื่อไฟล์ชื่อนั้นอีก แต่ผมไม่ใส่เพราะผมไม่ใช้ อิอิ

ครับ สำหรับ Entry นี้ก็คงกล่าวถึงแค่นี้ ส่วนถ้าใครยังไม่สะใจอยากแต่งอยากเติมอีก ก็เข้าไปดูในเครดิตครับ มีคนทำไว้หลายแบบเหมือนกันสำหรับผม แค่นี้ก็สบายแล้ว หุหุ …ว่าแล้วก็จบเท่านี้ดีกว่า Happy Logging นะครับ ;)

Credits:

@memogames
iphoneprogrammingfordummies.blogspot.com
Stack Overflow : NSLog Tip & Trick

มีนาคม 24, 2011 at 5:23 pm ใส่ความเห็น

iPhone’s project multi-target programming

ท่ามกลางสถานการณ์บ้านเมืองรุนแรงอย่างนี้ อัพบลอกดีกว่า (เอ๊ะ ไม่เกี่ยว) บลอก Entry นี้จริงๆควรจะอัพขึ้นไปตั้งแต่อาทิตย์ที่แล้ว แต่ด้วยเหตุผิดพลาดบางประการ ที่พิมพ์ไปเสร็จแล้วพออัพขึ้น ที่พิมพ์ไว้ดันหายไปไหนหมดก็ไม่รู้ จากนั้นก็ต้องมานั่งบิ๊วอารมณ์กันใหม่อีกรอบ บัดนี้ก็ถึงเวลาเขียนอีกรอบแล้ว

ในการพัฒนา App ไม่ว่าจะบน Mac หรือ iPhone ก็ตาม คงจะเคยเห็นกันว่าบาง App มีหลายเวอร์ชัน เช่น Lite, Standard, Full, Pro, etc.. ซึ่งความแตกต่างส่วนมากก็มักจะเป็นเรื่องของการจำกัด Feature หรือ App บางตัวที่อยู่บน Platform Mac ก็มาอยู่บน iPhone ต่อ อย่างเช่นเกม plant vs zombie หรือ twitter client อย่าง echofon เป็นต้น

ถ้าถามหลายๆคนถึงวิธีการ Develop App พวกนี้ให้เป็นหลายๆเวอร์ชั่นดังกล่าว หลายๆคนอาจจะใช้วิธีการ Duplicate project โดยการ Copy file ทั้งโปรเจคมา แล้วเข้าไปแก้โค้ด ตัด feature ไปตามเวอร์ชั่นๆไป (ดูไม่ make sense เท่าไหร่ แต่ผมเชื่อว่ามี และเยอะด้วยที่ทำแบบนี้) ผมเองก็เคยเช่นกันครับ ทำ App 8 เวอร์ชั่นเลยทีเดียว(จริงๆก็ไม่ได้เห็นด้วย แต่เขาสั่งมาก็ต้องทำ) ปัญหาที่เจออย่างหนักหน่วงเลยก็คือ “การแก้ไข Bug ยุ่งยากและเสียเวลาเป็นที่สุด” เพราะบั๊ก 1 จุดต้องใช้เวลาเพิ่มเป็น 8 เท่าและความแน่นอนว่าการแก้แบบเดียวกันกับโปรเจคเวอร์ชั่นต่างๆกัน มันอาจใช้ไม่ได้ผลซะด้วย

ดังนั้นการทำ App หลายๆเวอร์ชั่นด้วยวิธีการ Duplicate project ไม่น่าจะเป็นทางเลือกที่ควรนัก สำหรับการทำโปรเจคหลายๆเวอร์ชั่น โดยเฉพาะตอนที่ iPad มันเริ่มเข้ามาแล้วอย่างเช่นตอนนี้ ตามจริงมันก็ไม่ควรเป็นแบบนั้นอีกเช่นกัน ในเมื่อ XCode มี Target ให้ใช้อยู่ แล้วทำไมเราถึงไม่ใช้มันล่ะ

Target คืออะไร? Target เปรียบเสมือนพิมพ์เขียวที่กำหนดค่าต่างๆในขั้นตอนการ build ผลก็คือ เราสามารถกำหนดได้ว่าตั้งแต่ target ไหนชื่ออะไร ใช้ไอค่อนตัวไหน ไฟล์ไหนบ้างที่จำเป็นต่อการ build ยันรูปแบบผลที่ได้ว่าต้องการเป็น Application หรือ static library

เวลาเรา Create project ขึ้นมาซักตัว Target จะมีมาให้โดยปรกติเลย 1 ตัว ซึ่งจะอยู่ใน Section Targets ซึ่งเราสามารถเพิ่มได้ตอนไหนก็ได้ โดยการไปที่ Menu Project > New Target… จากนั้นจะขึ้น Window ขึ้นมาให้เลือก Target แบบที่เราต้องการ จากนั้นก็ตั้งชื่อ Target ที่สร้างขึ้น กด Finished ก็เป็นอันเสร็จเรียบร้อย (ตอนนี้เรากำหนดรูปแบบได้แล้ว)

ผลที่ได้จะได้ Target อันใหม่มา 1 อันและ Plist สำหรับ Target นั้นอีก 1 ไฟล์ Plist ก็เป็นที่รู้กันว่าไว้สำหรับการตั้งค่าต่างๆเช่น icon, bundle id, bundle name, etc… ซึ่งเราก็สามารถกำหนดได้ตามต้องการ Target ตัวใหม่ก็เช่นกันเราสามารถกำหนด Framework ที่ใช้ product name, platform ของ Application, etc… ตั้งค่าได้ทั้งหมดราวกับว่ามันเป็นคนละโปรเจคนั่นแหละครับ

องค์ประกอบของ Target ก็มีต่างกันไป ใน Entry นี้ขอพูดถึงแต่แบบ Application เท่านั้นนะครับ Application จะประกอบด้วย 3 ส่วนคือ

component.png

  1. Copy Bundle Resources – เป็นส่วนของ Resource ต่างๆใน Project พวก รูปภาพ, ไฟล์เสียง, วิดีโอ, ฯลฯ
  2. Compile Sources – เป็น Source code ล้วนๆครับ เอาแต่ไฟล์ .m เท่านั้น แล้วก็สำหรับ project จะต้องมี main.m ด้วยนะครับ อย่าลืม ไม่งั้น App จะรันไม่ได้นะครับ สำคัญมาก!!
  3. Link Binary With Libraries – เป็น Framework ที่ใช้ร่วมครับ ปรกติก็จะมี UIKit.framework ตัวนึงละ (สำหรับ iPhone/iPad) หรือไม่ก็ Cocoa.framework (สำหรับ Mac App)

วิธีการก็คือ Target ไหนใช้อะไร Compile บ้างก็ลากใส่เข้าไปตามหมวดหมู่ที่บอกข้างต้นครับ ไม่มีอะไรมาก หรือเวลาที่เรา Add ไฟล์อะไรก็ตามเข้ามาใน Project จะมี Sheet ขึ้นมาถามเราว่า ไฟล์นั้นจะ Copy หรือไม่ จะ link กับ Project อะไรยังไง ก็ให้ลองสังเกตด้านล่างครับ ว่าจะมีถาม Target ไหนด้วย เราก็สามารถเพิ่ม Resource ให้กับแต่ละ Target ผ่านทางนี้ได้เช่นกัน

addtoproj.png

อันนี้เป็นผลพลอยได้ของการสร้าง Target ตั้งแต่แรกๆครับ ส่วนถ้าไม่ได้ทำไว้แต่แรกก็ต้องมาลกาเพิ่มเอาเอง หรืออีกวิธีนึงคือ Duplicate target เอาแล้วค่อยเพิ่ม/ตัดออก เอาก็ยังได้ แต่วิธีนี้ต้อง config อะไรเยอะหน่อยเพื่อไม่ให้มันทับกัน และผมจะไม่ขอพูดถึงในที่นี้นะครับ มันค่อนข้างเยอะ

ต่อไปเป็นวิธีการเลือก Target วิธีการไม่ยากเลย กำหนดเอาที่ปุ่มด้านซ้ายบน กดแล้วจะขึ้น Menu ขึ้นมา ก็เลือก Target ที่ต้องการ build แค่นี้แหละครับ เสร็จแล้ว ง่ายจัง

settarget.png

เราได้ Target ใหม่แล้วสามารถ Config ได้ตามต้องการ คราวนี้เราจะสามารถใช้ source code เดียวกันแต่กำหนดการทำงานให้ต่างกันตาม target ได้หรือไม่ เพราะไม่งั้นการสร้าง target ก็ไม่มีประโยชน์อะไรเท่าไหร่ เพราะต้องเขียน class มากกว่ารอบเดียวขึ้นไปอยู่ดี ? คำตอบคือ “ได้ครับ” วิธีการที่ผมใช้ก็คือ “การตั้ง Tag ให้ Target แล้วเขียน source code กำหนดไปแต่ละ target โดยดูค่าจาก tag นั่นแหละ” (งงมั้ยเนี่ย)

ขั้นตอนก็คือ ไปตั้ง Tag ให้ Target โดยการ Double click ที่ target ที่ต้องการตั้ง tag (ขอเรียกแบบนี้แล้วกัน) ไปที่ Tab build แล้ว search Setting ว่า Other C Flags (อยู่ใน GCC 4.2 Language ครับ) ตั้งค่าเป็น “-DTARGET_NAME=1” ค่าหลังเครื่องหมาย = ก็แล้วแต่จะตั้งนะครับ

targetname.png

จากนั้นในส่วนของ Source code ที่ต้องการให้มีความแตกต่างในแต่ละ Target ก็จะใช้คำสั่ง #if เข้ามาช่วยครับ คำสั่งนี้จะเป็น if ในระดับของการ build เท่านั้น ไม่เกี่ยวกับ application logic ครับ ตัวอย่างการโค้ดก็เป็นแบบนี้

// Implement for each target

#if TARGET_NAME == 1
[aButton setHidden:NO];
[bButton setHidden:NO];
#elif TARGET_NAME == 2
[aButton setHidden:YES];
[bButton setHidden:NO];
#else
[aButton setHidden:YES];
[bButton setHidden:YES];
#endif

จากโค้ดตัวอย่างเป็นการ implement ง่ายๆนะครับ แค่ทำให้ดูว่า คำสั่ง #if, #elif, #endif รูปแบบเป็นไงบ้าง น่าจะพอเห็นภาพนะครับ

สำหรับ Entry นี้ก็คงจะพอแค่นี้นะครับ Entry หลังๆเกี่ยวกับ Target และ iPad ไว้ได้ลองของจริงแล้วจะเอามาแชร์ให้กันอีกนะครับ ตอนนี้ก็ happy coding สวัสดีครับ ;)

เมษายน 10, 2010 at 4:57 pm ใส่ความเห็น

Array in Objective-C & How to shuffle members

Class Array container ในภาษา Objective-C คือ NSArray และ NSMutableArray (จริงๆมีอีกอย่างคือ NSArrayController แต่ตอนนี้ยังมีอยู่ใน Cocoa เท่านั้น ไม่มีใน iPhone) ซึ่งความต่างระหว่าง NSArray และ NSMutableArray ก็คือ “ความสามารถในการแก้ไขภายหลังการ Initialize แล้ว” พูดง่ายๆ NSArray มี access attribute เป็น read-only แต่ NSMutableArray เป็น read-write นั่นเอง

คำถามต่อมาคือ “แล้วใช้ตัวไหนดี?” คำตอบก็คือ “ใช้ได้ทั้งคู่ครับ แตกต่างกันที่ Performance เล็กน้อยเท่านั้น” โดยส่วนตัวผมใช้ตามความสะดวก ถ้าจำเป็นต้อง read-write ก็ใช้ NSMutableArray ซึ่งการใช้งาน NSMutableArray ก็ดูตาม Document ได้เลย

อย่างที่บอกว่า NSMutableArray สามารถแก้ไขหลังจาก Initialize ได้ ดังนั้นแน่นอนว่า “ต้อง sort ได้ด้วย” ซึ่งใน Entry นี้ผมจะนำเสนอการ sort แบบ Random ผมต้องการ sort members ใน mutable array แบบสุ่ม ผมสามารถทำได้ดังนี้

int randomSort(id obj1, id obj2, void *context ) {
    // returns random number -1 0 1
    return (arc4random()%3 - 1);
}

- (void)shuffle {
    // call custom sort function
    NSMutableArray *puzzles = [NSMutableArray arrayWithObject:@"1", @"2", @"3", @"4", @"5", nil];
    [puzzles sortUsingFunction:randomSort context:nil];

    NSLog(@"Members after shuffle = %@", puzzles); 
}

จากโค้ด ผมสร้าง mutable array ขึ้นมา 1 ชุดแล้วสั่งให้ sort ด้วยฟังก์ชั่น randomSort ซึ่งใน randomSort จะทำการสุ่มค่า 3 ค่า คือ -1, 0, 1 ซึ่ง -1 หมายถึง การเรียงแบบตามลำดับ(NSOrderAscending) 0 หมายถึง การเรียงแบบปกติ (NSOrderSame) และ 1  หมายถึงการเรียงแบบกลับด้าน(NSOrderDescending) ซึ่งฟังก์ชั่น sort จะจัดลำดับของ member แต่ละตัวจากผลที่ได้จากสุ่มนั่นเอง

ส่วน arc4random เป็นฟังก์ชั่นสุ่มของ ภาษา C ครับ การใช้คำสั่ง rand() หรือ random() มันเป็นการสุ่มที่ไม่ dynamic เท่าไหร่นัก ผลลัพธ์ที่ได้จากการสุ่มจะเหมือนกันทุกครั้ง

เพียงเท่านี้เราก็สามารถสุ่มสมาชิกใน mutable array ได้แล้ว นอกจากนี้ยังมีการ sort อื่นๆได้อีกนะครับ เจออันไหนน่าสนใจผมจะมาแนะนำอีกใน Entry ต่อๆไปนะครับ

#reference http://stackoverflow.com/questions/56648/whats-the-best-way-to-shuffle-an-nsmutablearray

กุมภาพันธ์ 4, 2010 at 12:45 am ใส่ความเห็น

XCode custom template

…กลับมาแล้วครับ

กลับมาแล้วสำหรับ Entry iPhone Development แต่คราวนี้จะกลับมาเขียนที่นี่ที่เดิม เพราะ Host ของเวบ i-gee กำลังจะหมดอายุแล้ว แล้วผมเองก็ไม่ได้ทำอะไรกับมันมากซะด้วย คิดว่าจะไม่ต่ออายุและปล่อยให้มันหมดไป ถ้าจะเปิด Web ใหม่อีกครั้ง คงหา Community ให้ได้ซักจำนวนหนึ่งก่อน แล้วมาช่วยๆกันเขียนดีกว่า ใครสนใจก็คุยกันได้นะครับ

กลับมาคราวนี้ เริ่มต้นกันที่เรื่องที่(ดูเหมือนจะ)ยาก แต่จริงๆแล้วง่ายมากๆ และใช้ประโยชน์ได้มากด้วยเช่นกัน เรื่องนั้นก็คือเรื่องของ Template

โดยปกติแล้ว apple จะมี Template สำหรับการพัฒนา Application แบบต่างๆมาให้เราใช้ เช่นแบบ View-based, Tableview-based etc… ซึ่ง โดยปกติแล้ว เวลาเราเริ่มโปรเจคก็จะเริ่มกันจาก Template พวกนี้ แต่ถ้างานของเรามันนอกเหนือจาก Template ที่ Apple ให้มา

อย่างเช่นงานที่ผมทำอยู่ Application ของ True ทุกตัว จะมี Intro screen, Splash screen ของ Application (ซึ่งผิดหลัก HIG ของ Apple ทุกอย่าง) ซึ่งหมายความว่า ผมจะต้องใส่พวกนี้ซ้ำๆทุกครั้งที่มีการเริ่มโปรเจคใหม่ ซึ่งข้อเสียก็คือ 1) เสียเวลา 2) อาจจะลืมใส่หรือลืม Config ค่าบางอย่าง ซึ่งถ้าไอพวกที่ต้องใส่นี้ถูกใส่ไปตั้งแต่สร้างโปรเจค ปัญหาและ defect เรื่องเดิมๆพวกนี้ก็จะหมดไป

นอกจากนั้นยังมีประโยชน์แบบอื่นๆ (อย่างเช่นเรื่องของการทำ Test Case ที่ผมจะเขียนใน Entry หลังๆ) อีกครับที่ได้จากการทำ Template

ดังนั้น สร้าง Template ไว้ใช้เองกันดีกว่า

เริ่มจาก สำหรับ Snow Leopard ไฟล์ Template ของ XCode จะถูกเก็บอยู่ที่ /Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode ภายใน Folder นี้ก็จะมี Template ต่างๆ ซึ่งที่เรากำลังจำทำเป็น Project Template ก็เข้าไปที่ Folder Project Templates/Application

จะพบ Template หลายแบบมากมาย การจะสร้าง Template ของเรา วิธีที่ง่ายที่สุดของเราก็คือ “Copy” Template แบบที่ใกล้เคียงของเรามากที่สุดครับ จากนั้น ตั้งชื่อ Folder ก็จะเป็นการตั้งชื่อ Template ของเราแล้ว ตอนนี้ ถ้าลอง Create New Project ใน XCode ก็จะเจอ Template ของเราแล้วครับ

ให้เรา เปิดไฟล์ ___PROJECTNAME___.xcodeproj และแก้ไข Template ตามที่ต้องการครับ จะแอด Library, Framework, Config compiler ยังไงก็ตามต้องการเลย ส่วนตรงไหนที่ต้องการให้ Dynamic ตามชื่อของโปรเจคที่ถูกสร้างก็ใส่ prefix ชื่อ ___PROJECTNAME___ เข้าไปครับ

เท่านี้ก็เสร็จแล้ว หลังจากนี้ เราก็สามารถสร้าง Project ด้วย Template ของคุณเองได้แล้ว ง่ายมากเลยใช่มั้ยครับ แต่ถ้ายังไม่ทำให้คุณรู้สึกเป็นเจ้าของของมัน (เพราะแค่ Copy มาแล้วแก้เอา) คุณก็สามารถระบุ Description และเปลี่ยน Icon Image ได้ด้วย

วิธีการก็คือ ให้คลิกขวาที่ ___PROJECTNAME___.xcodeproj แล้วเลือก Show Package Contents คราวนี้ละครับ ถ้าต้องการเปลี่ยน Description ของ Template ของเรายังไง ก็เปลี่ยนในไฟล์ TemplateInfo.plist ได้เลย

ส่วนรูปภาพ ก็ให้ใช้โปรแกรม Icon Composer (อยู่ที่ /Developer/Applications/Utilities) สร้างไฟล์ icns ขึ้นมา วิธีการใช้โปรแกรมนี้ก็ง่ายมาก แค่เอารูปภาพที่มีขนาด 512×512 ใส่ลงไปในช่อง 512 หรือถ้ามีขนาดเล็กกว่านั้นก็ใส่ช่องเล็กกว่านั้นหรือใส่ช่องใหญ่ไปด้วยก็ได้ จากนั้นก็ Save as.. ที่ path ที่ต้องการ ซึ่งสำหรับ template ก็ตั้งชื่อเป็น “TemplateIcon.icns” ด้วย จากนั้นก็เอาไปใส่แทนรูป Logo template ที่เราต้องการจะเปลี่ยน แค่นี้ก็เรียบร้อยครับ

เป็นไงครับ ง่ายๆแต่ได้ผล แค่นี้เราก็มี Template ไว้ใช้เองแล้ว สำหรับ Entry นี้ก็ขอจบไว้แค่นี้ Happy coding with your template ครับ ;)

มกราคม 26, 2010 at 2:21 pm 2 ของความคิดเห็น

ดูหนังบนไฟล์ .nrg Disk Image

เคยไหม กับการดาวน์โหลดหนังมาอย่างยาวนาน แต่ไฟล์ที่ได้กลับเป็นไฟล์ Image ซะอย่างงั้น ไฟล์ Image ที่ว่าหมายถึงไฟล์ที่ใช้สำหรับโปรแกรมไรท์แผ่นนะครับ ไม่ใช่ไฟล์รูปภาพ ถ้าเราไม่มีแผ่นเปล่าหล่ะ หรือไม่อยากไรท์หล่ะ หรือใช้ OS อื่นที่เปิด Format นั่นมันไม่มีโปรแกรมเปิดหล่ะ หรือเรายังอยากจะปล่อยไฟล์นั้นไว้สำหรับ Seed ใน Bittorent หล่ะ เหตุผลร้อยแปดที่เราอยากจะดูหนังจาก Disk Image ซะให้ได้

ไฟล์ Disk Image จะมีอยู่หลายนามสกุลครับ แต่ที่เจอบ่อยจะเป็น .iso, .nrg หรือนามสกุลอื่นๆ (นึกไม่ออกแล้ว) วิธีการมีง่ายๆครับ ถ้าใช้งานบนวินโดวส์ ก็ใช้โปรแกรม Daemon Tool สร้างไดรฟ์ CD จำลองแล้วแล้ว Mount ข้อมูลจาก File disk image ก็เป็นอันโอเคแล้ว

แต่ผมดันใช้แมคน่ะซิครับ แต่ไม่เป็นปัญหา ผมมีวิธีง่ายกว่านั้นอีก คือ ถ้าไฟล์ฟอร์แมตเป็น .nrg ก็ใช้วิธีการ เปลี่ยนนามสกุลมันซะ ให้เป็น .iso จากนั้นเปิดด้วยโปรแกรม VLC ทั้งแบบที่เป็น .iso นั้นซะเลย VLC ก็สามารถหาโหลดได้ฟรีครับ บนวินโดวส์หรือ Linux ก็คิดว่าทำได้เช่นเดียวกัน เพราะ VLC มีทั้ง 3 Platform ครับ

* Update : ไม่ต้องแปลงนามสกุลก็ได้ เปิดทั้งเป็น .nrg เลยก็ได้ วู้ว สุโค่ย

พฤษภาคม 11, 2009 at 9:26 am 5 ของความคิดเห็น

iPhone Development – View, Drawing

สำหรับ Entry นี้อาจจะพูดถึงส่วนของ View ใน iPhone นะครับ ซึ่งอยู่ใน Lecture ที่ 5 ของ stanford course ซึ่งจะกล่าวถึงคลาส UIView ของ iPhone, การใช้เครื่องมือสำหรับการวาดอย่างง่ายครับ

ไม่แน่ใจว่ามันจะก้าวกระโดดไปนิดรึเปล่า เอาเป็นว่า Entry นี้ผมจะหลักเลี่ยงการโค้ดนะครับ เริ่มกันที่ View นะครับ

ส่วนที่เป็น View คือส่วนที่เป็นสี่เหลี่ยมผืนผ้าตรงหน้าจอนั่นแหละครับ ทั้งหมดเลย ซึ่งภายใน View จะมีการทำงาน 2 อย่างอยู่ด้วยกัน คือ ส่วนของ Content และ Event

Content ก็คือตัวอักษร, รูปภาพหรือสิ่งที่ถูกวาดขึ้นบนจอภาพนั่นเองครับ ใน View แต่ละหน้าจะมี View หลักตัวหนึ่ง(เทียบตาม Tree ก็เป็น Root) เราเรียกว่า Superview ครับ ภายใน Superview ก็จะมี View ย่อยๆ เรียกว่า Subview ถ้านึกไม่ออกว่าเป็นไง ก็ลองนึกถึงกระดานปักหมุด(Superview)ที่มีกระดาษ(subview)แปะอยู่แล้วกันครับ ส่วน Event คือเหตุการณ์ที่เกิดขึ้นบนหน้าจอนั่นเองครับ ไม่ว่าจะเป็นการ Tab, การ Scroll ฯลฯ ทั้งหมดที่จะสั่งการให้ iPhone ทำงานได้ ถือเป็น Event หมด

เนื่องจาก View เป็นการวาดรูปภาพขึ้นมาบนส่วนของ Content ดังนั้นโครงสร้างต่างๆที่เกี่ยวข้องกับ View ก็เป็นเกี่ยวกับการวาดเช่นกัน ได้แก่ CGPoint หมายถึง ตำแหน่งที่อยู่(x,y) ,CGSize หมายถึง ขนาด(Width, Height) และ CGRect หมายถึงกรอบ(CGPoint, CGSize) ลักษณะ Coordinate ของ iPhone จะไม่เหมือนกับพิกัดการวาดรูปทั่วๆไปครับ จุด origin จะอยู่ที่มุมซ้ายบน (จากปกติมักจะอยู่ซ้ายล่าง)

เกี่ยวกับการวาดนั้น การอ้างอิงพิกัดหรือพ้ืนที่สำหรับวาด จะมีอยู่ 2 แบบ คืออ้างอิงจาก Frame และอ้างอิงจาก Bound ทั้งสองแบบแตกต่างกันตรงที่ “มันเป็นตำแหน่งเมื่อเทียบกับขอบกระดานปักหมุกหรือเทียบกับขอบกระดาษที่แปะ” ถ้า Frame คือเมื่อเทียบกับขอบกระดานปักหมุด แต่ถ้า Bound ก็เทียบกับกระดาษบนกระดานปักหมุด ถ้ายังไม่เข้าใจลองดูที่สไลด์ที่ 19 ก็อธิบายได้ชัดเจนดีครับ มีคำแนะนำอยู่นิดหน่อย (อยู่ในสไลด์ที่ 20) เกี่ยวกับการใช้งาน Frame และ Bound

สิ่งที่อยู่เหนือกว่า Superview คือ Window แต่ละ App จะมี 1 Window และ Window มักจะถูกจัดการมาให้เราใน template เรียบร้อยแล้ว

ส่วนเรื่องของการโค้ด มีตัวอย่างอยู่ใน สไลด์ที่ 25-27 นะครับ ไม่ขอเอามาเขียนซ้ำนะครับ แล้วก็คิดว่าโค้ดไม่น่าจะยากอะไรด้วย แต่ถ้าสงสัยก็โพสถามเอาละกันนะครับ

ต่อไปเรื่องของการ Drawing ครับ

การ Drawing ลงไปบน Content View นั่น จะทำโดยการ override คำสั่งการวาดไปในฟังก์ชั่น Drawrect ครับ แต่การสั่งให้ Draw จะไม่ได้ใช้วิธีการเรียกฟังก์ชั่น Drawrect ครับ แต่จะใช้คำสั่ง setNeedDisplay แทน งงมั้ยครับ? ลักษณะนี้เรียกว่า “Lazy Loading” ครับ view ของเราจะไม่ถูกวาดอยู่ตลอดเวลา แต่วาด(ตามที่สั่งใน drawRect)แค่เฉพาะตอนที่สั่ง(ว่า setNeedDisplay)เท่านั้น

เครื่องมือเกี่ยวกับการวาด จะเป็น Core Graphics และ Quartz 2D ทั้งสองตัวที่กล่าวถึงเป็น Graphic Library บน Cocoa ครับ ใช้โดย Library นี้เป็น C-Base API นะครับ ไม่ใช่ Objective-C ส่วนวิธีการวาดอย่างละเอียดนั้น คงไม่ขอพูดถึงในที่นี้ เพราะจะยาวจนเกินไปครับ(รวมทั้งอยากหลีกเลี่ยงการ Coding ใน Entry นี้ไปก่อนด้วย) คงจะมาอัพเดตในคราวหน้า แต่ถ้าสนใจก็ดูในสไลด์ก่อนก็ได้ครับ ใน Entry นี้ไว้เท่านี้ก่อนครับ

มีนาคม 23, 2009 at 2:03 am ใส่ความเห็น

Objective – C Custom Class

ก่อนอื่นขอบอกก่อนนะครับ ว่าหลังจากนี้ ผมจะอิงเนื้อหาจาก CS193P ของ Stanford มาเขียนเป็นบทๆ (เพราะถ้าตั้งหัวข้อเขียนเอง ท่าทางจะงง และจะไม่ครบถ้วน) ถ้าอยากดูสไลด์ประกอบก็ตามในเวบของ CS193P เลยนะครับ

จากก่อนหน้านี้ ผมอธิบายคร่าวๆเกี่ยวกับสิ่งต่างๆที่ต้องรู้ และในหัวข้อ Objective-C ก็อธิบายไว้คร่าวๆเหมือนกัน Entry นี้จะมาเจาะลึกกันซักหน่อย โดยจะเริ่มกันที่เรื่องของ Custom Class ของ Objective-C

ในการสร้าง Custom Class ใน Objective-C ไฟล์ที่ได้จากการสร้าง New Class จะมี 2 ไฟล์ คือไฟล์ .h และ .m
– ไฟล์ .h จะเป็น Header ไฟล์ ที่กำหนดลักษณะทั้งหมดของคลาส ว่า Class Name ชื่ออะไร มี Attribute และ Method อะไรบ้าง นอกจากนั้นยังเป็นส่วนที่กำหนดการเชื่อมต่อกับ Interface Builder ด้วย ลักษณะก็จะเป็นแบบนี้

#import <Foundation/Foundation.h>  // import เหมือนกับคำสั่ง include ของ C/C++

@interface ClassName : NSObject {
// Attribute ของ Class : เขียนเหมือนภาษา C ครับ
// Syntax: datatype varName
id  attr1;
NSString *attr2;

}
// Methods Header : คล้ายๆกับภาษา C เหมือนกันครับ ต่างกันนิดหน่อย
// Syntax: -/+ (returnDatatype)MethodName:(ParameterDatatype)parameterName;
– (void)setAttr2:(NSString *)aValue;
– (Nsstring *)attr2;

@end

– ไฟล์ .m เป็นส่วนของการ Implement Method ของคลาสทั้งหมด ลักษณะก็ประมาณนี้

#import “headerFile.h”

@implementation ClassName

– (void)setAttr2:(NSString *)aValue {
attr2 = aValue;
}

– (NSString *)attr2 {
return attr2;
}

@end

ครับ จากตัวอย่างเป็นการสร้าง Class ที่มี Method Getter กับ Setter นะครับ ต่อไปก็จะเป็นการสร้าง Object, Memory Management และการ ลบ Object นะครับ เริ่มต้นที่การสร้าง Object

การสร้าง Object มีสองขั้นตอนคือ การจองพื้นที่ และ การกำหนดค่าตั้งต้นของ Object ซึ่งรูปแบบมีดังนี้

ObjectClass *ObjectName = [[ObjectClass alloc] init];

การกำหนดค่าตั้งต้นอาจจะมี Parameter อื่นๆได้ด้วย ในกรณีตัวอย่างหมายถึง Default การกำหนดนี้ จะเกี่ยวข้องกับ Memory Management ตรงที่ Object ที่ถูกประกาศ จะมี retain count เป็น 1 หมายความว่า ตราบใดก็ตามที่ Object ตัวนี้ยังมีค่า retain count เป็น 1 หมายความว่า object ตัวนี้จะยังคงอยู่ในหน่วยความจำไปเรื่อยๆ ถ้าเราต้องการลบ Object ตัวนี้เราก็ทำได้โดยการใช้คำสั่ง Release แบบนี้ครับ

[ObjectName release];

ซึ่งจากข้างต้น ให้พูดง่ายๆก็คือ malloc กับ free ในภาษา C นั่นแหละครับ

แล้วก็อย่างที่บอกก่อนหน้านี้ครับ หลังจาก Mac OS X ออกมาเป็นเวอร์ชั่น 10.5 Leopard สิ่งที่คลานตามออกมาด้วยกัน คือ Objective-C 2.0 หลักๆก็มีสามอย่างอย่างที่เคยบอกนะครับ แต่Entry นี้จะเน้นเรื่อง Property แค่เรื่องเดียว เพราะเป็นเรื่องสำคัญใน iPhone Development เลยทีเดียว

Property เป็นสิ่งที่เข้ามาช่วยกำหนดคุณลักษณะของ Attribute ของ Class ของเราครับ ว่ามันอยู่ในหน่วยความจำอย่างไร Access ค่าแบบไหน ถามว่ามันจะรู้ไปทำไมว่าอยู่ในหน่วยความจำอย่างไร (retain, assign, copy) ก็เพราะฟีเจอร์เกี่ยวกับ Garbage Collector ส่วนเรื่อง Access ค่าอย่างไร (readwrite, readonly) ก็เป็นเรื่องที่เกี่ยวกับการใช้งานฟีเจอร์สร้าง Method Getter/Setter อัตโนมัติของ Property เอง (มันจะสร้างแบบไหนก็เกี่ยวกับมันอยู่ในหน่วยความจำอย่างไรเช่นกัน)

ส่วนว่าแต่ละอย่างมันหมายความว่ายังไงบ้าง ก็หมายความอย่างนี้ครับ

retain – Attribute นั้นถูกประกาศขึ้นโดย retain Count เป็น 1 Value เป็น default

assign – Attribute นั้นเป็น Pointer ชี้ไปที่ Attribute อื่นอีกทีนึง

copy – Attribute นั้น Access ค่าโดยการ Copy ค่ามาจากที่อื่น แต่ไม่ได้เพิ่ม retain count ขึ้นมาด้วย

readonly, readwrite – เป็นตัวกำหนดการ Access Attribute ว่าให้อ่านอย่างเดียวหรือเขียนได้ด้วย

ซึ่งตัวอย่างการใช้งานก็จะเปลี่ยนจากตัวอย่างด้านบนมาเป็นลักษณะนี้ครับ

ไฟล์ Header

#import <Foundation/Foundation.h>

@interface ClassName : NSObject {
id  attr1;
NSString *attr2;
}
@property id attr1;
@property Nsstring *attr2;

@end

ไฟล์ Implement

#import “headerFile.h”

@implementation ClassName

@synthesis attr1;
@synthesis attr2;

@end

จะเห็นว่า Method Getter/Setter หายไปและแทนที่ด้วยการกำหนด property แทน และในส่วนของ implement ก็แค่ใช้คำสั่ง @synthesis <#attribute> เพื่อให้มันสร้าง Method Getter และ Setter ขึ้นมา สั้นและง่ายขึ้นเยอะเลยใช่มั้ยครับ

ส่วนเรื่องการใช้งาน จะใช้ dot syntax เข้ามาแทนการเข้าถึง attribute ที่กำหนด property ครับ ลักษณะก็เป็นแบบนี้ (ใช้ class จากตัวอย่างข้างต้น)

objectExample.attr2 = @”test String”;  // อันนี้เป็นกรณี Setter method

NSLog(@”%@”, objectExample.attr2);  // อันนี้เป็นกรณีของ Getter method

ไม่ยากเกินไปใช่มั้ยครับ เกี่ยวกับเรื่องของ Custom Class ใน Objective-C สำหรับเนื้อหา Entry นี้อ้างอิง CS193P : Chapter 3 Custom Class นะครับ อยากดูสไลด์ก็ไปดูได้ (แต่ผมไม่ได้ทำหรอกนะ) เข้าใจไม่เข้าใจยังไงก็ติชมได้ครับ สำหรับบทนี้ขอจบเท่านี้ครับ

มีนาคม 6, 2009 at 10:04 am 2 ของความคิดเห็น

Older Posts


del.icio.us For iPhone dev

Post Calendar

กันยายน 2019
พฤ อา
« ธ.ค.    
 1
2345678
9101112131415
16171819202122
23242526272829
30