Custom UI and Easy to customize

เมื่อเขียนโปรแกรม ios ไปเรื่อยๆสักระยะหนึ่ง สิ่งหนึ่งที่โปรแกรมเมอร์แบบเราๆ จะต้องเจอแน่ๆ นั่นก็คือ custom ui หรือการปรับแต่งหน้าตาของโปรแกรม ให้มันดู cool นั่นเอง .. ก็แน่นอนว่า วิธีที่ง่ายสุดในแต่งปรับแต่งนั่นก็คือ ให้คนอื่นทำให้เรา (แต่มันคงเป็นไปได้ยาก ใช่ม่ะ) อะๆๆ งั้นมาลองวิธีที่ง่ายกว่านั้น และนั่นก็คือ การไปใช้ ui control ของคนอื่นที่เค้าเขียนไว้แล้ว (แน่นอนละใครจะอยากไปเขียนเองให้เหนื่อย ถูกม่ะ) อย่างในเวป cocoacontrol.com ก็มีหลายอย่างให้เลือกใช้งาน

แต่ถ้ามันไม่มีละ ? (นั่นไง ซวยละ) .. สุดท้ายมันก็หนีไม่พ้นที่จะต้องเขียน custom control ถูกป่ะ ?

ผมเชื่อว่าหลายๆคน คงจะเคย custom ui กันมาแล้วแน่นอน อย่างเช่น UIButton หรือ UITableViewCell ใช่ม่ะ ถ้าใครยังไม่เคยก็คงต้องบอกว่าคุณยังไม่ใช่ iOS Dev ที่แท้จริง .. อันที่จริงการ ปรับแต่ง หรือสร้าง  control พวกนี้มันก็ไม่ใช่เรื่องยากอะไรเท่าไหร่ แต่ว่า พวก control ที่เราสร้างขึ้นมา มันมักจะปรับแต่งไม่ง่าย standard ui ที่มาพร้อมกับ XCode  เพราะว่า ui เหล่านั้น แค่ลากวาง แล้วก็กดเปลี่ยน property ใน inspector เป็นอันเสร็จพิธีเลยถูกต้องม่ะ

อย่างในรูปด้านล่างนี่ ถ้าอยากจะเปลี่ยนสีปุ่ม ก็แค่กดเปลี่ยนสีก็จบ ไม่ต้องเขียนโค้ดให้เหนื่อยเลย ให้ตายสิโรบิ้น

button

แต่ถ้าหากเป็น ui control ที่เราสร้างขึ้นมาเองละ ?

เช่น สมมติว่า เขียน control ที่เป็น ปุ่มแบบโค้งมน เราก็อาจจะเขียน control ได้ประมาณนี้

เมื่อนำไปใช้ใน Storyboard หลังจากลาก Button วางแล้ว ก็ต้องเปลี่ยนให้เป็นคลาสที่เราได้สร้างไว้

button

ถ้าให้โปรแกรมทำงาน  มันก็จะได้แบบนี้

round_button

ปัญหาก็คือว่า ถ้าเราอยากจะเปลี่ยนสีของ ขอบ ปรับขนาดของเส้นรอบๆ จะทำยังไง โดยที่ไม่ต้องไปแก้ไขโค้ด ?

เราสามารถที่จะทำให้มันมี property ปรับง่ายๆเหมือนอย่าง standard ได้ไหม ?

ผมบอกเลยว่า “ได้”

วิธีการนั้นไม่ยากเลย แค่ใช้ IBDesignable และ IBInspector เข้ามาช่วย

ซึ่งโค้ดที่ปรับใหม่ ก็จะมีลักษณะแบบนี้

เมื่อพิจารณาจากโค้ด เราได้บอกว่า คลาส RoundButton นั้นรองรับ Interface Builder และ มี inspector ทั้งหมด 3 ตัวที่สามารถปรับแต่งได้ นั่นก็คือ Border Color , Border Width และ Corner Radius

ซึ่งถ้าหากเราใช้คลาสที่สร้างขึ้นใหม่นี้ ก็จะเห็นว่า จากที่มันแสดงผลใน storyboard แบบไม่มีเส้นขอบโค้งๆ แต่ตอนนี้มันแสดงได้แล้ว

ok_button

และถ้าเข้าไปดูใน inspector ก็จะเห็นว่า มี property ใหม่เพิ่มขึ้นมา  3 อย่างด้วยกัน

prop

เป็นไง มันช่าง F**King DAMN Cool ไหมละ ?

