내에서는 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]를 사용하십시오 .
[소유하지 않은 자아] 를 사용할 때 충돌이 발생하면 해당 폐쇄의 어느 시점에서 자아가 없는 것으로 추측 할 수 있으므로 대신 [약한 자아] 를 사용해야 합니다.
나는 강한 사용에 대한 매뉴얼의 전체 섹션을 정말로 좋아했습니다. , 약한 , 그리고 소유되지 않은를 폐쇄에 :
참고 : 폐쇄 라는 용어를 사용했습니다. 새로운 스위프트 용어 인 블록 대신 .
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)
}