Weak Strong Dance and swiftweak in Swift

Source: Internet
Author: User
Tags usleep

Weak Strong Dance and swiftweak in Swift

Dear bloggers who are interested in blog posts, I am sorry to tell you a very unfortunate message,

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

Because the post will only be published here/

The layout of the new blog is better, and the reading experience is better. You are welcome to vomit, leave a message, and subscribe.

 

 

 

I'm about to celebrate the new year again. You can no longer be as shameless as you did at the beginning (in our Guangdong dialect, we mean red packets)

Figure 1

Figure 2

It seems that this year has no benefits.

Who made brother already work.

This year, the company's development tasks have been completed, and Apple has never been held responsible for Christmas, so we should be idle in the last half month.

The bloggers refer to Swift, which has been raised to 2.1 and is also open-source. In this case, Swift is also fat enough, and the syntax will never be changed, it's time to start again.

Why? In fact, in the First Swift Beta version, our project manager tried palyground and it was awesome. "Let's use Swift to develop the next project ", then there is Swift1.0... 2.0. Every update, every syntax change, and every time XCode was opened, it was filled with red. The shocking scenes made the bloggers suffer countless times. Fortunately, this project is dead, oh yeah!

Well, let's pick up Swift again. Today's article is a masterpiece of passionate translation, and my English level has been fully affirmed by the original author:

Figure 3

See it. There is no obstacle to communication !! We had a pleasant chat for a long time ~~ , Passionate, biu ~

Let's go back to the blog topic. This time we will talk about "Weak/Strong Dance"

Solve the 2011 WWDC Session to be pursued by loop reference in block #322 the amazing code at that time was as follows:

- (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];  }];}

You can also see that AFNetWorking uses block as follows:

__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 familiar with "weak/strong dance" in Objective-C, But I suddenly want to know what to do in Swift? Is there a legendary best practice?

Now, start translating!

Original

First, we provide an example of circular references caused by references that do not use weak in the closure.

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 giant base and obvious circular reference. self-> block-> self

So,deinitThe method is never executed, even if youcPoint againnilOr other instances,cIt will not be destroyed. This is a stubborn and naughty loop reference, especially when youcPointnilAfter that, you can no longer reference this object, and it will quietly lie in the heap memory, leaving the world independent, and then you will leak the heap memory, then you may feel a little sad from the lower body ~ ~ No.

In fact, the parameter List (Capture List) of the closure in Swift can be used to obtainweak selfTo avoid circular references, but this does not meet our requirements, onlyweakIs not a "weak/strong dance" drop.

Use closure parameter list
Class C {let name: String var block: ()-> Void )? Init (name: String) {self. name = name block = {[weak self] in // <-- Here are some changes to 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

Use[weak self]There is a detail, that isselfIn the closureOptionalFrom the code aboveself?.doSomething()We can see that.

But if you use it in this closureself?(Multiple Useself?), The problem arises, becauseself?Is a weak reference, so you cannot determine allself?All operations can be completed. After all, if the referencedselfYou may get down at any time, and then raise an angry question:

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

Note: of course, in generaldispatch_async()You do not have to worry about circular references, because self does not holddispatch_async()So the above Code does not really lead to circular references. If your closure does not pay much attention to the results, thenselfIsnilThe closure won't be executed any more. This is quite useful.

The above code is not printedafter sleepBecauseself?This sentence has been suspended before being printed.

This kind of rootless bug can usually make you half-dead. So we usually encounter multiple trials in this closure.self?Usuallyself?Become thick and strongstrong self, (The blogger is also thick and strong, covering his face ~~) This is the legendary "weak/strong dance". Why is this dance called dance?The US team lifted the banNot bad. The U. S. Team Leader in the women's federation is also ledweakChangestrongAh ~, Well, it's too far away, and the chrysanthemums all hurt. We are doing technical translation! Be serious! Respect the original author! Let's call it dance. With this dance, we can ensure that once the closure is executed,selfNotnil.

However, as mentioned at the beginning of the articleSwiftI am not very sure about the best practices for changing back to strong in weak/strong dance...

Obtain strong references. Use optional binding. if let
Func doClosure () {dispatch_async (dispatch_get_global_queue (0, 0) {[weak self] in if let strongSelf = self {// <-- here is the essence of 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} // <-- this is the essence of strongSelf. log ("before sleep") usleep (500) strongSelf. log ("after sleep ")}

Output

before sleepafter sleepDestroying C

Advantages:

  • It is obvious that the entire operation process
  • Non-optional local variables are obtained in the closure.

Disadvantages:

  • Unfortunately, we cannotif let self = selfBecauseselfIs a constant, not variable, so we can onlyif let strongSelf = selfUse ugly in the scope of the ClosurestrongSelf.
  • In the closure of swift, if you haven't tried itstrongSelfInsteadselfIn this way, the compiler will warn! Because at this timeselfIt is optional. Compared with OC, no warning will be given. (I read this sentence 21 times. Why do I think this is not a disadvantage)
Use withExtendedLifetime

There is a function in the Swift Standard Library:withExtendedLifetime()It feels like the goldfish like Apple has intentionally 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

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:

  • No longer need to use uglystrongSelfNow

Disadvantages:

  • selfOr is it his mother's choice? Is it necessary to call a method or something !?, The blogger suddenly remembered one of his skills: one-handed solution.
Customize withExtendedLifetime()

This method is thought by @ jtbandes, which is 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. (original) feel no advantages ~

Disadvantages:

  • strongSelfChanged to use$0The blogger thinks, oh, it's still ugly, and the readability is worse.
  • In this case, I had to add some extra type info todispatch_async()Closure. I'm not totally sure why. I don't know what he said ~

Translation is now complete

Postscript

For the Weak section in Swift "Weak/Strong Dance", you can refer to Meida's article memory management,WeakAndUnowned.

I have been using Swift for more than a week. Although Xcode is writing Swift just like a plain text editor, I still want to say: Swift is true.™Safe! It's hard to think about crash.

And Happy Christmas!

Close the pen and leave.

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.