คราวนี้อยากจะปรับอะไรก็ทำใน Storyboard ได้เลยทันที ไม่ต้องไปแก้ code ให้มันเสียเวลา

Review Dell U2414H

จริงๆแล้วใช้ Macbook Retina จอภาพมันก็สวยดีนะ แต่ว่าเมื่อทำงานไปได้สักพักใหญ่ๆ ผมก็รู้สึกว่า จอมันเล็กเขียนโค้ดแล้วมันอ่านไม่ค่อยมันส์เลย คือบางทีต้องกวดสายตา เลื่อนจอภาพลงมาเพื่อให้เห็นโค้ดทั้งหมด ยิ่งมีเวลาเขียน iOS มี Simulator ด้วยแล้ว ก็รู้สึกว่า มันเล็กไปหน่อย ถ้าได้จอมาต่อก็น่าจะดี

จอภาพมันก็มีหลายแบบมากมายในตลาด ทั้งเล็ก ใหญ่ ราคาแพง ถูก หลายยี่ห้อมากมาย ดังนั้น ก่อนจะไปเลือกซื้อ หรือหาอะไร ผมก็ตั้งหลักไว้ว่า

  • ต้องมี port HDMI หรือ Display , Mini Display เพื่อใช้ต่อกับ Macbook Retina
  • มีประกันให้อุ่นใจ
  • งบไม่เกิน 10,000 บาท
  • ขนาดไม่เล็ก ไม่ใหญ่ไป (สำหรับผม 27″ ใหญ่ไป  และจอ 20″ ก็เล็กไปสำหรับเขียนโค้ด )

อันที่จริงมันก็มีจอหลายรุ่นที่ตรงตามที่ผมอยากได้ แต่ก็มาลงเอยกับ Dell U2414H เพราะว่า

  • เคยใช้จอ Dell มาก่อน จากประสบการณ์คิดว่ามันโอเค
  • รุ่นนี้ประกัน 5 ปี ( ถ้าเลือกเอา 3 ปีก็ถูกกว่านิดหน่อย )
  • ผมซื้อในราคา 8 พันบาท แต่ไปรับของเอง (ถ้าสั่งซื้อในเวปออนไลน์ ก็ประมาณ 9 พัน ส่งฟรี)
  • Onsite service
  • Spec ต่างๆของจอ อยู่ในขั้นดี
  • มันมีช่องต่อ usb จากจอ

Open Box

_DSC0106

ตัวที่ผมได้มานี้คือ Dell UltraShape U2414H (Rev A03) คือจอภาพรุ่นนี้จะมี Rev 1 , 2 , 3 ถ้าจะซื้อก็ต้องดูด้วยนะครับว่าเป็น Rev ไหน เพราะ Rev 3 คือรุ่นใหม่สุด (ณ เวลาที่ผมเขียน)

_DSC0107

เมื่อดูข้างๆกล่อง ตรงที่ผมขีดสีแดงเอาไว้ มันบอกว่า รุ่นนี้ ประกัน 5 ปี (U2414H ปกติจะประกัน 3 ปี)  เอาละอย่ามัวเสียเวลากันเลย เริ่มแกะกล่องกันเลยดีกว่า

_DSC0109

หลังจากแกะกล่องออกมา ก็จะพบสายไฟที่ให้มา ประกอบไปด้วย

_DSC0113

  • สาย power
  • สาย usb
  • สาย display port

_DSC0133

_DSC0131

คือมันไม่แถมสาย HDMI มาให้แต่ให้ สาย Mini Display ไว้ต่อกับ Macbook ก็ถือว่าโอเค

ฐานตั้งที่ให้มาก็ดูแข็งแรงดี

_DSC0114

_DSC0115

หลังจากแกะห่อออกมาละ ด้านหลังของจอภาพก็ประมาณนี้

_DSC0116

รายละเอียดต่างๆของการผลิต ก็บอกไว้หลังจอ และที่ผมได้มา มันก็เขียนไว้ว่าผลิต มกราคม 2016  ในส่วนของ serial number ก็ตรงกับข้างกล่อง

_DSC0119

ด้านหน้าจอ ก็อย่างที่เห็น ขอบบาง

_DSC0124

ดูกันใกล้ๆ จะเห็นว่าในส่วนของการแสดงผลเกือบจะติดขอบเลยทีเดียว

_DSC0123

เมื่อประกอบกับฐานเสร็จ ก็จะเป็นแบบนี้

_DSC0127

จอมันจะปรับเลื่อนขึ้นลงได้ และบิดองศาก้มเงิย ได้ พอประมาณ

