July 31, 2015

อีกทางสวยๆ ? ในการกำหนด Style ให้กับ IBOutlet

การเขียนโค้ดกำหนดสี, ฟอนต์, หรือ Accessibility เป็นอะไรที่ค่อนข้างเหนื่อยหน่ายสำหรับหลายๆ คน ซึ่งปกติแล้วเราคาดหวังว่ามันควรถูกกำหนดค่าทุกอย่างได้ผ่าน Storyboard สิ

แต่ในหลายๆ ครั้งเราก็จำเป็นต้องเขียนโค้ดเพื่อกำหนดค่าเริ่มต้นต่างๆ ให้กับ IBOutlets เอง ซึ่งก็มักเข้าไปเขียนทิ้งไว้ใน ViewDidLoad ซึ่งบางทีโค้ดก็ยาวมาก และบางทีเราก็สร้าง method สำหรับกำหนดค่าต่างๆ ให้กับ IBOutlet อีกที แบบนี้


แต่ก็มีอีกทางหนึ่งที่เราสามารถทำได้ คือไปกำหนดไว้ใน didSet เลยแบบนี้

July 19, 2015

Automatic UI Testing ด้วย Xcode 7

Xcode 7 มาพร้อมกับ Automatic UI Testing ที่จะช่วยให้เราสามารถทดสอบ UI ได้ง่ายมากขึ้นกว่าวิธีเดิมๆ มาก ซึ่งจุดเด่นของ Automatic UI Testing ที่มาพร้อมกับ Xcode 7 ก็คือ
  1. ไม่จำเป็นต้องเขียน script ทดสอบเองทั้งหมด เพราะมีระบบบันทึก (UI Recording) การใช้งาน และสร้างโค้ดออกมาให้เราเองอัตโนมัติ สิ่งที่เราต้องทำเพิ่มก็คือ เขียนและออกแบบเงื่อนไข ต่างๆ ที่เราต้องการทดสอบ
  2. เข้าถึง UI Element ต่างๆ บนหน้าจอด้วยการอ้างถึง element นั้นๆ จริงๆ ไม่ใช่การกำหนดพิกัด หรืออ้างตำแหน่งของการแตะ หรือการ swipe ซึ่งการระบุพิกัดมีข้อเสียมากๆ ก็คือ หากแอปเราทำงานบนหน้าจอหลากหลายขนาด วิธีการนี้อาจใช้งานไม่ได้เลย ยิ่งถ้าแอปเรามีการเคลื่อนย้าย UI Element บนหน้าจอในขณะใช้งานด้วยแล้วล่ะก็ยิ่งแย่ไปใหญ่ ซึ่งการอ้างถึง UI Element ต่างๆ บนหน้าจอนั้น Xcode 7 จะใช้ความสามารถของ Accessibility ที่มีมาบน iOS ก่อนหน้านี้นานแล้ว (แต่นักพัฒนาหลายท่านไม่ค่อยใช้กัน -- รวมทั้งผมเองด้วย)
  3. รัน Test ไปพร้อมๆ กับ การรัน Unit Test ตามปกติ ไม่ต้องแยกแอปออกมาต่างหาก เหมือนกับการทำ UI Test แบบเดิมๆ ที่ต้องรัน Instrument ขึ้นมา ซึ่งวุ่นวาย และช้าอืดอาด ... ใช่แล้ว ตอนนี้ Automatic UI Testing ผนวกเข้าเป็นหนึ่งเดียวกับ Xcode 7 เลย!
  4. ใช้ XCTest Framework ที่คุ้นเคย

Search APIs ใน iOS9

แต่เดิมก่อนที่จะมี iOS 9 เราสามารถใช้ Spotlight ค้นหาได้เฉพาะแอป และข้อมูลบางอย่างที่ iOS อนุญาตเท่านั้น เช่น รายชื่อ โดยที่นักพัฒนาไม่สามารถควบคุมอะไรได้เลย แต่พอมาถึง iOS 9 Apple ได้เปิดโอกาสให้นักพัฒนาสามารถกำหนดได้ว่า เนื้อหาตรงไหนในแอปที่สามารถถูกค้นหาและถูกแสดงอยู่ในผลการค้นหาโดย Spotlight ได้บ้าง ซึ่งเครื่องมือที่ Apple เพิ่มเข้ามาช่วยงานนี้ก็คือ CoreSpotlight นั่นเอง

