1-bQCSLKNrW3ROh34pl2_Jww
เนื่องจากมีโอกาสได้แบ่งปันเรื่อง MVP pattern ให้ทีมนิดหน่อย (แบบไม่ตั้งใจ)
ซึ่งมีเรื่องหนึ่งที่ติดค้างไว้ก็คือ
การ Inject Object จาก Storyboard ไปเลย
จะได้ไม่ต้องมาสร้าง object ขึ้นมาใน ViewController เอง
ทำให้การเขียน code ง่าย และ สะดวกขึ้น

จากตัวอย่าง code ในวันนี้อยู่ที่ Github

ซึ่งไปดูในไฟล์ ViewController.swift จะพบว่า
function sort() ทำการสร้าง object จาก class SortController ขึ้นมา
ดังนี้

คำอธิบาย
class SortController นั้นคือ Presenter หรือตัวแทนการทำงาน
หรือเป็นส่วน business logic ของระบบนั่นเอง
ซึ่งจากตัวอย่างจะทำการเรียงลำดับข้อมูลตัวอักษร
ดังนั้นเราจึงพยายามแยกการทำงานออกมาจาก ViewController

จากการสร้าง object ของ SortController นี่เอง

จึงมีคำถามว่า ถ้าเราไม่อยากมาสร้าง object แบบนี้ล่ะ
เนื่องจากไม่ต้องการให้ code ผูกมัดจนเกินไป (Tight coupling)
มันมีวิธีอื่น ๆ อีกไหม ?
ซึ่งตอบได้เลยว่ามีหลายวิธีมากเช่น

  • เขียนเอง
  • ใช้ library เกี่ยวกับ dependency injection

รวมทั้งวิธีที่ผมใช้คือ Inject ผ่าน Storyboard กันไปเลย
แต่ต้องแก้ไข code นิดหน่อย
มาเริ่มกันเลย

ขั้นแรกแก้ไขไฟล์ SortController.swift ให้ extends มาจาก NSObject ก่อน

ขั้นที่สองทำการแก้ไขไฟล์ ViewController.swift
ให้ทำการเพิ่มตัวแปรชนิด SortController เข้ามาดังนี้

ขั้นที่สามสร้าง Object ขึ้นมา และ เพิ่มเข้ามายัง Storyboard
ทำการเลือกชื่อ class เป็น SortController ซะ
แสดงดังรูป

xcode-01

ขั้นตอนที่สี่ทำการเชื่อมโยงระหว่าง object ใน Storyboard กับตัวแปรใน ViewController
แสดงดังรูป

xcode-02

ขั้นตอนที่ห้าถ้า run ระบบจะพังตอนเปิดขึ้นมา
เนื่องจากจะทำการสร้าง object ของ SortController ขึ้นมา
ด้วยการเรียกผ่าน init() ซึ่งใน code ไม่มี
ดังนั้นจำเป็นต้องสร้างขึ้นมา หรือลบ init() ที่เราไม่ออกไป
ซึ่งผมเลือกการลบทิ้งไป

ผลที่ตามมาจากการลบไปนั้น
พบว่าระบบสามารถ run ขึ้นมาได้ แต่ไม่สามารถใช้งานได้
เนื่องจากเกิด error ดังนี้

fatal error: unexpectedly found nil while unwrapping an Optional value

ขั้นตอนที่หกทำการแก้ไขด้วยการแก้ไข code
เปลี่ยนจากการ Injection แบบเดิมคือ Constructor Injection
มาเป็น Property หรือ Setter Injection ซะ
ซึ่งเป็นการ injection ที่นิยมใน framework ต่าง ๆ
ดังนั้นจึงทำการแก้ไขดังนี้

แต่ยังไม่จบนะ !!
ลอง Run Test ของระบบนี้สิ
แล้วจะพบว่าตายเรียบ
เนื่องจากเราเปลี่ยนวิธีการพัฒนานั่นเอง
ดังนั้นจงแก้ไขซะดี ๆ

ขั้นตอนที่เจ็ดแก้ไข test ทั้งหมด และ ปรับชื่อให้อ่านง่ายขึ้น
รวมทั้งอย่างลืมเรื่อง SwiftLint ด้วยว่าต้องมีค่าเป็น 0 นะ
นั่นคือไม่มี warning ใด ๆ เลย

เพียงเท่านี้ก็สามารถแก้ไขและปรับมาใช้การ Inject Object
ผ่านทาง Storyboard ได้แล้ว
สามารถดู code จากการแก้ไขได้ที่ Github::Up1