วันพฤหัสบดีที่ 7 พฤษภาคม พ.ศ. 2558

หัดเขียน Swift ตอนที่ 5 - Array



Collection พื้นฐานในภาษา Swift ที่จะพูดถึงในวันนี้ ก็คือ Array และ Dictionary ครับ มาเริ่มกันเลย!


Array

สำหรับอาเรย์ในภาษา Swift สามารถประกาศและเรียกใช้ได้ โดยมีวิธีดังตัวอย่างต่อไปนี้



จากภาพตัวอย่าง เรา กำหนด ค่า  [1,2,3,4,5]  ซึ่งเป็นข้อมูลที่มีรูปแบบโครงสร้างของอาเรย์ในภาษา Swift ดังนั้น ตัวแปรที่ชื่อ array จึงเป็นอาเรย์ ที่เก็บข้อมูลตัวเลข 1 ถึง 5 ตามลำดับ (ลำดับมีความสำคัญ)

หรือเราจะกำหนดชนิดของข้อมูลที่ต้องการเก็บลงอาเรย์ไว้ตอนประกาศเลยก็ได้ ดังนี้


          จากภาพตัวอย่าง จะเห็นว่าเราสามารถกำหนดให้อาเรย์ เก็บได้เฉพาะข้อมูลที่เป็น Interge เท่านั้น 

ดังนั้น พอผมทำการเพิ่มข้อมูลชนิด String ลงไปในอาเรย์ด้วยเมดตอด append() จึงเกิด Error ขึ้นครับ

แถม :


        จากภาพเป็นการเพิ่มข้อมูลตัวเลขลงในอาเรย์ทีละหลายๆตัวในคำสั่งเดียว โดยใช้เมดตอดชื่อ extend()



ทั้งหมดนี่ก็เป็นการใช้ Array อย่างง่ายๆนะครับ ยังมีmethod อีกหลายตัวที่ผมไม่ได้ใช้ให้ดู และถ้าถามว่า อาเรย์ในภาษา Swift นั้น  มีวิธีที่สามารถเก็บค่าแบบหลายๆชนิด ในอาเรย์ชุดเดียวกันได้ไหม ตอบว่า ได้นะครับ แต่ไว้ผมจะพูดถึงทีหลังครับ :3  ในบทความต่อไป เราจะไปต่อกันเรื่อง Dictionary นะครับ





วันพุธที่ 6 พฤษภาคม พ.ศ. 2558

หัดเขียน Swift ตอนที่ 4 - Optionals , Forced Unwrapping , Implicit Unwrapping



นบทความที่ผ่านๆมา เราได้ก็รู้พื้นฐานต่างๆของ Swift ไปบ้างแล้ว ได้แก่ ตัวแปร , ค่าคงที่ , ชนิดตัวแปร , สตริง และพวก control flow ต่างๆ (loop , if else , switch case) ดังนั้น ในบทความนี้ ผมจะเขียนถึงพื้นฐานที่ Advance ขึ้น ( อย่าเพิ่ง งง คำว่า พื้นฐานแบบ Advance 5555+ คือผมจะบอกว่า มันคือพื้นฐานของเจ้าภาษานี้ แต่ภาษาอื่นผมยังไม่เคยเห็นเค้าใช้กัน ) ซึ่งก็คือ Optionals , Forced unwrapping และ Implicit Unwrapping 

nil , Null หรือ NULL คำนี้ทุกคนคงรู้จักกันอยู่แล้ว แต่บางคนไม่รู้จักอันตรายของมัน คนที่เขียนโปรแกรมไม่รอบครอบ(อย่างผม) ก็มักจะโดนเจ้าค่า nil นี้ทำงานของผม บุ้ง! กลายเป็นโกโก้ครั้นไปหลายครั้งแล้วครับ เช่น API ภายนอกที่โปรแกรมของผมใช้งานอยู่ เกิดล่ม หรือมีการปรับเปลี่ยน ทำให้โปรแกรมผมได้ค่า nil เอาไปใช้ แล้วไม่ได้มีการดักเรื่องเหตุการณ์นี้เอาไว้ โปรแกรมผมก็เลยแครช!   (ดีนะยังไม่ตกงาน) ดังนั้นในภาษา Swift นี้ เค้าจะให้ความสำคัญกับเรื่องนี้มากๆ หากไม่มีความจำเป็นจริงๆ ก็ไม่ควรมีค่า nil เก็บอยู่ในตัวแปรเลยหล่ะครับ 0_0    งั้นเอาเป็นว่า เรามาเริ่มกันเลยดีกว่าครับ



