[ios] 인수를 사용하여 스위프트 블록에서 약한 자체를 올바르게 처리하는 방법

내에서는 TextViewTableViewCell블록을 추적하는 변수와 블록이 전달되고 할당되는 구성 방법이 있습니다.
여기 내 TextViewTableViewCell수업이 있습니다.

//
//  TextViewTableViewCell.swift
//

import UIKit

class TextViewTableViewCell: UITableViewCell, UITextViewDelegate {

    @IBOutlet var textView : UITextView

    var onTextViewEditClosure : ((text : String) -> Void)?

    func configure(#text: String?, onTextEdit : ((text : String) -> Void)) {
        onTextViewEditClosure = onTextEdit
        textView.delegate = self
        textView.text = text
    }

    // #pragma mark - Text View Delegate

    func textViewDidEndEditing(textView: UITextView!) {
        if onTextViewEditClosure {
            onTextViewEditClosure!(text: textView.text)
        }
    }
}

내 메소드에서 configure 메소드를 사용할 때 cellForRowAtIndexPath전달하는 블록에서 weak self를 올바르게 사용하는 방법은
다음과 같습니다.

let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {(text: String) in
   // THIS SELF NEEDS TO BE WEAK
   self.body = text
})
cell = bodyCell

업데이트 : 사용하여 다음을 얻었습니다 [weak self].

let myCell = tableView.dequeueReusableCellWithIdentifier(textViewCellIdenfitier) as TextViewTableViewCell
myCell.configure(text: body, onTextEdit: {[weak self] (text: String) in
        if let strongSelf = self {
             strongSelf.body = text
        }
})
cell = myCell

내가 할 때 [unowned self]대신 [weak self]하고 꺼내 if문을 응용 프로그램이 충돌합니다. 이것이 어떻게 작동하는지에 대한 아이디어가 [unowned self]있습니까?



답변

클로저에 self 가 없을 경우 [weak self]를 사용하십시오 .

클로저에서 self 가 절대로없는 경우 [owned self]를 사용하십시오 .

[소유하지 않은 자아] 를 사용할 때 충돌이 발생하면 해당 폐쇄의 어느 시점에서 자아가 없는 것으로 추측 할 수 있으므로 대신 [약한 자아] 를 사용해야 합니다.

나는 강한 사용에 대한 매뉴얼의 전체 섹션을 정말로 좋아했습니다. , 약한 , 그리고 소유되지 않은를 폐쇄에 :

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

참고 : 폐쇄 라는 용어를 사용했습니다. 새로운 스위프트 용어 인 블록 대신 .

iOS에서 블록 (목표 C)과 클로저 (Swift)의 차이점


답변

넣어 [unowned self]전에 (text: String)...귀하의 폐쇄에. 이것을 캡처 목록 이라고하며 클로저에서 캡처 된 심볼에 소유권 명령을 배치합니다.


답변

** Swift 4.2 용으로 편집 :

@ Koen이 언급했듯이 swift 4.2는 다음을 허용합니다.

guard let self = self else {
   return // Could not get a strong reference for self :`(
}

// Now self is a strong reference
self.doSomething()

추신 : 나는 투표를하기 때문에 클로저 탈출 에 관한 독서를 추천하고 싶습니다. .


편집 : @ tim-vermeulen이 언급했듯이 Chris Lattner는 2016 년 1 월 22 일 금요일 19:51:29 CST에 말했다.이 트릭은 자체적으로 사용해서는 안되므로 사용하지 마십시오. 비 탈출 탈출 정보와 @gbk의 캡처 목록 답변을 확인하십시오. **

캡처 목록에서 [약한 자아]를 사용하는 사람들에게는 자아가 전혀 없을 수 있으므로 가장 먼저 가드 문으로 확인하십시오.

guard let `self` = self else {
   return
}
self.doSomething()

인용 부호가 무엇인지 궁금한 경우 self이름을 this , weakSelf 또는 무엇이든 변경할 필요없이 클로저 내부에서 자체를 사용하는 것이 좋습니다.


답변

캡처 목록 사용

캡처 목록 정의

캡처 목록의 각 항목은 클래스 인스턴스 (예 : self) 또는 일부 값으로 초기화 된 변수 (delegate = self.delegate!)에 대한 약하거나 소유되지 않은 키워드의 쌍입니다. 이 쌍은 쉼표로 구분 된 한 쌍의 대괄호 안에 작성됩니다.

캡처 목록을 클로저의 매개 변수 목록 앞에 놓고 제공된 경우 반환 유형 :

lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // closure body goes here
} 

클로저가 컨텍스트에서 유추 될 수 있으므로 매개 변수 목록 또는 리턴 유형을 지정하지 않은 경우 캡처 목록을 클로저의 맨 처음에 배치 한 후 in 키워드를 배치하십시오.

lazy var someClosure: Void -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // closure body goes here
}

추가 설명


답변

편집 : LightMan의 업데이트 된 솔루션에 대한 참조

LightMan의 솔루션을 참조하십시오 . 지금까지 나는 사용하고 있었다 :

input.action = { [weak self] value in
    guard let this = self else { return }
    this.someCall(value) // 'this' isn't nil
}

또는:

input.action = { [weak self] value in
    self?.someCall(value) // call is done if self isn't nil
}

일반적으로 유추 된 경우 매개 변수 유형을 지정할 필요가 없습니다.

매개 변수가 없거나 $0클로저에서 참조하는 경우 매개 변수를 모두 생략 할 수 있습니다 .

input.action = { [weak self] in
    self?.someCall($0) // call is done if self isn't nil
}

완전성을 위해; 클로저를 함수에 전달하고 매개 변수가 아닌 @escaping경우 다음이 필요하지 않습니다 weak self.

[1,2,3,4,5].forEach { self.someCall($0) }


답변

신속한 4.2 ? 기준으로 다음을 수행 할 수 있습니다.

_ = { [weak self] value in
    guard let self = self else { return }
    print(self) //? will never be nil
}()


답변

스위프트 4.2

let closure = { [weak self] (_ parameter:Int) in
    guard let self = self else { return }

    self.method(parameter)
}

https://github.com/apple/swift-evolution/blob/master/proposals/0079-upgrade-self-from-weak-to-strong.md