เราจะใช้ [การปิดบังตัว] ในสวิฟท์


467

ใน WWDC 2014 เซสชั่น 403 Intermediate Swiftและการถอดเสียงมีสไลด์ดังต่อไปนี้

ป้อนคำอธิบายรูปภาพที่นี่

ลำโพงพูดในกรณีนั้นถ้าเราไม่ใช้[unowned self]ตรงนั้นมันจะเป็นความจำรั่ว หมายความว่าเราควรใช้[unowned self]การปิดภายในเสมอหรือไม่?

บนเส้น 64 ViewController.swift ของ app Swift อากาศ , [unowned self]ฉันไม่ได้ใช้ แต่ผมปรับปรุง UI โดยใช้บางส่วน@IBOutletเหมือนและself.temperature self.loadingIndicatorมันอาจจะตกลงเพราะทุกวินาทีฉันที่กำหนดไว้@IBOutlet weakแต่เพื่อความปลอดภัยเราควรใช้อยู่เสมอ[unowned self]?

class TempNotifier {
  var onChange: (Int) -> Void = {_ in }
  var currentTemp = 72
  init() {
    onChange = { [unowned self] temp in
      self.currentTemp = temp
    }
  }
}

ลิงก์รูปภาพเสียหาย
Daniel Gomez Rico

@ DanielG.R ขอบคุณฉันสามารถเห็นมัน i.stack.imgur.com/Jd9Co.png
Jake Lin

2
เว้นแต่ฉันเข้าใจผิดตัวอย่างที่ให้ไว้ในสไลด์เป็น incorrect- onChangeควรจะ[weak self]ปิดเพราะมันเป็นที่สาธารณะ (ภายใน แต่ยังคง) คุณสมบัติดังนั้นวัตถุอื่นอาจจะได้รับการจัดเก็บและการปิดการเก็บรักษาวัตถุ TempNotifier รอบ(ไปเรื่อย ๆ ถ้า โดยใช้วัตถุที่ไม่ปล่อยให้ไปของonChangeการปิดจนกว่าจะเห็นความTempNotifierเป็นไปผ่านโทษอ่อนแอของตัวเองไปTempNotifier ) ถ้าvar onChange …เป็นเช่นprivate var onChange …นั้น[unowned self]จะถูกต้อง ฉันไม่แน่ใจ 100% ของสิ่งนี้แม้ว่า; ใครบางคนที่ถูกต้องฉันโปรดถ้าฉันผิด
Slipp D. Thompson

@ Jake Lin `var onChange: (Int) -> Void = {}` วงเล็บปีกกาแสดงถึงการปิดที่ว่างเปล่าหรือไม่? เช่นเดียวกับในการกำหนดอาเรย์ว่างด้วย[]? ฉันไม่พบคำอธิบายในเอกสารของ Apple
bibscy

@bibscy ใช่{}คือการปิดที่ว่างเปล่า (ตัวอย่างของการปิด) เป็นค่าเริ่มต้น (ไม่ได้ทำอะไรเลย) (Int) -> Voidคือคำจำกัดความการปิด
Jake Lin

คำตอบ:


871

[unowned self]ไม่มีมีแน่นอนครั้งที่คุณไม่ต้องการที่จะใช้ บางครั้งคุณต้องการปิดการจับภาพตัวเองเพื่อให้แน่ใจว่ามันยังรอบโดยเวลาปิดเรียกว่า

ตัวอย่าง: การร้องขอเครือข่ายแบบอะซิงโครนัส

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

ควรใช้เมื่อunowned selfใดหรือweak self

เวลาเท่านั้นที่คุณต้องการจริงๆที่จะใช้[unowned self]หรือ[weak self]เมื่อคุณจะสร้างวงจรการอ้างอิงที่แข็งแกร่ง รอบการอ้างอิงที่แข็งแกร่งคือเมื่อมีการวนรอบของการเป็นเจ้าของเมื่อวัตถุจบลงด้วยการเป็นเจ้าของซึ่งกันและกัน (อาจผ่านบุคคลที่สาม) และดังนั้นพวกเขาจะไม่ถูกจัดสรรคืนเนื่องจากพวกเขาทั้งคู่มั่นใจว่ากันและกันติดกัน

