วิธีสร้างบริดจ์ระหว่างเฟรมเวิร์กในแอพ iOS

หากรหัสแอพของคุณเป็นแบบนี้ ...

“ ฉันต้องการส่งออกส่วนหนึ่งของแอพของฉัน แต่มันเชื่อมโยงกับส่วนที่เหลือของแอปอย่างจานสปาเก็ตตี้!”

กำลังพยายามส่งออกแอปขนาดเล็กซึ่งขึ้นอยู่กับเกินไป

เมื่อฉันเริ่มที่จะทำให้เป็นส่วนหนึ่งของแอพที่ฉันกำลังทำงานอยู่ฉันทำให้วิ่งเข้าไปในกำแพง

ฉันต้องการส่งออกบริการ (อันที่จริงแล้วเป็นบริการติดตาม) ลงในกรอบงานที่แยกต่างหาก ปัญหาคือบริการนี้เชื่อมโยงกับแอปน้อยเกินไป มันกำลังใช้บริการอื่นซึ่งตัวมันเองใช้อีกอันหนึ่งยึดติดแน่นในแอพ

เพื่อที่จะส่งออกบริการติดตามฉันจะต้อง refactor และสร้างใหม่ทั้งชุดของบริการในกรอบใหม่!

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

มาเริ่มด้วยตัวอย่างที่เป็นรูปธรรมกันเถอะ!

ที่นี่เราเป็นวิธีที่ดีที่สุดในการเรียนรู้และทำความเข้าใจว่าสิ่งต่าง ๆ ทำงานอย่างไรเพื่อฝึกฝน! (ฉันจะให้ repo Github สำหรับตัวอย่างนี้ในตอนท้ายของโพสต์นี้)
ขอผมตั้งบริบทเรามีแอพเล็ก ๆ ที่มีเพียง 2 หน้าจอ:

  • หน้าจอหลัก
  • หน้าจอการชำระเงิน (เราต้องการส่งออกหน้าจอนั้นไปยังกรอบงาน)

หน้าการชำระเงินมี TextField เพื่อป้อนหมายเลขบัตรและปุ่มชำระเงิน เมื่อคุณกดปุ่มการชำระเงินควรจะเปิดใช้งาน
แต่! ความท้าทายอยู่ในวิธีการชำระเงิน สมมติว่าเราไม่สามารถส่งออกบริการการชำระเงินด้วยเหตุผลบางอย่างที่ฉันปรากฏก่อนหน้านี้เล็กน้อย

หน้าจอหลักและหน้าจอการชำระเงิน

ดังนั้นเราจึงมีสองหน้าจอนี้ประกาศในเป้าหมายที่แตกต่างกันสองแห่ง หน้าจอหลักจะประกาศในเป้าหมายของแอปหลักและหน้าจอการชำระเงินจะประกาศในโมดูลอื่นที่เรียกว่า PaymentModule นอกจากนี้เรายังมี PaymentService ประกาศในเป้าหมายแอปหลักดังต่อไปนี้:

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

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

ดังนั้นเราจะใช้วิธีนี้จาก PaymentViewController อย่างไร

กำหนดโปรโตคอลในโมดูล

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

ดังนั้นให้กำหนดโปรโตคอลชื่อ PaymentServiceProtocol ด้วยวิธีการชำระเงิน:

การใช้โปรโตคอลในแอป

ตอนนี้เราต้องบอก PaymentService ของเราเพื่อให้สอดคล้องกับโปรโตคอลนี้ เราแค่ต้องเพิ่มสิ่งนี้:

“ ทำไมวิธีที่ประกาศในโปรโตคอลไม่ได้ใช้งานในส่วนขยายนี้”

คุณมีสิทธิ์เมื่อปฏิบัติตามโปรโตคอลคุณต้องใช้คุณสมบัติและวิธีการ เคล็ดลับที่นี่คือชื่อวิธีการในโพรโทคอลเหมือนกับชื่อวิธีการใน PaymentService ที่เราประกาศก่อนหน้านี้เล็กน้อย ด้วยวิธีดังกล่าวระบบจะรู้ว่าจะต้องใช้วิธีการชำระเงินที่ประกาศในคลาส PaymentService เมื่อเข้าถึงวิธีโปรโตคอล

การเชื่อมโยงสองส่วน

ตอนนี้เราต้องรวมสองส่วนเข้าด้วยกัน
จาก HomeViewController เมื่อเราแตะที่ปุ่ม“ ไปที่หน้าการชำระเงิน” เรากำลังทำให้การชำระเงินเป็น ในเวลานั้นเราจะผ่านการอ้างอิงไปยังคลาส PaymentService แต่ตัวควบคุมการชำระเงินในโมดูลจะเห็นว่าเป็นประเภท PaymentServiceProtocol

นี่คือเคล็ดลับ:

เรากำลังผ่าน PaymentService.self และรหัสในโมดูลจะเห็น PaymentServiceProtocol.Type
ตอนนี้เราสามารถใช้วิธีการโทรที่กำหนดไว้ในแอพจากโมดูล!

การใช้สะพาน

ตอนนี้มันง่ายมากที่จะใช้สะพานที่เราสร้างขึ้น:

วิธีการทำ TapPayButton ถูกเรียกเมื่อใดก็ตามที่คุณแตะที่ปุ่มชำระเงิน (ฟังดูถูกต้องใช่ไหม?) ตรวจสอบที่บรรทัดที่ 23: เรากำลังเรียกวิธีชำระเงินในการอ้างอิงโปรโตคอลที่เราได้รับจากแอพ

เนื่องจาก PaymentService เป็นไปตามโปรโตคอลนี้ระบบจะดำเนินการโค้ดภายในวิธีการชำระเงินซึ่งกำหนดไว้ใน PaymentService.swift

กล่าวอีกนัยหนึ่งเรากำลังใช้วิธีการที่เราไม่สามารถโทรจากโมดูลได้ในตอนแรก! ตั้งค่าบริดจ์แล้ว

นี่คือสิ่งที่ดูเหมือนว่าเมื่อคุณแตะที่ปุ่มจ่าย

ใช้วิธีการจ่ายที่มีอยู่ในเป้าหมายหลักจากโมดูลการชำระเงิน

ข้อสรุป

เพื่อสรุปวิธีการเชื่อมต่อนี้สามารถใช้งานได้หากคุณต้องการส่งออกส่วนประกอบของแอพของคุณไปยังเฟรมเวิร์ก

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

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

ฉันยอมรับว่าในโลกอุดมคติที่มียูนิคอร์นและสิ่งแฟนซีเราจะไม่ทำอย่างนั้น เราอยากจะส่งออกส่วนประกอบทั้งหมด แต่อย่างที่บอกไปหลายครั้งมันเป็นไปไม่ได้เสมอ

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

เรื่องนี้ได้รับการเผยแพร่ใน The Startup ซึ่งเป็นสิ่งพิมพ์ผู้ประกอบการที่ใหญ่ที่สุดของ Medium ตามด้วยผู้คน +442,678 คน

สมัครสมาชิกเพื่อรับเรื่องเด่นของเราที่นี่