การทำให้ Spotlight รู้จักเนื้อหาที่ต้องการภายในแอปของเรา มี 3 ขั้นตอนดังนี้
  1. สร้าง CSSearchableItemAttributeSet เพื่อใช้เก็บเนื้อหาที่เราอยากให้ Spotlight แสดงในผลการค้นหา (เช่น title, description และภาพประกอบ)
  2. เก็บ CSSearchableItemAttributeSet ลงใน  CSSearchableItem
  3. ส่ง CSSearchableItem ให้ CSSearchableIndex ทำ index เพื่อให้ Spotlight หาเจอ
จาก 3 ขั้นตอนที่ว่ามา ก็จะได้หน้าตาโค้ดดังนี้

July 15, 2015

ทำความรู้จักกับ defer ใน Swift 2

คำสั่ง defer ถูกเพิ่มเข้ามาใน Swift 2 คำสั่งนี้ช่วยการันตีได้ว่าโค้ดที่อยู่ในบล็อคที่ประกาศโดยใช้ defer จะทำงานก่อนจบฟังก์ชัน, เม็ดธ็อด หรือ scope เสมอ

ดูตัวอย่างปัญหา


จากตัวอย่าง ฟังก์ชันจะเปิดไฟล์ จากนั้นตรวจสอบและเขียนข้อมูลโดยใช้ guard (ทำความรู้จักกับ guard ใน Swift 2) และบรรทัดสุดท้ายสั่งปิดไฟล์

แต่จะเกิดอะไรขึ้นหากสิ่งที่นำมาเขียนลงไฟล์มีปัญหา และทำให้ต้องจบฟังก์ชันก่อนสั่งปิดไฟล์ แน่นอนว่าไฟล์ไม่ถูกปิดและไฟล์ถูกเปิดทิ้งไว้อยู่อย่างนั้น

ทางแก้ของปัญหานี้ทำได้ 2 ทาง คือ เขียนคำสั่งปิดไฟล์ไว้ก่อน return ทุกๆ อัน และอีกทางหนึ่งคือทำ Pyramid of Doom ซึ่งทั้ง 2 ทางที่กล่าวถึง ล้วนไม่ใช่ทางออกที่ดีนัก แล้วทางออกไหนล่ะที่ดีกว่า?

July 13, 2015

ทำความรู้จักกับ guard ใน Swift 2

คำสั่ง guard เป็นของใหม่ที่ถูกเพิ่มเข้ามาใน Swift 2 และถูกเปิดตัวใน Apple's Platform State of the Union

จริงๆ แล้ว guard ก็คล้ายกับคำสั่ง if ที่ใช้ตัดสินใจว่าจะทำงานหรือไม่ทำงานโดยอิงกับ boolean ที่ส่งไปให้ตรวจสอบ แต่สิ่งที่ต่างกันชัดเจนก็คือโค้ดที่อยู่ในบล็อกคำสั่ง guard จะทำงานก็ต่อเมื่อค่าความจริงที่ทดสอบเป็นเท็จ ซึ่งวิธีตัดสินใจแบบนี้ก็จะคล้ายกับ assert นั่นเอง

เปรียบเทียบเทคนิคปกติที่ใช้กันอยู่


นี่คือท่าปกติที่หลายคนมักใช้ตรวจสอบว่าค่าที่ส่งเข้ามาในฟังก์ชั่นมีค่าตรงตามต้องการหรือไม่ หากไม่ใช่สิ่งที่ต้องการ ก็จบฟังก์ชัน ไม่ต้องทำอะไร แต่จริงๆ แล้วทำแบบนี้จะพบว่ามีจุดสังเกตอยู่ 2 จุด ได้แก่
  1. เรากำลังตรวจสอบโดยใช้เงื่อนไขของสิ่งที่เราไม่ต้องการ ไม่ได้ใช้เงื่อนไขของสิ่งที่เราต้องการมาตรวจสอบ (ส่วนใหญ่แล้วเรามักตรวจสอบกันแบบไหนเอ่ย?)
  2. หากต้องการใช้ตัวแปรที่ถูกตรวจสอบว่าใช้งานได้แล้ว เราจำเป็นต้องบังคับ unwrap optional value ก่อนจะนำมันไปใช้