Is 2nd [weak self] ever required in a closure inside another closure? - ios

I always like to use [weak self], to prevent any potential memory leakage.
I was wondering, is 2nd [weak self] required, in a closure inside another closure? For instance
2 [weak self]
func takePhoto() {
AVCaptureDevice.requestAccess(for: AVMediaType.video) { [weak self] response in
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
Or, it is redundant to do so for the above case, and single [weak self] will be sufficient?
Single [weak self]
func takePhoto() {
AVCaptureDevice.requestAccess(for: AVMediaType.video) { [weak self] response in
DispatchQueue.main.async {
guard let self = self else { return }
May I know, which one is the most accurate approach?

Related

want to set a self var using guard statement

I have this code, where I'm trying to set a self variable (self?.users) from a view model call. The code snippet looks like this.
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.global().async { [weak self] in
self?.model?.findAll() { [weak self] users, exception in // network call
guard users != nil, self?.users = users else { // Optional type ()? cannot be used as a boolean; test for !=nil instead
}
}
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
}
I'm capturing [weak self] twice, is that okay?, can I capture it once as weak in the enclosing closure?
Should I use this instead of guard statement?
self?.model?.findAll() { [weak self] users, exception in
if exception != nil {
self?.users = users
}
}
DispatchQueue closures don't cause retain cycles so capture lists are not necessary.
Something like this, to avoid confusion I'd recommend to rename the incoming users and the code to reload the table view must be inside the closure
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.global().async {
self.model?.findAll() { [weak self] foundUsers, exception in // network call
guard let foundUsers = foundUsers else { return }
self?.users = foundUsers
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
}
}
And don’t forget to call super

swift - performSegue not working in RxSwift Observable subscribe

I have the following code:
loginViewModel.facebookLogin
.asObservable()
subscribe() { [unowned self] facebookLogin in
if let isLoggedIn = facebookLogin.element?.isLoggedIn {
if isLoggedIn {
elf.performSegue(withIdentifier: "toRestaurantSelect", sender: self)
}
}
if let didLoginFail = facebookLogin.element?.didLoginFail {
self.errorLabel.isHidden = !didLoginFail
}
}
.disposed(by: disposeBag)
The facebookLogin is a Variable and is updated when the user logs in. However, the performSegue is not called (the condition is true). Strangely enough, if I turn on Slow animations in the emulator the segue is executed. When Slow animations are turned off the segue doesn't execute (the Facebook login works). Any help is appreciated. Thanks!
i think you should use the main thread to make it work
loginViewModel.facebookLogin
.asObservable()
.subscribe() { [unowned self] facebookLogin in
if let isLoggedIn = facebookLogin.element?.isLoggedIn {
if isLoggedIn {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "toRestaurantSelect", sender: self)
}
}
}
if let didLoginFail = facebookLogin.element?.didLoginFail {
self.errorLabel.isHidden = !didLoginFail
}
}
.disposed(by: disposeBag)
Do the observation with the main scheduler:
loginViewModel.facebookLogin
.asObservable()
// Switch to the main scheduler
.observeOn(MainScheduler.instance)
subscribe() { [unowned self] facebookLogin in
if let isLoggedIn = facebookLogin.element?.isLoggedIn {
if isLoggedIn {
elf.performSegue(withIdentifier: "toRestaurantSelect", sender: self)
}
}
if let didLoginFail = facebookLogin.element?.didLoginFail {
self.errorLabel.isHidden = !didLoginFail
}
}
.disposed(by: disposeBag)

Correct memory management in closures

I have method with closure.
It works like this
func ping() -> pingProtocol {
let factory = pingFactory()
let ping = factory.getPing() // returns pingProtocol conforming instance, for example "PingService"
return ping
}
func performPing(success: #escaping () -> (), fail: #escaping () -> ()) {
ping().status { (ready, response) in
if ready {
success()
} else {
fail()
}
}
}
Realisation of ping is abstraction over Alamofire.
class PingService {
func status(completion: #escaping (Bool, ServiceResponse) -> Void) {
doSimpleRequest(endPoint: "/api/get_state/", param: [:], completion: completion)
}
func doSimpleRequest(endPoint: String, param: [String: Any], completion: #escaping (Bool, ServiceResponse) -> Void) {
APIManager.shared.postRequest(mode: APIMode.Service, endPoint: endPoint, parameters: param) { [weak self] (response, error) in
guard let strongSelf = self else {
return
}
guard let response = response as? [String: Any] else { return }
let serviceResponse = ServiceResponse(dict: response)
if error != nil {
completion(false, serviceResponse)
return
}
completion(true, serviceResponse)
}
}
}
The problem is that with weak self guard in self is always triggers. If I use unowned, I get crash. If I dont use weak or unowned it works fine.
The ping method itself lives in viewmodel of controller, and controller stays on screen when completion block is needed to be executed, so the problem is in deallocation of ping instance, not in viewmodel thats holds it.
If I use capture list I dont get desired behavior, but If I do I suspect that I get memory leak.
What is best practice here ?

Difference between weak self vs weak self()

What is the difference between passing [weak self] as an argument to a closure vs passing [weak self] ()
For example :
dispatch_async(dispatch_get_main_queue()) { [weak self] in
//Some code here
}
v/s
dispatch_async(dispatch_get_main_queue()) { [weak self] () -> Void in
//Some code here
}
You do not pass [weak self] () as an argument to a closure.
[weak self] is a capture list and precedes the
parameter list/return type declaration () -> Void
in the closure expression.
The return type or both parameter list and return type can be omitted if they can
be inferred from the context, so all these are valid
and fully equivalent:
dispatch_async(dispatch_get_main_queue()) { [weak self] () -> Void in
self?.doSomething()
}
dispatch_async(dispatch_get_main_queue()) { [weak self] () in
self?.doSomething()
}
dispatch_async(dispatch_get_main_queue()) { [weak self] in
self?.doSomething()
}
The closure takes an empty parameter list () and has a Void
return type.

Do I need [unowned self] or [weak self] in this closure?

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(netHex: 0xfc3158)
fadeBackground()
NSTimer.scheduledTimerWithTimeInterval(self.fadeTime, target: self, selector: Selector("fadeBackground"), userInfo: nil, repeats: true)
}
func fadeBackground(){
UIView.animateWithDuration(self.fadeTime, delay: 0, options: UIViewAnimationOptions.AllowUserInteraction, animations: {
var randomIndex = Int(arc4random_uniform(UInt32(CONSTANTS.MainColorScheme.count)))
self.view.backgroundColor = CONSTANTS.MainColorScheme[randomIndex]
}) { (stuff Bool) -> Void in
}
}
I'm a little confused about why I need to use [unowned self]. According to this answer, I should only use [unowned self] if I don't care that self is still around when the closure is called. But I never see why that would ever be the case. Why would I not care if self is around? I want self to be around when the closure is called -- that's why I wrote the code there.
Do I need unowned self in the animations closure?
In this case you don't need to use capture list, because both closures are UIView and not retained by self. The retain cycle is not created in your example.

Resources