จากภาพ ผมลองประกาศตัวแปร str เป็น String ซึ่งให้เก็บค่า nil ผลที่ได้ก็คือ Error ครับ เพราะใน Swift นั้น String ต้องเก็บ String value ครับ ส่วน nil มันไม่ใช่ String


แล้วถ้าผมอยากเก็บ nil จริงๆ ล่ะ เพราะบางทีเราไม่รู้ค่าในตอนเริ่มต้น แต่อยากประกาศมันไว้ก่อน ซึ่งก็ทำได้ครับ แต่คุณจะต้องใช้ ”Optional”  ซึ่งหมายถึง จะมีค่าอยู่ หรือไม่มีค่าอยู่ ก็ได้ (“have a value” or “may have a value”)  ซึ่งในภาษาอื่นๆ เรามักจะใช้ค่า -1 หรือ 0 เพื่อบอกว่า ไม่มีค่าเก็บอยู่ 



วิธีการใช้ Optionals

แบบง่ายสุดเลย คือเพิ่มเครื่องหมายคำถาม “?” ไว้ที่หลังชนิดตัวแปร เช่น




จากภาพตัวอย่าง จะเห็นว่า  str ตัวแรกที่ไม่ได้ประกาศเป็น Optional และไม่มีการกำหนดค่าเริ่มต้นให้ จะมี Error เกิดขึ้น แต่กับ str2 ดันไม่มี Error และยังสามารถเก็บค่า nil ได้ด้วย เพราะว่า str2 ประกาศเพิ่มไว้ว่าเป็น Optional นั่นเอง



จากตัวอย่าง เราประกาศ Optional ให้ str ไว้ ซึ่งพอ str เรียกใช้ method ชื่อ uppercaseString ดันเกิด Error ขึ้นดังภาพ ทั้งที่ปกติตอนไม่ได้ประกาศOptional ก็ใช้ได้นี่หว่า สาเหตุที่เป็นเช่นนี้ ก็เพราะว่า String กับ String? ถือเป็นคนละตัวกันจึงใช้ต่างกัน (String? สามารถเก็บได้ทั้ง String และ nil) ซึ่งตัว String? ไม่มี Method ชื่อ uppercaseString เหมือน String ครับ   ส่วนสาเหตุนั้นผมคิดว่า สมมุติว่าถ้า String? เก็บค่า nil อยู่ แล้วเราไปเรียกใช้ method  uppercaseString (แปลงเป็นตัวอักษรพิมพ์ใหญ่) มันก็จะมีปัญหาน่ะสิครับ เพราะแปลง nil เป็นอักษรพิมพ์ใหญ่ไม่ได้!   ซึ่งถือเป็นข้อดีที่ทำให้โปรแกรมของเรามีประสิทธิภาพกว่าเดิม ลดจำนวน Bug ที่อาจจะเกิดขึ้นได้ในอนาคต :)

จาก Error ดังกล่าว ถ้าเราอยากแปลงเป็นตัวพิมพ์ใหญ่ล่ะ ทำยังไง?  ไม่ยากครับ เราแค่ทำการตรวจสอบค่าก่อนใช้งาน ดังนี้


จากภาพ เรา assign ค่าของ str ไปไว้ที่ตัวแปร unwrappedStr ก่อน ซึ่งหากค่าที่ได้ ไม่ใช่ค่า nil (เป็น String Value) เงื่อนไข if ก็จะเป็นจริง จากนั้นค่อยเรียกใช้method uppercaseString ครับ  แต่ถ้า เป็น nil ก็จะไปเข้า Else แทนครับ ซึ่งเราจะไม่ยอมให้เรียกใช้ method uppercaseString โดยเด็ดขาด (เสี่ยงต่อการแครชมาก)  ดังนั้น นี่จึงเป็นวิธีที่เราควรใช้!  


Forced unwrapping

