ความกลัวเข้ามาอย่างช้าๆเพราะฉันรู้ว่าฉันกำลังจะหมดรูปถ่ายสต็อกเหล่านี้

Swift + การเริ่มต้นด้วยการปิด

ปิด F.T.W.

บันทึกย่อ - โพสต์ในอนาคตทั้งหมดของฉันจะถูกเผยแพร่บนเว็บไซต์เฉพาะของฉันและเอกสารนี้ไม่ได้รับการปรับปรุง ขอบคุณที่อ่าน!

ฉันเริ่มที่จะขุดการเริ่มต้นทั้งหมดใน Swift ฉันเขียนเกี่ยวกับมัน ฉันเขียนเกี่ยวกับสาเหตุที่ใช้งานได้เหมือนกัน ฉันพูดไปแล้ว ฉันอ่านเกี่ยวกับเรื่องนี้ (มาก) แต่เดี๋ยวก่อนฉันกลับมาอีกครั้งสำหรับเรื่องนี้

ในหลาย ๆ วิธีที่สวยงามและหลากหลายที่เราสามารถเริ่มต้นบางสิ่งใน Swift ได้ - โดยทั่วไปแล้วการปิดไม่ได้นำมาใช้เป็นวิธีการที่จะทำเช่นนั้น แต่อนิจจามันสามารถสร้างรหัสต้นแบบ boilerplate ™ที่เจ็บปวดน้อยลงและสามารถจัดการได้ง่ายขึ้น

สำหรับอินเทอร์เฟซผู้ใช้แบบเป็นโปรแกรมออกมี - นี่สำหรับคุณ!

UIKit == UIHugeSetupCode ()

ดูสิมันไม่ใช่ความผิดของ UIKIT ส่วนประกอบที่ผู้ใช้ต้องมีการโต้ตอบกับผู้ใช้นั้นคือรหัสการติดตั้งเนื่องจากการตั้งค่า โดยทั่วไปแล้วสิ่งเหล่านี้จะค้นพบจำนวนมากใน viewDidLoad หรือ loadView:

แทนที่ func loadView ()
{
    ให้ helloWorldLbl = UILabel ()
    helloWorldLbl.text = NSLocalizedString (“ controller.topLbl.helloWorld”, ความคิดเห็น:“ Hello World!”)
    helloWorldLbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    helloWorldLbl.textColor = UIColor.whiteColor ()
    helloWorldLbl.textAlignment = .Center
    self.view.addSubview (helloWorldLbl)
}

นี่เป็นมาตรฐานที่เป็นธรรมสำหรับพวกเราที่ร่วมลงทุนกับ Cocoa Touch โดยไม่มี. xib หรือ. storyboard แม้ว่าถ้าคุณแบ่งปันความรักที่มีต่อวิธีการ viewDidLoad หรือ loadView ขนาดจิ๋วของฉันคุณสามารถนำสิ่งนี้ไปใช้ที่อื่นได้

บอกเด็ก ๆ ว่า:

ให้ helloWorldLbl: UILabel = {
    ให้ lbl = UILabel ()
    lbl.text = NSLocalizedString (“ controller.topLbl.helloWorld”, ความคิดเห็น:“ Hello World!”)
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = UIColor.whiteColor ()
    lbl.textAlignment = .Center
    ส่งคืน lbl
} ()

น่ารัก. ในหนังสือของ Apple ใน Swift มันตั้งข้อสังเกตว่า“ ถ้าค่าเริ่มต้นของคุณสมบัติของคุณต้องการการปรับแต่งหรือตั้งค่าบางอย่างคุณสามารถใช้การปิดหรือฟังก์ชั่นระดับโลกเพื่อกำหนดค่าเริ่มต้นที่กำหนดเองสำหรับคุณสมบัตินั้น” ปรับแต่งและตั้งค่าได้มากมาย

อย่างไรก็ตามหนึ่งในผลพลอยได้ที่น่าดึงดูดก็คือลักษณะของ loadView ในขณะนี้:

แทนที่ func loadView
{
    self.view.addSubview (self.helloWorldLbl)
}

รับทราบอย่างไรก็ตามของ“ ()” ในตอนท้ายของการปิดในการประกาศทรัพย์สิน นี่เป็นการให้วิซาร์ด Swift ตัวเล็ก ๆ ที่คอมไพล์โค้ดของคุณรู้ว่าอินสแตนซ์นั้นถูกกำหนดให้กับประเภทการคืนของการปิด หากเราไม่สนใจสิ่งนี้อาจเป็นไปได้ว่าเราสามารถมอบหมายการปิดจริงให้กับอินสแตนซ์ได้

และในกรณีนี้นั่นคือ

กฎคือกฎ

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

ตัวอย่างเช่น:

ให้ helloWorldLbl: UILabel = {
    ให้ lbl = UILabel ()
    lbl.text = self.someFunctionToDetermineText () // ข้อผิดพลาดของคอมไพเลอร์
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = self.myAppTheme.textColor () // ข้อผิดพลาดอื่น
    lbl.textAlignment = .Center
    ส่งคืน lbl
} ()

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

นี่คือข้อเสียที่แตกต่างกัน แต่รับประกันว่าจะเสียเปรียบเมื่อใช้การปิดเพื่อเริ่มต้น แม้ว่าจะเหมาะสมแล้ว - และสอดคล้องกับหนึ่งในสามเป้าหมายการออกแบบของ Swift: ความปลอดภัย

