闭包不能隐式捕获一个变异的自参数 [英] Closure cannot implicitly capture a mutating self parameter

查看:508
本文介绍了闭包不能隐式捕获一个变异的自参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Firebase观察事件,然后在完成处理程序中设置图像

  FirebaseRef.observeSingleEvent(of:.value ,如下:{(snapshot)in 
if _ = snapshot.value as?NSNull {
self.img = UIImage(named:Some-image)!
} else {
self.img = UIImage(命名为some-other-image)!
}
})

然而,我得到这个错误


Closure不能隐式捕获一个变异的自我参数


我不确定这个错误是什么,寻找解决方案并没有帮助

observeSingleEvent(of:with:)最有可能是一个值类型(一个 struct ?),在这种情况下,变异的上下文可能不会明确地捕获 @escaping 闭包中。

简单的解决方案是将拥有的类型更新为引用一次( class )。






版本



的方法,您可以使用以下方法来查看FireShell脚本:声明如下:
$ b


  func observeSingleEvent(eventType:FIRDataEventType,
with block :@escaping(FIRDataSnapshot) - >无效)


block 闭包被标记为 @escaping 参数属性,这意味着它可以转义它的函数体,甚至 self的生命期(在你的上下文中)。使用这些知识,我们构建了一个更简单的例子,我们可以分析:

$ $ p $ struct $ F $ {b $ b private func bar( (){block()}>()){block()}

mutating func bax(){
bar {print(self)} // this closure may outlive' self'
/ * error:closure不能隐式地捕获
变异的自参数* /
}
}



现在,错误信息变得更加明显,我们转向Swift 3中实现的以下演变提议:



说明[强调我的]:


捕获 inout 参数,包括 self 在一个mutatin中g
方法
,在可变的闭包文字中变成了一个错误,除非
捕获是明确的
(从而是不可变的)。 b

现在,这是一个关键点。对于类型(例如 struct ),我认为对于拥有在你的例子中,observeSingleEvent(...),这样的显式捕获是不可能的,afaik(因为我们正在使用一个值类型,而不是一个引用)。

这个问题最简单的解决方法是使类型拥有 observeSingleEvent(...)引用类型,例如一个 class ,而不是一个 struct

<$ p $ ($)$ {
init(){}
private func bar(with block:@escaping() - >()){block()}

func bax(){
bar {print(self)}
}
}

请注意,这将通过强引用捕获 self ;取决于你的上下文(我自己并没有使用Firebase,所以我不知道),你可能希望明确地捕获 self ,例如

  FirebaseRef.observeSingleEvent(of:.value,与:{[weak self](snapshot)in ... 


I am using Firebase to observe event and then setting an image inside completion handler

FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
        if let _ = snapshot.value as? NSNull {
            self.img = UIImage(named:"Some-image")!
        } else {
            self.img = UIImage(named: "some-other-image")!
        }
})

However I am getting this error

Closure cannot implicitly capture a mutating self parameter

I am not sure what this error is about and searching for solutions hasn't helped

解决方案

The short version

The type owning your call to FirebaseRef.observeSingleEvent(of:with:) is most likely a value type (a struct?), in which case a mutating context may not explicitly capture self in an @escaping closure.

The simple solution is to update your owning type to a reference once (class).


The longer version

The observeSingleEvent(of:with:) method of Firebase is declared as follows

func observeSingleEvent(of eventType: FIRDataEventType, 
     with block: @escaping (FIRDataSnapshot) -> Void)

The block closure is marked with the @escaping parameter attribute, which means it may escape the body of its function, and even the lifetime of self (in your context). Using this knowledge, we construct a more minimal example which we may analyze:

struct Foo {
    private func bar(with block: @escaping () -> ()) { block() }

    mutating func bax() {
        bar { print(self) } // this closure may outlive 'self'
        /* error: closure cannot implicitly capture a 
                  mutating self parameter              */
    }
}

Now, the error message becomes more telling, and we turn to the following evolution proposal was implemented in Swift 3:

Stating [emphasis mine]:

Capturing an inout parameter, including self in a mutating method, becomes an error in an escapable closure literal, unless the capture is made explicit (and thereby immutable).

Now, this is a key point. For a value type (e.g. struct), which I believe is also the case for the type that owns the call to observeSingleEvent(...) in your example, such an explicit capture is not possible, afaik (since we are working with a value type, and not a reference one).

The simplest solution to this issue would be making the type owning the observeSingleEvent(...) a reference type, e.g. a class, rather than a struct:

class Foo {
    init() {}
    private func bar(with block: @escaping () -> ()) { block() }

    func bax() {
        bar { print(self) }
    }
}

Just beware that this will capture self by a strong reference; depending on your context (I haven't used Firebase myself, so I wouldn't know), you might want to explicitly capture self weakly, e.g.

FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...

这篇关于闭包不能隐式捕获一个变异的自参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