_DSC0129

ถ้าหากไม่ชอบการวางจอภาพแนวนอน จะเปลี่ยนเป็นแนวตั้งก็ได้

_DSC0130

ในส่วนของภายนอก ก็พอมองเห็นภาพละ ต่อไปก็ลองเอาไปต่อกับ macbook  กันเลย

_DSC0160

จอ Dell U2414H นี้ไม่ใช่จอแบบความละเอียดสูงเหมือน retina display ดังนั้นแล้ว ความคม  (dpi ) จะเอาไปสู้ จอ macbook คงไม่ได้แน่ๆ

_DSC0159

แต่ถ้าเอามาเปรียบเทียบพื้นที่การทำงานก็จะเห็นได้ว่ามันมีพื้นที่เยอะกว่าเดิมมาก

Untitled-2

และในส่วนของการปรับแต่งก็เหมือนๆ จอทั่วๆไป ปรับโทนสี ความสว่าง เลือก input source ว่าจะรับสัญญาณจาก hdmi หรือ diplay port ได้

_DSC0161

รูปเปรียบเทียบกับ Macbook 13″

_DSC0165

สรุปแล้ว ผมว่ามันเป็นจอที่เหมาะกับการเขียนโปรแกรมมาก เพราะ

  • มีพื้นที่ให้เขียนโค้ดเยอะกว่า macbook retina
  • สีสันของภาพ คุณภาพของจออยู่ในขั้นดีมาก
  • ใช้ usb 1 ช่อง ต่อจาก macbook  ไปเข้าจอ แต่เราจะได้ช่อง usb หลังจอภาพ เพิ่มมา 3 ช่อง
  • ราคาคุ้มค่ากับที่ต้องจ่ายไป

จากการใช้งานสักระยะ ผมว่ามันก็โอเคนะ แต่ยังไม่ได้เอาไปทดสอบกับ การเล่นเกมส์ว่าเป็นยังไง สำหรับใครที่หาจอไว้เขียนโปรแกรม ยิ่งถ้าหาจอสำหรับต่อ Macbook ผมว่าเป็นจอภาพรุ่นที่แนะนำ แต่อย่างไรก็ตาม เลือกให้เหมาะกับตัวเองครับ ลองพิจารณาจากหลายอย่าง เช่น งบ ขนาดจอภาพ ที่ต้องการ ช่องต่ออุปกรณ์ต่าง

สำหรับผมก็ขอจบการ review  เพียงเท่านี้

Semantic Versioning

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

version

อย่าง atom ก็บอกไว้ว่า version 1.3.2 คนทั่วๆไปก็คงไม่ได้สนใจว่า เลขเหล่านี้คืออะไร เข้าใจแค่เพียงว่า ตัวเลขเยอะขึ้นก็คือ version ใหม่กว่าเดิม แต่ถ้าคุณเป็น Developer เรื่องของ version จะกลายเป็นสิ่งสำคัญมาก เพราะเมื่อเขียนโปรแกรมไปสักพัก เราอาจจะต้องใช้ Library จากข้างนอก ที่เราไม่ได้เป็นเขียนขึ้นมาเอง เมื่อเลือก Library หรือ API แล้ว แน่นอนว่าไลบารีต่างๆที่เราเลือกใช้ ก็มักมีการ update เป็นเวอร์ชันใหม่ ซึ่งโดยปกติเราก็จะเปลี่ยนไปใช้เวอร์ชั่นใหม่ถูกไหม เพราะ library อาจจะมีการแก้ bug เพิ่ม feature อะไรก็ว่ากันไป  …. แต่หลายๆครั้งเราก็ต้องพบว่า อ้าวนี่เราต้องแก้ไขโค้ดใหม่ เพราะ API , Library เหล่านั้น ได้เปลี่ยนแปลง  บางฟังชั่นได้ยกเลิกไป หรือฟังชั่นที่เคยใช้งานใช้งานประจำ ต้องการพารามิเตอร์เพิ่มเติม อะไรแบบนี้  คำถามคือ เราจะรู้ได้ยังไงว่า ไลบารี่ที่เค้า update ใหม่เนี่ย โค้ดของเราจะยังใช้งานได้ โดยไม่ต้องแก้ไขอะไร ?

โอเค หลายคนอาจจะบอกว่า โปรเจคเล็กๆ แก้โค้ดของเราให้เป็น API ตัวใหม่ก็จบละ แต่ถ้าเป็นโปรเจคใหญ่ๆ มีโค้ดซับซ้อน การไปไล่แก้คำสั่งต่างๆย่อมปวดหัวแน่นอน และในมุมกลับกัน ถ้าหากเราเป็นคนที่เขียน library , api  เหล่านั้นเสียเองละ

