我注意到在 Swift 2.2 中,使用 @noescape 标记为非转义的闭包不需要显式的 self。在 Swift 3 中,默认情况下所有闭包都是非转义的,现在如果您希望它们能够转义,则需要使用 @escaping 标记它们。
鉴于默认情况下 Swift 3 中的所有闭包都是非转义的,为什么它们需要显式的 self?
final class SomeViewController: NSViewController {
var someClosure: () -> () = { _ in }
override func viewDidLoad() {
super.viewDidLoad()
someClosure = {
view.layer = CALayer() // ERROR: Implicit use of `self` in closure; use `self.` to make capture semantics explicit
}
}
}
最佳答案
In Swift 3, all closures are non-escaping by default
不,在 Swift 3 中,只有闭包函数参数(即本身就是函数的函数输入)在默认情况下是非转义的(根据 SE-0103 )。例如:
class A {
let n = 5
var bar : () -> Void = {}
func foo(_ closure: () -> Void) {
bar = closure // As closure is non-escaping, it is illegal to store it.
}
func baz() {
foo {
// no explict 'self.' required in order to capture n,
// as foo's closure argument is non-escaping,
// therefore n is guaranteed to only be captured for the lifetime of foo(_:)
print(n)
}
}
}
作为closure在上面的例子中是非转义的,禁止被存储或捕获,从而将其生命周期限制为函数的生命周期 foo(_:) .因此,这意味着它捕获的任何值都保证在函数退出后不会保持捕获状态——这意味着您无需担心捕获时可能发生的问题,例如保留周期。
但是,闭包存储的属性(例如上例中的 bar)根据定义转义(用 @noescape 标记它是荒谬的)作为其生命周期 不 限于给定的函数——只要给定的实例保留在内存中,它(以及因此捕获的所有变量)就会保留在内存中。因此,这很容易导致诸如保留循环之类的问题,这就是为什么您需要使用显式 self. 的原因。为了使捕获语义明确。
事实上,举例来说,您的示例代码将在 viewDidLoad() 上创建一个保留周期。被称为someClosure强烈捕获 self , 和 self强烈引用someClosure ,因为它是一个存储属性。
值得注意的是,作为“存储函数属性总是转义”规则的扩展,存储在聚合中的函数(即具有关联值的结构和枚举)也总是转义,因为对您的操作没有任何限制聚合体。作为pointed out by pandaren codemaster ,这个当前包括Optional – 意思是 Optional<() -> Void> (又名 (() -> Void)? )总是在转义。不过,编译器最终可能会将其作为函数参数的特例,因为可选的已经建立在很多编译器的魔法之上。
当然,您希望能够使用 @noescape 的地方attribute 在闭包上,闭包是函数中的局部变量。这样的闭包将具有可预测的生命周期,只要它不存储在函数外部或被捕获。例如:
class A {
let n = 5
func foo() {
let f : @noescape () -> Void = {
print(n)
}
f()
}
}
不幸的是,作为@noescape在 Swift 3 中被删除,这是不可能的(有趣的是,在 Xcode 8 GM 中,这是可能的,但会产生弃用警告)。作为Jon Shier says ,我们将不得不等待它被重新添加到语言中,这可能发生也可能不会发生。
关于swift - 为什么闭包在 Swift 3 中默认都是非转义的而需要显式的 `self`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39433221/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?