Gettin ’น่ารักด้วย Collections

พื้นที่หนึ่งที่ฉันพบว่าเทคนิคนี้มีประโยชน์เป็นพิเศษคือมีอินสแตนซ์ที่แสดงถึงหนึ่งในคอลเลกชันที่หลากหลายใน Swift จากพรสวรรค์มากมายของสวิฟท์การแบ่งและกลั่นกรองคอลเล็กชั่นด้วยพลังของพันยักษ์ใหญ่ถือเป็นหนึ่งในสิ่งที่ฉันชอบมากที่สุด

ลองพิจารณาตัวอย่างต่อไปนี้ซึ่งนำมาจากเครื่องมือเริ่มต้นในโครงการที่ฉันกำลังทำงานอยู่ คลาสที่มีรหัสนี้มีคุณสมบัติ [นักพัฒนา] ในการเปิดตัวครั้งใหม่ฉันจะตั้งค่าเริ่มต้นจากไฟล์. plist หลังจากนั้นจะถูกเก็บไว้ผ่าน NSKeyedArchiver

การ์ดให้ devs = NSKeyedUnarchiver.unarchiveObjectWithFile (DevDataManager.ArchiveURL.path!) เป็น? [ผู้พัฒนา] อื่น
{
    self.developers = {
        ให้ pListData = // รับข้อมูล plist
        var devArray: [Developer] = [Developer] ()
        // ตั้งค่า devArray จากข้อมูล plist
        return devArray.map {$ 0.setLocation ()}
                       .filter {$ 0.isRentable}
                       .sort {$ 0.name <$ 1.name}
     } ()
    กลับ
}
self.developers = devs

ฉันค่อนข้างชอบวิธีการนี้เนื่องจากแม้ว่าเราจะไม่ได้ใช้มันนอกเหนือจากตัวเริ่มต้นความตั้งใจของรหัสนั้นชัดเจนมากในการที่จะรับผิดชอบต่อการตั้งค่าคุณสมบัติเท่านั้น

เนื่องจาก initializers และการแทนที่ viewDidLoad มีขนาดใหญ่ขึ้นการแบ่งสิ่งต่าง ๆ ออกมาเช่นนี้ (อย่างน้อยที่สุด) เป็นของขวัญต้อนรับในแง่ของการอ่านได้

รับ NSCute

หากคุณเพิ่งเริ่มขุดสิ่งต่าง ๆ ด้วยการปิดตัวเอง แต่กำลังทุกข์ทรมานจากการขาดการใช้งานเงินจำนวนมากในรหัสของคุณให้กำลังใจ การใช้ Swiftery ผู้ชำนาญหนึ่งสามารถเขียนโค้ดบางอย่างที่ infers ประเภทภายในปิดตัวเองซึ่งทำให้การกำหนดค่ารูปแบบโปรบางอย่าง พิจารณารหัสนี้ซึ่งฉันได้พบกับ NSHipster ที่ให้ข้อมูลเสมอ:

@warn_unused_result
ฟังก์ชั่นสาธารณะ Init  (ค่า: ประเภท, บล็อก @noescape: (วัตถุ: ประเภท) -> โมฆะ) -> ประเภท
{
    บล็อก (วัตถุ: ค่า)
    ค่าส่งคืน
}

ฉันชอบสิ่งที่เกิดขึ้น ฟังก์ชั่นสาธารณะที่จะปิดด้วยวัตถุที่พิมพ์โดยใช้ข้อมูลทั่วไปแล้วส่งกลับประเภทนั้น ซึ่งหมายความว่าคุณสามารถพลิกกลับและเริ่มต้นสิ่งต่าง ๆ ด้วยข้อมูลประเภทเพิ่มเติม จากนั้นตัวอย่างโค้ดแรกของเราจะเป็นดังนี้:

ให้ helloWorldLbl = Init (UILabel ()) {
    $ 0.text = NSLocalizedString (“ controller.topLbl.helloWorld”, ความคิดเห็น:“ Hello World!”)
    $ 0.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    $ 0.textColor = UIColor.whiteColor ()
    $ 0.textAlignment = .Center
}

แม้ว่ามันอาจดูเหมือนแฟนซี แต่ก็เป็นการทำลายความจำเป็นของตัวแปรอินสแตนซ์จากภายในการปิดและกำจัดข้อกำหนด“ ()” ออก ดีมาก

ความคิดสุดท้าย

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

มันเป็นวิธีที่สนุกที่จะทำสิ่งต่าง ๆ และมีหลายวิธีในการทำสิ่งเดียวกันใน Objective-C เพื่อนเก่าของเรา แต่เดี๋ยวก่อนคุณรู้ใช่มั้ย

จนถึง nextWeek = {ให้สัปดาห์ = สัปดาห์ () week.advancedBy (วัน: 7)} ()

Jordan Morgan เป็นวิศวกรซอฟต์แวร์ iOS ที่ทำงาน Dreaming In Binary

หากคุณเรียนรู้เกี่ยวกับการใช้ closures สำหรับผู้เริ่มต้นโปรดอย่าลังเลที่จะไปข้างหน้าและขอแนะนำ NSR (สิ่งนี้โดยที่: ด้านล่าง);