โอเค .. ในวันแรกที่ปล่อย library ให้คนอื่นใช้งาน ก็ตั้งเป็น 1.0 ใช่ไหม ? ต่อมาพบว่ามันมีบั๊ก แก้ไขโค้ดเสร็จ ต้องการจะปล่อย lib ตัวใหม่ ก็ต้องปรับ เลข version กันสักหน่อย แต่ก็ไม่รู้จะตั้งเป็นเลขอะไรระหว่าง 1.1 หรือเปลี่ยนเป็น 2.0 ไปเลย เราจะมีหลักการยังไงในการตั้งเลข version ?

หรือเคยสังเกตกันไหมว่า บางทีเราใช้ library ที่โหลดมาจากเน็ท เค้าจะมีเลขบอกไว้ เช่น LibA 4.0 ต่อมาเมื่อมีการปรับปรุงแก้ไข bug ก็เปลี่ยนเลขเป็น 4.2 แล้วเคยคิดไหมครับว่า ทำไมมันไม่เป็น 5.0 หรือ 4.1 ละ ?

เมื่อหลายๆปีก่อน ผมเองก็เป็นคนหนึ่งที่เขียนเลข version แบบมั่วๆ โดยไม่มีหลักการอะไรเหมือนกัน อยากได้อะไรก็ตั้งเอาเอง เช่น 1.2.0 beta อะไรแบบนี้ เห็นมันเท่ดี แม้ว่าการเขียนเลข version นั้นไม่ได้มีแนวทางตายตัว ว่าต้องเขียนแบบนี้ถึงจะถูกต้อง อย่างไรก็ตามมันมีหลักการที่เป็นที่นิยมใช้อยู่ ซึ่งหนึ่งในนั้นคือ Semantic Version

เลข Semantic Version จะมีความสำคัญอย่างมาก สำหรับ Developer เพราะมันจะช่วยให้เราเลือก Version ของ Library ได้ถูกต้อง และถ้าหากเราเขียน Library ให้คนอื่นเอาไปใช้ยิ่งต้องเขียนเลข version ให้ดี ซึ่งอย่างกรณี JKNotificationPanel ที่เป็น cocoapod library ของผมเอง นั้นก็ตั้งเลข version ตามแบบ semantic นี้เหมือนกัน

วันนี้ก็เลยจะขอพูดถึง Semantic Version และหลักการของมัน อย่างคร่าวๆเพื่อให้เราสามารถเขียนเลข version ให้มีความหมาย มากกว่า แค่บอกว่า library , api ที่เราใช้อยู่นั้น ใหม่ หรือ เก่า

Semantic Version

การเขียน semantic version นั้นมักจะใช้ในการเขียน Library และ API ต่างๆ ซึ่งเลข version ที่เป็น semantic version นั้นจะประกอบไปด้วยเลข 3 ส่วนคือ  x.y.z ( ไม่มี z ก็ได้ )

โดยที่เลขแต่ละตัวนั้นหมายถึง

  • X คือ Major  Version
  • Y คือ Minor  Version
  • และสุดท้าย Z คือ Patch Version

แต่ก่อนที่จะไปทำความเข้าใจการเขียนเลข เหล่านี้จะขออธิบายเพิ่มเติมเกี่ยวกับศัพท์ที่จะยินอยู่บ่อยๆสักหน่อย นั่นคือ backward compatibility

คำว่า Backward compatibility คือ การทำงานเข้ากันได้กับ API เดิม เช่น สมมติว่า โปรเจคเราใช้ LibA 1.0 ซึ่งมีฟังก์ชั่น Sum( a, b ) ที่รับค่า integer สองตัวคือ a และ b และในเวลาต่อมา LibA ได้ออกเวอร์ชั่นใหม่เป็น 1.2  และปรับปรุงให้ฟังก์ชั่น Sum นั้นสามารถรับค่า double ได้

ถ้าโค้ดของเราที่เรียกฟังก์ชัน Sum ยังทำงานได้ โดยที่ไม่ต้องเปลี่ยนแปลงอะไร นั่นคือไม่ต้องเปลี่ยนค่า a,b เป็น double สามารถใช้ integer ต่อไปได้ นั่นหมายถึงว่า libA ตัวใหม่นี้รองรับ backward compatibility

เอาละ เมื่อเข้าใจคำศัพท์แล้ว ต่อไปก็มาดูหลักการกันเลย