ในกรณีเฉพาะของการปิดคุณเพียงแค่ต้องตระหนักว่าตัวแปรใด ๆ ที่ถูกอ้างอิงภายในนั้นได้รับการ "ปิด" ตราบใดที่การปิดอยู่ใกล้วัตถุเหล่านั้นจะถูกรับประกันว่าอยู่ใกล้ วิธีเดียวที่จะหยุดการเป็นเจ้าของที่เป็นที่จะทำหรือ[unowned self] [weak self]ดังนั้นถ้าชั้นเรียนเป็นเจ้าของการปิดและการปิดนั้นรวบรวมการอ้างอิงที่แข็งแกร่งไปยังคลาสนั้นคุณจะมีวัฏจักรการอ้างอิงที่แข็งแกร่งระหว่างการปิดและการเรียน ซึ่งรวมถึงถ้าชั้นเป็นเจ้าของสิ่งที่เป็นเจ้าของการปิด

โดยเฉพาะในตัวอย่างจากวิดีโอ

ในตัวอย่างบนสไลด์TempNotifierเป็นเจ้าของการปิดผ่านonChangeตัวแปรสมาชิก หากพวกเขาไม่ได้ประกาศselfว่าunownedจะปิดตัวเองก็จะselfสร้างวงจรอ้างอิงที่แข็งแกร่ง

ความแตกต่างระหว่างunownedและweak

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


1
สวัสดี คำตอบที่ดี ฉันกำลังดิ้นรนเพื่อทำความเข้าใจตนเองที่ไม่มีเจ้าของ เหตุผลที่ใช้อ่อนแอตัวเองเป็นเพียง 'ตัวเองกลายเป็นตัวเลือก' ไม่เพียงพอสำหรับฉัน เหตุใดฉันจึงต้องการใช้ 'ตัวตนที่ไม่มีกรรมสิทธิ์' โดยเฉพาะstackoverflow.com/questions/32936264/…

19
@robdashnash ข้อดีของการใช้ตนเองที่ไม่ได้เป็นเจ้าของคือคุณไม่จำเป็นต้องแกะตัวเลือกซึ่งอาจเป็นรหัสที่ไม่จำเป็นถ้าคุณรู้แน่ ๆ ด้วยการออกแบบว่ามันจะไม่เป็นศูนย์ ท้ายที่สุดตัวตนที่ไม่ได้ใช้จะใช้เพื่อความกระชับและอาจเป็นคำแนะนำสำหรับนักพัฒนาในอนาคตที่คุณไม่เคยคาดหวังว่าจะมีคุณค่าใด ๆ
drewag

77
เคสสำหรับใช้[weak self]ในการร้องขอเครือข่ายแบบอะซิงโครนัสอยู่ในตัวควบคุมมุมมองที่ใช้การร้องขอนั้นเพื่อเติมข้อมูลในมุมมอง หากผู้ใช้สำรองเราไม่จำเป็นต้องเติมมุมมองอีกต่อไปและเราไม่ต้องการการอ้างอิงไปยังตัวควบคุมมุมมอง
David James

1
weakการอ้างอิงถูกตั้งค่าเป็นnilเมื่อวัตถุถูกจัดสรรคืน unownedการอ้างอิงไม่ใช่
BergQuester

1
ฉันสับสนเล็กน้อย unownedใช้non-Optionalในขณะที่weakถูกใช้Optionalเพื่อselfเป็นของเราOptionalหรือnon-optional?
มูฮัมหมัดนายาบ

193

อัปเดต 11/2016

ผมเขียนบทความเกี่ยวกับเรื่องนี้ขยายคำตอบนี้ (มองเข้าไปใน SIL จะเข้าใจสิ่งที่ ARC ไม่) ให้ตรวจสอบมันออกมาที่นี่

