Weak strong Dance in Swift

Source: Internet
Author: User
Tags usleep blog layout

Dear Blog Park's attention to Bo main article friends tell you a very unfortunate news oh,

This article will be the blogger in the blog Park published the last article,

Because after the article blogger will only be posted here Oh http://daiweilai.github.io/

New Blog layout better, reading experience better, welcome to vomit Groove, message, subscribe yo

Soon again the new year, eh, can no longer like the original Shameless tease is (we Guangdong dialect for red envelopes meaning)

Figure 1

Figure 2

Looks like it's out of this year.

Who let brother already work?

The company's development mission this year is finished, and Apple is very hǎo (yàng) (DE) Let the Christmas do not review, so this half a month should be idle.

Bo Master pinch refers to a calculation, Swift has been raised to 2.1, and also open source, so it seems that Swift is also fat enough, grammar will never have big changes, it is time to catch up again.

Why, in fact, at the time of the Swift Beta, our project manager tried out Palyground, clapped, Bang Bang, "we use Swift to develop the next project," then Swift1.0 ... 2.0, every upgrade, every grammar change, every time Xcode opened the moment is Azolla, that shocking scenes countless times let Bo master tortured. Finally, fortunately, this project is dead, oh yes!

OK, pick up the swift again, today's article is a Passion translation masterpiece, and my English level has been fully affirmed by the original author:

Figure 3

See, no obstacles to communication!! We chatted happily for a long time ~, passionate, Biu biu ~

Okay, back to the subject of the blog post, this time we're talking about "Weak/strong Dance."

Resolving circular references in block search for the WWDC Session #322 The amazing code is like this:

- (void)dealloc{  [[NSNotificationCenter defaultCenter] removeObserver:_observer];}- (void)loadView{  [super loadView];  __weak TestViewController *wself = self;  _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"                                                                object:nil                                                                 queue:nil                                                            usingBlock:^(NSNotification *note) {      TestViewController *sself = wself;      [sself dismissModalViewControllerAnimated:YES];  }];}

Or you can see how afnetworking is using block:

__weak __typeof(self)weakSelf = self;AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {__strong __typeof(weakSelf)strongSelf = weakSelf;strongSelf.networkReachabilityStatus = status;if (strongSelf.networkReachabilityStatusBlock) {strongSelf.networkReachabilityStatusBlock(status);}};

We are all very familiar with the "Weak/strong Dance" in objective-c, but I suddenly want to know how to do it in the swift language. Is there a legendary best practice?

All right, translation begins!

Original

First, let's give an example of a circular reference that is caused by a reference in a closure that does not use weak.

class C {    let name: String    var block: (() -> Void)?    init(name: String) {        self.name = name        block = {            self.doSomething()        }    }    deinit { print("Destroying \(name)") }    func doSomething() { print("Doing something for \(name)") }}var c = C(name: "one")print(c.name)c = C(name: "two")print(c.name)

Output

onetwo

This is an example of a huge base and obvious circular reference, self--block->self

So, the deinit method is absolutely not enforced, even if you put the c re-pointing nil or other instances, c will not be destroyed, this is stubborn and naughty circular reference, especially when you c point to the nil object, you can no longer quote, It lies quietly in the heap of memory, leaving the world and independent, and then you will be a heap of memory leaks, and then you faint sadness from the lower body came ~ ~ No Then

In fact, the list of parameters of the closure in Swift (Capture list) has been able to get you weak self to avoid circular references, but it does not reach our requirements, only the weak construction of "Weak/strong Dance" drops.

Using the closure parameter list
class C {    let name: String    var block: (() -> Void)?    init(name: String) {        self.name = name        block = { [weak self] in  // <-- 这里做出一些改变            self?.doSomething()        }    }    deinit { print("Destroying \(name)") }    func doSomething() { print("Doing something for \(name)") }}var c = C(name: "one")print(c.name)c = C(name: "two")print(c.name)

Output

oneDestroying onetwo

So there is no circular reference ~

Use in closures self

The use [weak self] of a detail, that is self in the closure will become Optional from the above code self?.doSomething() can be seen.

But if you use it in this closure self? (multiple use), the problem is, self? because this self? is a weak reference, then you cannot be sure that all the operations in this closure self? can be done, after all, if the reference self may be hung at any time, Then he raised a chestnut with rage:

Figure 4

class C {    deinit { println("Destroying C") }    func log(msg: String) { println(msg) }    func doClosure() {        dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in            self?.log("before sleep")            usleep(500)            self?.log("after sleep")        }    }}var c: C? = C()  // Optional, so we can set it to nilc?.doClosure()dispatch_async(dispatch_get_global_queue(0, 0)) {    usleep(100)    c = nil  // This will dealloc c}dispatch_main()

Output

before sleepDestroying C

Tip: Of course, in general dispatch_async() you don't have to worry about having a circular reference, because self does not hold dispatch_async() a block, so the above code does not really cause a circular reference, and if your closure is not very results-oriented, then the self closure will not be nil executed, This is still very useful.

The code above does not print after sleep , because self? it has been hung up before printing this sentence.

Usually this root-free bug can turn you half to death. So often encountered in this closure of the trial self? operation of the times, generally will turn self? into thick and strong strong self , (Bo is also thick and strong, cover face ~ ~) This is the legendary "Weak/strong Dance", this dance, the amount, what ghost, Why this technology is called dance Ah, I think is called 美队解禁奥义技 still good, the United States Women's Federation inside the captain of the U.S. is also from weak strong the ~, well, pull too far, chrysanthemum is painful, we are in the technical translation! Be serious! Be respectful to the original author! Let's call dance, after this dance, we can make sure that once the closure is executed, it will not be self nil .

But, as I said at the beginning of the article, what's the Swift best practice for getting back to strong in the "Weak/strong dance" I'm not sure ...

Get some ideas for strong references use optional bindings if let
func doClosure() {    dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in        if let strongSelf = self {  // <-- 这里就是精髓了            strongSelf.log("before sleep")            usleep(500)            strongSelf.log("after sleep")        }    }}// or in Swift 2, using `guard let`:dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in    guard let strongSelf = self else { return }  // <-- 这里就是精髓了    strongSelf.log("before sleep")    usleep(500)    strongSelf.log("after sleep")}

Output

before sleepafter sleepDestroying C

Advantages:

    • It's obvious that the whole process of operation
    • I got a non-optional local variable in the closure.

Disadvantages:

    • Unfortunately we cannot if let self = self , because self it is constant, immutable, so that we can only in the scope of the if let strongSelf = self closure to use the ugly strongSelf .
    • In Swift's closure, if you have not tried it strongSelf , use it self so the compiler warns you! Because this time self is optional, compared to OC, will not be warned. (This sentence has been read 21 times, why do you think this is not a disadvantage?)
Use withExtendedLifetime

There is a function in Swift's standard library: It withExtendedLifetime() feels like Apple, the goldfish, deliberately induced us to use this function to implement "Weak/strong dance".

/// Evaluate `f()` and return its result, ensuring that `x` is not/// destroyed before f returns.func withExtendedLifetime<T, Result>(x: T, @noescape _ f: () -> Result) -> Result

Then try it.

func doClosure() {    dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] in        withExtendedLifetime(self) {            self!.log("before sleep")            usleep(500)            self!.log("after sleep")        }    }}

Advantages:

    • There's no need to use ugly in closures strongSelf .

Disadvantages:

    • selfOr a damn choice, call the method or something!? , or to unpack, Bo Master suddenly think of one of his skills: one-handed solution, hehe
Customize a withExtendedLifetime()

This is the way @jtbandes this guy thinks, probably like this:

 extension Optional {    func withExtendedLifetime(body: Wrapped -> Void) {        if let strongSelf = self {            body(strongSelf)        }    }}// Then:func doClosure() {    dispatch_async(dispatch_get_global_queue(0, 0)) { [weak self] () -> Void in        self.withExtendedLifetime {            $0.log("before sleep")            usleep(500)            $0.log("after sleep")        }        return    }}

Advantages:

    • Follows naming conventions set by the standard library. Feel no Merit ~

Disadvantages:

    • strongSelfBecome used $0 , bloggers think Oh, still ugly, and less readable
    • In this case, I had to add some extra type info to the dispatch_async() closure. I ' m not totally sure why. I don't know what the hell he said.

The translation is over.

Postscript

For Swift's "Weak/strong Dance", in the Weak section, you can refer to this article on Meow for memory management,Weak and unowned .

It's been a lot of sense to use swift back for more than a week, although Xcode is writing swift like a plain text editor, but I'd like to say: Swift is safe! It's hard to crash.

and Happy christmas!.

Collect your pen and leave.

Weak strong Dance in Swift

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.