ส่วนอีกวิธีหนึ่งที่สามารถทำให้ Optional สามารถเรียกใช้ method ของ String ได้ โดยไม่ต้องตรวจสอบ if - else ก่อนเหมือนข้างบน คือ ใช้ Forced unwrapping ครับ คำว่า Forced ก็เหมือนกับการบังคับให้ทำไม่ว่ายังไงก็ตาม คล้ายกับ Force Close หรือบังคับปิดโปรแกรมแบบ ใช้ Ctrl+Alt+Delete แบบนั้นเลย ซึ่งถ้าเรามั่นใจว่าจะไม่เกิดปัญหาภายหลัง ก็ใช้ได้ครับ แต่ถ้าไม่ ก็อย่าใช้ไปเด็ดขาด! ดังนั้น Forced unwrapping จะใช้เมื่อตัวแปรนั้นมีค่าเก็บอยู่ 100% ถ้าเป็น nil จะ Error ครับ ดังนั้นเมื่อแน่ใจว่าจะมีค่าเก็บอยู่แน่ๆแล้ว มันก็เลยยอมให้เราเรียกใช้ Method uppercaseString ได้

วิธีการใช้ Force Unwrapping ก็เพียงแค่เติมเครื่องหมายตกใจ “ ! ” ต่อท้ายชื่อตัวแปร ครับ ดังนี้



 จากภาพ เรามั่นใจว่า ถึง str จะประกาศเป็น Optional แต่ไม่ได้เก็บค่า nil แน่นอน เพราะเรากำหนดค่า String ไว้แล้ว จึงสามารถบังคับให้ใช้ method uppercaseString ได้ (ปกติ Optional เรียกใช้ method นี้ไม่ได้)


Implicitly Unwrapped Optional

ทวนเรื่องเก่าสักนิดนะครับ 
Optional เป็นการอนุญาติให้ตัวแปรที่เราสร้างสามารถเป็น nil ได้ ซึ่งก่อนใช้งานตัวแปร เราสามารถใช้ if ตรวจสอบว่ามีค่าว่างก่อนใช่งาน หรือถ้าเรามั่นใจว่าไม่เป็นค่า nil แน่ๆ เราก็ใช้ Forced unwrapping (“!”) ได้เลย

แต่ในบางครั้ง เรามั่นใจเสมอว่า Optional ที่เราสร้างขึ้น หลังจากที่เราได้ค่าออกมาใช้งานในครั้งแรกแล้ว ตัวแปรนี้จะไม่เป็นค่า nil อีกต่อไป เราก็สามารถกำหนดได้ว่า ตัวแปรนี้ จะไม่มีวันเป็นค่า nil ตลอดไป ซึ่งจะเป็น optional ที่มีค่าเก็บอยู่ 100% โดยปกติเราจะใช้เครื่องหมาย ! ตอนเรียกใช้งานตัวแปรทุกครั้ง ซึ่งบางทีมันก็เสียเวลาใช่ไหมครับ ทั้งที่เรามั่นใจว่า ไม่ใช่ค่า nil แน่ๆ แต่ต้องมาใส่ “!” ทุกครั้งเลย   เพราะเหตุนี้จะมีวิธีให้เรายกเลิกการใช้เครื่องหมาย ! ทั้งหมดได้โดยง่าย ซึ่งจะถูกเรียกว่า Implicitly Unwrapped Optional
โดยที่ตอนที่สร้าง optional เราจะไม่ใช้เครื่องหมาย ? เพื่อสร้าง optional แต่เราจะใช้ ! ตั้งแต่ตอนสร้างเลย ยกตัวอย่างเช่น



เพื่อให้เห็นตัวอย่างชัดเจน มาดูเปรียบเทียบแบบใช้ Implicitly Unwrapped Optional กับแบบไม่ได้ใช้กันดีกว่า ดังนี้





สำหรับบทความนี้ จบเพียงเท่านี้นะครับ ขอให้ผู้อ่านพยายามอ่านเรื่องนี้ให้เข้าใจ เพราะจะต้องเจอต้องใช้มันบ่อยมาก ซึ่งตอนผมเห็นพวกนี้ครั้งแรก ผมก็งงเป็นไก่ตาแตกเหมือนกันครับ Xcode มันบอกให้ผมเติมเครื่องหมายพวกนี้ ผมก็เติมตามที่มันบอก โดยไม่รู้ว่ามันคืออะไร 555+ ไว้เจอกันใหม่ในบทต่อไป เรื่อง Array นะครับ ^_^