คำตอบเดิม

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

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

รวดเร็วและอ่อนแอ

สถานการณ์

คุณสามารถมีสถานการณ์ที่เป็นไปได้สองสถานการณ์:

  1. ปิดมีชีวิตเดียวกันของตัวแปรดังนั้นการปิดจะสามารถเข้าถึงได้เท่านั้นจนกว่าตัวแปรที่สามารถเข้าถึงได้ ตัวแปรและการปิดนั้นมีอายุการใช้งานเท่ากัน ในกรณีนี้คุณควรประกาศอ้างอิงเป็นที่ไม่มีเจ้าของ ตัวอย่างทั่วไปคือการ[unowned self]ใช้ในหลายตัวอย่างของการปิดขนาดเล็กที่ทำบางสิ่งในบริบทของผู้ปกครองของพวกเขาและที่ไม่ได้ถูกอ้างอิงที่อื่นจะไม่ได้อายุยืนกว่าพ่อแม่ของพวกเขา

  2. อายุการปิดไม่ขึ้นอยู่กับตัวแปรตัวใดตัวหนึ่งการปิดสามารถยังสามารถอ้างอิงได้เมื่อตัวแปรไม่สามารถเข้าถึงได้อีกต่อไป ในกรณีนี้คุณควรประกาศข้อมูลอ้างอิงว่าอ่อนแอและตรวจสอบว่าไม่มีข้อมูลก่อนใช้ (อย่าบังคับให้แกะ) ตัวอย่างทั่วไปของสิ่งนี้คือ[weak delegate]คุณสามารถเห็นได้ในบางตัวอย่างของการปิดการอ้างอิงวัตถุผู้มอบหมายที่ไม่เกี่ยวข้อง (อายุการใช้งาน) อย่างสมบูรณ์

การใช้งานจริง

แล้วคุณจะใช้เวลาส่วนใหญ่แบบไหนกัน?

การอ้างอิง Joe Groff จาก twitter :

ไม่เป็นเจ้าของเร็วกว่าและอนุญาตให้เปลี่ยนไม่ได้และไม่เป็นไปตามข้อกำหนด

หากคุณไม่ต้องการความอ่อนแออย่าใช้มัน

คุณจะหาข้อมูลเพิ่มเติมเกี่ยวกับการที่ไม่มีเจ้าของ*งานภายในที่นี่

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


26
ฉันเบื่อที่จะได้ยินคำอธิบายของนกแก้ว "ใช้สัปดาห์ถ้าตัวเองอาจเป็นศูนย์ใช้ไม่ได้ใช้เมื่อไม่สามารถเป็นศูนย์ได้" โอเคเราเข้าใจ - ได้ยินล้านครั้ง! คำตอบนี้จะขุดลึกลงไปว่าเมื่อใดที่ตนเองสามารถเป็นศูนย์ในภาษาอังกฤษธรรมดา ๆ ได้ ขอบคุณสำหรับคำอธิบายที่ยอดเยี่ยมนี้ !!
TruMan1

ขอบคุณ @ TruMan1 ฉันจริง ๆ เขียนโพสต์ในเรื่องนี้ที่จะจบลงในบล็อกของฉันในไม่ช้าจะปรับปรุงคำตอบด้วยลิงก์
Umberto Raimondi

1
คำตอบที่ดีในทางปฏิบัติมาก ฉันได้รับแรงบันดาลใจให้เปลี่ยน vars อ่อน ๆ ที่ไวต่อการแสดงของฉันเป็นไม่มีเจ้าของตอนนี้
original_username

"อายุการปิดไม่ขึ้นอยู่กับตัวแปรตัวใดตัวหนึ่ง" คุณพิมพ์ผิดหรือเปล่า?
น้ำผึ้ง

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