อันที่จริงการตั้งตัวเลข semantic นี้มีหลักการ ที่เขียนไว้ใน http://semver.org/ อยู่แล้ว ไปอ่านกันได้ แต่โดยสรุปอย่างย่อแล้ว มันมีหลักการง่ายๆคือ

  • เลข x.y.z นี้จะต้องไม่เป็นค่าติดลบ คือ จะไม่เขียน -1.0.0 อะไรแบบนี้
  • ค่าจะต้องไม่เป็น 0 คือ เขียนเลข 0.0.0 ไม่ได้
  • ค่าจะต้องเพิ่มขึ้นเสมอ เช่นตอนนี้ใช้ 1.4 เมื่อเปลี่ยน version ก็ต้องมีค่ามากขึ้น จะเขียน 1.3 ไม่ได้
  • ถ้าเลข Major Version มีค่าเป็น 0 นั่นหมายถึงว่า เป็น version ที่กำลังเริ่มต้นพัฒนา API ต่างๆอาจจะเปลี่ยนแปลงได้เสมอ
  • การเปลี่ยนเลข Patch Version จะใช้กับการแก้ไข bug ที่ทำให้การทำงานของ API, Function ของ library นั้นไม่ถูกต้อง เช่นฟังชั่น Sum ส่งค่าลบเลข มาแทน ผลการบวกเลข ในกรณีนี้จะต้องทำการเปลี่ยนเลข Patch  เช่นจาก 1.0.0 เป็น 1.0.1 เป็นต้น
  • Minor Version จะเปลี่ยนก็ต่อเมื่อ มีการเพิ่ม Feature , API ใหม่ๆ แต่ยังคงรองรับ api เก่า (backward compatibility) และถ้าหากเปลี่ยนเลข Minor Version แล้ว เลข Patch จะต้องเปลี่ยนเป็น 0
    เช่น 1.1.3 ก็เปลี่ยนเป็น 1.2.0
  • Major Version จะเปลี่ยน เมื่อ มีการเพิ่ม Feature หรือ  API แต่ไม่รองรับ backward compatibility และเมื่อเปลี่ยนเลข Major ใหม่ ตัวเลข Minor , Patch จะต้องเปลี่ยนเป็น 0
    เช่น 1.1.3 ถ้าหากเปลี่ยนเป็น 2.0.0 หมายถึงว่า lib นี้ได้เพิ่ม feature และไม่รองรับ backward นั่นเอง
  • ในกรณีที่เป็น pre-release ( ยังไม่สมบูรณ์ แต่ออกมาให้ลองใช้ก่อน ) อาจจะเขียน ตัวหนังสือ หรือตัวเลขต่อท้ายได้ เช่น 1.0.0-alpha , 1.0.0-beta.2 และแน่นอนว่าเวอร์ชั่นที่ไม่มี prelease ต่อท้ายคือเวอร์ชั่นที่ใหม่กว่า เช่น (เก่าสุด) 1.0.0-alpha  < 1.0.0-beta < 1.0.0 < 1.0.1 (ใหม่ล่าสุด)

ทีนี้พอจะเข้าใจแล้วใช่ไหมครับว่า เลข version นั้นมีความสำคัญยังไง และเราก็ควรจะใช้ semantic version นี้ให้เป็นประโยชน์

เอาละครับก่อนจากกัน ลองตอบตัวเองกันสักหน่อยว่า

Swift 2.0 กับ Swift 2.2 นั้นหมายถึงอะไร

เชื่อว่าหลังจากอ่านบทความนี้จบ คุณก็ตอบได้ใช่ไหมละครับว่า 2.2 การเพิ่ม feature ใหม่ๆ และรองรับ backward compatibility คือพูดง่ายๆว่า ถ้าหากเราเขียนโค้ดด้วย Swift 2.0 มันจะยังทำงานกับ Swift 2.2 ได้ โดยที่ไม่ต้องเปลี่ยนแปลงอะไร แต่จะถูกแจ้งว่า โค้ดบางส่วน กำลังจจะ deprecate ( ยกเลิก ) ในอนาคต นั่นเอง

Swift Programming ตอนที่ 11 : Introduction to iOS Programming

วันนี้เราจะเรียนรู้ และทำความเข้าใจ basic concept ต่างๆที่ใช้ในการเขียนโปรแกรม iOS  เช่น MCV ,  Delegate , Action-Target และการทำงานของ  Window

เขียนโปรแกรมกันเถิดจะเกิดผล Programming and technology