在我的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)
}
}
}
当我在cellForRowAtIndexPath
方法中使用configure方法时,如何在我传入的块中正确使用弱自我。
这是我没有弱自我的原因:
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]
?
答案 0 :(得分:173)
如果 self 在闭包中可能为零,请使用 [弱自我] 。
如果 self 永远不会在闭包中使用 [无主自我] 。
如果你在使用 [无主自我] 时崩溃了,我猜在封闭的某个时刻自我是零,这就是为什么你必须选择 [弱自我] < / strong>相反。
我真的很喜欢手册中关于在闭包中使用强,弱和无主的整个部分:
注意:我使用了术语闭包而不是阻止这是更新的Swift术语:
Difference between block (Objective C) and closure (Swift) in ios
答案 1 :(得分:30)
将[unowned self]
放在(text: String)...
之前。这称为捕获列表,并将所有权说明放在闭包中捕获的符号上。
答案 2 :(得分:26)
**为Swift 4.2编辑:
正如@Koen评论的那样,swift 4.2允许:
Bitmap bwBitmap = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565 );
float[] hsv = new float[ 3 ];
for( int col = 0; col < bitmap.getWidth(); col++ ) {
for( int row = 0; row < bitmap.getHeight(); row++ ) {
Color.colorToHSV( bitmap.getPixel( col, row ), hsv );
if( hsv[ 2 ] > 0.5f ) {
bwBitmap.setPixel( col, row, 0xffffffff );
} else {
bwBitmap.setPixel( col, row, 0xff000000 );
}
}
}
return bwBitmap;
P.S。:由于我有一些上升票,我想建议阅读escaping closures。
编辑:正如@ tim-vermeulen评论的那样,Chris Lattner在2016年1月22日星期五19:51:29 CST表示,这个技巧不应该用于自我,所以请不要使用它。检查@gbk中的非转义闭包信息和捕获列表答案。**
对于那些在捕获列表中使用[弱自我]的人,请注意self可能是nil,所以我要做的第一件事就是用一个保护声明检查
guard let self = self else {
return // Could not get a strong reference for self :`(
}
// Now self is a strong reference
self.doSomething()
如果您想知道guard let `self` = self else {
return
}
self.doSomething()
周围的引号是什么,那么在封闭内部使用self是一个专业技巧,而无需将名称更改为 this , weakSelf 或其他什么。
答案 3 :(得分:25)
定义捕获列表
捕获列表中的每个项目都是弱者或无人物的配对 带有对类实例(如self)或a的引用的关键字 用一些值初始化的变量(例如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
}
答案 4 :(得分:23)
编辑:参考LightMan的更新解决方案
见LightMan's solution。到现在为止我一直在使用:
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) }
答案 5 :(得分:7)
_ = { [weak self] value in
guard let self = self else { return }
print(self) // will never be nil
}()
答案 6 :(得分:7)
Swift 4.2
holder.tvIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("search_engines");
intent.putExtra("url", url);
int PreviousSelectedItem = selectedItem;
selectedItem = i;
// Set the static value in the MainActivity
// This can be accessed from all other classes
MainActivity.selectedItem = i;
intent.putExtra("selected", selectedItem);
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
notifyItemChanged(PreviousSelectedItem);
notifyDataSetChanged();
}
});
答案 7 :(得分:3)
您可以在块的参数之前在捕获列表中使用[weak self]或[unowned self]。捕获列表是可选语法。
[unowned self]
在这里运作良好,因为单元格永远不会是零。否则,您可以使用[weak self]
答案 8 :(得分:0)
如果你崩溃了,你可能需要[弱自我]
我的猜测是你正在创建的块仍以某种方式连接起来。
创建一个prepareForReuse并尝试清除其中的onTextViewEditClosure块。
func prepareForResuse() {
onTextViewEditClosure = nil
textView.delegate = nil
}
看看是否可以防止崩溃。 (这只是猜测)。
答案 9 :(得分:0)
[Closure and strong reference cycles]
您知道,Swift的闭包可以捕获实例。这意味着您可以在闭包内部使用self
。特别是escaping closure
[About]可以创建一个strong reference cycle
。顺便说一下,您必须在self
中明确使用escaping closure
。
快速闭包具有Capture List
功能,由于您对捕获的实例没有强大的引用,因此可以避免这种情况并中断引用循环。捕获列表元素是一对weak
/ unowned
和对类或变量的引用。
例如
class A {
private var completionHandler: (() -> Void)!
private var completionHandler2: ((String) -> Bool)!
func nonescapingClosure(completionHandler: () -> Void) {
print("Hello World")
}
func escapingClosure(completionHandler: @escaping () -> Void) {
self.completionHandler = completionHandler
}
func escapingClosureWithPArameter(completionHandler: @escaping (String) -> Bool) {
self.completionHandler2 = completionHandler
}
}
class B {
var variable = "Var"
func foo() {
let a = A()
//nonescapingClosure
a.nonescapingClosure {
variable = "nonescapingClosure"
}
//escapingClosure
//strong reference cycle
a.escapingClosure {
self.variable = "escapingClosure"
}
//Capture List - [weak self]
a.escapingClosure {[weak self] in
self?.variable = "escapingClosure"
}
//Capture List - [unowned self]
a.escapingClosure {[unowned self] in
self.variable = "escapingClosure"
}
//escapingClosureWithPArameter
a.escapingClosureWithPArameter { [weak self] (str) -> Bool in
self?.variable = "escapingClosureWithPArameter"
return true
}
}
}
weak
-更可取的是,在可能 unowned
-在确保实例所有者的生存期大于闭包期限时使用它答案 10 :(得分:0)
从 Swift 5.3
开始,如果在闭包中的 self
之前传递 [self]
,则不必在闭包中解包 in
。
在this swift doc中引用someFunctionWithEscapingClosure { [self] in x = 100 }