105

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

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

    class MyViewController: UIViewController {
          @IBOutlet weak var myButton: UIButton!
          let networkManager = NetworkManager()
          let buttonPressClosure: () -> Void // closure must be held in this class. 
    
          override func viewDidLoad() {
              // use unowned here
              buttonPressClosure = { [unowned self] in
                  self.changeDisplayViewMode() // won't happen after vc closes. 
              }
              // use weak here
              networkManager.fetch(query: query) { [weak self] (results, error) in
                  self?.updateUI() // could be called any time after vc closes
              }
          }
          @IBAction func buttonPress(self: Any) {
             buttonPressClosure()
          }
    
          // rest of class below.
     }

17
อันนี้ต้องการ upvotes เพิ่มเติม ตัวอย่างที่เป็นของแข็งสองตัวอย่างแสดงให้เห็นว่าการปิดปุ่มกดจะไม่มีอยู่นอกช่วงอายุการใช้งานของตัวควบคุมมุมมองและสามารถใช้งานที่ไม่เป็นเจ้าของได้
ทิม Fuqua

2
ดังนั้นเพื่ออธิบายให้ชัดเจนเรามักจะใช้ไม่เป็นเจ้าของหรืออ่อนแอเมื่อเรียกตนเองในบล็อกปิดหรือไม่ หรือมีเวลาที่เราจะไม่เรียกคนอ่อนแอ / ไม่เป็นเจ้าของ? ถ้าเป็นเช่นนั้นคุณช่วยยกตัวอย่างให้เช่นกันได้ไหม?
ลูกา

ขอบคุณมาก.
Shawn Baek

1
มันทำให้ฉันมีความเข้าใจอย่างลึกซึ้งยิ่งขึ้นเกี่ยวกับ [ตัวตนอ่อนแอ] และ [ตัวตนที่ไม่ได้เป็นเจ้าของ] ขอบคุณมาก @ @
Tommy

มันเยี่ยมมาก จะทำอย่างไรถ้าฉันมีภาพเคลื่อนไหวที่ขึ้นอยู่กับการโต้ตอบของผู้ใช้ แต่ใช้เวลาสักครู่จึงจะเสร็จสิ้น จากนั้นผู้ใช้ย้ายไปที่ viewController อื่น ฉันเดาว่าในกรณีนี้ฉันควรจะใช้weakมากกว่าunownedใช่ไหม?
ฮั

67

ถ้าตัวเองอาจจะเป็นศูนย์ในการใช้งานปิด[อ่อนแอตนเอง]

ถ้าตัวเองไม่เคยจะเป็นศูนย์ในการใช้งานปิด[ไม่มีเจ้าของตัวเอง]

เอกสารแอปเปิ้ลสวิฟท์มีส่วนที่ดีกับภาพอธิบายความแตกต่างระหว่างการใช้ที่แข็งแกร่ง , อ่อนแอและไม่มีเจ้าของในการปิด:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html


50

นี่คือคำพูดที่ยอดเยี่ยมจากฟอรั่มนักพัฒนาของ Appleอธิบายรายละเอียดอร่อย:

unownedเทียบunowned(safe)กับunowned(unsafe)

unowned(safe)เป็นการอ้างอิงที่ไม่ใช่เจ้าของที่ยืนยันการเข้าถึงว่าวัตถุยังมีชีวิตอยู่ มันเป็นเหมือนการอ้างอิงทางเลือกที่อ่อนแอซึ่งไม่ได้แนบมากับx!ทุกครั้งที่เข้าถึง unowned(unsafe)เหมือน__unsafe_unretainedใน ARC - เป็นข้อมูลอ้างอิงที่ไม่ได้เป็นเจ้าของ แต่ไม่มีการตรวจสอบรันไทม์ว่าวัตถุยังมีชีวิตอยู่ในการเข้าถึงดังนั้นการอ้างอิงที่ห้อยต่องแต่งจะเข้าสู่หน่วยความจำขยะ unownedมักจะเป็นคำพ้องสำหรับunowned(safe)ขณะนี้ แต่ความตั้งใจก็คือว่ามันจะได้รับการเพิ่มประสิทธิภาพในการunowned(unsafe)ในการ-Ofast สร้างเมื่อตรวจสอบ runtime เป็นคนพิการ

unowned VS weak

unownedใช้งานง่ายกว่าweakจริงมาก วัตถุ Native Swift มีการนับการอ้างอิงสองครั้งและunowned การอ้างอิงการชนนับการอ้างอิงที่ไม่ได้เป็นเจ้าของแทน การนับการอ้างอิงที่คาดเดายาก วัตถุที่ถูก deinitialized เมื่อมันแข็งแรงจำนวนการอ้างอิงถึงศูนย์ แต่ก็ไม่ได้ deallocated จริงจนกว่าจะ ไม่มีเจ้าของจำนวนการอ้างอิงยังเหลือศูนย์ สิ่งนี้ทำให้หน่วยความจำถูกเก็บไว้อีกต่อไปเล็กน้อยเมื่อมีการอ้างอิงที่ไม่ได้เป็นเจ้าของ แต่มักจะไม่เกิดปัญหาเมื่อunowned ถูกใช้เนื่องจากวัตถุที่เกี่ยวข้องควรมีช่วงชีวิตที่ใกล้เคียงกันอยู่ตลอดเวลาและเป็นเรื่องที่ง่ายและเหนือกว่าค่าใช้จ่ายต่ำกว่าการใช้งานตารางข้างที่ใช้สำหรับการอ้างอิงศูนย์ที่อ่อนแอ

ปรับปรุง:ในปัจจุบันสวิฟท์weakภายในใช้กลไกเดียวกับunownedไม่ ดังนั้นการเปรียบเทียบนี้ไม่ถูกต้องเพราะมันเปรียบเทียบ Objective-C กับสวิฟท์weakunonwed

เหตุผล

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

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

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

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

ตื่นเต้นใช่มั้ย


38

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

แต่ไมค์แอชได้บันทึกไว้ว่า Swift ได้ปรับปรุงการใช้ vars ที่อ่อนแอเพื่อใช้กับโต๊ะข้าง ๆ อย่างไร

https://mikeash.com/pyblog/friday-qa-2017-09-22-swift-4-weak-references.html

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

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


ขอบคุณสำหรับการอัปเดตและสาธุในย่อหน้าสุดท้าย
คำขวัญ

1
ดังนั้นหลังจากการเปลี่ยนแปลงใหม่มีเวลาที่weakไม่สามารถใช้แทนunownedหรือไม่?
ฮั

4

อ้างอิงจากApple-doc

  • การอ้างอิงที่อ่อนแอนั้นเป็นประเภทที่เป็นทางเลือกเสมอและจะกลายเป็นศูนย์โดยอัตโนมัติเมื่ออินสแตนซ์ที่อ้างอิงถูกจัดสรรคืน

  • หากการอ้างอิงที่ถูกจับจะไม่กลายเป็นศูนย์มันควรจะถูกบันทึกเป็นข้อมูลอ้างอิงที่ไม่ได้เป็นเจ้าของเสมอแทนที่จะเป็นข้อมูลอ้างอิงที่อ่อนแอ

ตัวอย่าง -

    // if my response can nil use  [weak self]
      resource.request().onComplete { [weak self] response in
      guard let strongSelf = self else {
        return
      }
      let model = strongSelf.updateModel(response)
      strongSelf.updateUI(model)
     }

    // Only use [unowned self] unowned if guarantees that response never nil  
      resource.request().onComplete { [unowned self] response in
      let model = self.updateModel(response)
      self.updateUI(model)
     }

0

หากไม่มีข้อใดถูกต้อง

TL; DR

เช่นเดียวกับimplicitly unwrapped optionalหากคุณสามารถรับประกันได้ ว่าการอ้างอิงจะไม่เป็นศูนย์ ณ จุดใช้งานให้ใช้ unowned ถ้าไม่เช่นนั้นคุณควรใช้ความอ่อนแอ

คำอธิบาย:

ผมดึงมาดังต่อไปนี้ด้านล่างที่: การเชื่อมโยงที่ไม่มีเจ้าของที่อ่อนแอ จากสิ่งที่ฉันรวบรวมตัวเองที่ไม่มีชื่อไม่สามารถเป็นศูนย์ได้ แต่ตัวที่อ่อนแอสามารถเป็นตัวของตัวเองได้ หวังว่ามันจะช่วย

"การอ้างอิงที่ไม่เป็นที่รู้จักอ่อนแอและการอ้างอิงที่ไม่เป็นเจ้าของมีพฤติกรรมคล้ายกัน แต่ไม่เหมือนกัน"

การอ้างอิงที่ไม่มีเจ้าของเช่นการอ้างอิงที่อ่อนแอจะไม่เพิ่มจำนวนการเก็บรักษาของวัตถุที่ถูกอ้างอิง อย่างไรก็ตามใน Swift, การอ้างอิงที่ไม่มีเจ้าของมีเพิ่มประโยชน์ของการไม่เป็นตัวเลือก สิ่งนี้ทำให้ง่ายต่อการจัดการแทนที่จะหันไปใช้การรวมตัวเลือก สิ่งนี้ไม่เหมือนกับตัวเลือก Unwrapped นัยโดยปริยาย นอกจากนี้ในการอ้างอิงที่ไม่มีเจ้าของอยู่ไม่ใช่ปรับศูนย์เล็งปืน ซึ่งหมายความว่าเมื่อวัตถุถูกจัดสรรคืนมันจะไม่เป็นศูนย์ตัวชี้ ซึ่งหมายความว่าการใช้การอ้างอิงที่ไม่ได้เป็นเจ้าของในบางกรณีอาจนำไปสู่การพอยน์เตอร์ห้อยต่องแต่ง. สำหรับคุณที่ใกล้เคียงกับที่จำวันที่มีวัตถุประสงค์ -C อย่างที่ฉันทำแผนที่อ้างอิงที่ไม่ได้อ้างอิงกับการอ้างอิง unsafe_unretained

นี่คือสิ่งที่ทำให้สับสนเล็กน้อย

การอ้างอิงที่อ่อนแอและไม่เป็นเจ้าของทั้งสองจะไม่เพิ่มจำนวนการเก็บรักษาไว้

พวกเขาทั้งสองจะถูกนำมาใช้เพื่อทำลายวงจรรักษา แล้วเราจะใช้มันเมื่อไหร่!

ตามเอกสารของ Apple :

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


0
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "AnotherViewController")
        self.navigationController?.pushViewController(controller, animated: true)

    }

}



import UIKit
class AnotherViewController: UIViewController {

    var name : String!

    deinit {
        print("Deint AnotherViewController")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        print(CFGetRetainCount(self))

        /*
            When you test please comment out or vice versa

         */

//        // Should not use unowned here. Because unowned is used where not deallocated. or gurranted object alive. If you immediate click back button app will crash here. Though there will no retain cycles
//        clouser(string: "") { [unowned self] (boolValue)  in
//            self.name = "some"
//        }
//


//
//        // There will be a retain cycle. because viewcontroller has a strong refference to this clouser and as well as clouser (self.name) has a strong refferennce to the viewcontroller. Deint AnotherViewController will not print
//        clouser(string: "") { (boolValue)  in
//            self.name = "some"
//        }
//
//


//        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser (self.name) has a weak refferennce to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)
//
//        clouser(string: "") { [weak self] (boolValue)  in
//            self?.name = "some"
//        }


        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser nos refference to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)

        clouser(string: "") {  (boolValue)  in
            print("some")
            print(CFGetRetainCount(self))

        }

    }


    func clouser(string: String, completion: @escaping (Bool) -> ()) {
        // some heavy task
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            completion(true)
        }

    }

}

หากคุณไม่แน่ใจเกี่ยวกับการ [unowned self] ใช้งาน [weak self]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.