background

Yesterday, the third day of the year, at 11:30 in the evening, was suddenly knocked by my colleague Kim driver: “help me see this experiment, we also review together…”

Could this experiment go wrong? The company’s code review system is very perfect, and every line of code has to be reviewed. And my colleague even specially put this paragraph on the review meeting, seven or eight heads together to stare at. Can that be a problem?

But the data don’t lie: an experiment that was explicitly given to Chinese-speaking users was statistically flooded with American users.

Hamster: “From the code it looks absolutely fine.”

Colleague: “It may be true that there are many Chinese speakers in the United States. What a surprise!”

Hamster: “There must be something wrong with this, the United States is 4 times as many as China… That’s right, we can free the American empire…”

After watching it for more than two hours, I finally found the problem. It turned out to be the Swift pit. Let’s see how the code is written.

The problem

The offending code can be roughly simplified as follows:

class StaticVarTestClass {
  static var myStaticVar: Bool = {
    print("initializing static var!")
    return false
  }()
}

class SomeOtherClass {
    static func foo(myEnum: SomeEnum) {
        print("before!")
        switch myEnum {
            case a: 
                print("into case a!")
                print(StaticVarTestClass.myStaticVar)
            case b: break
        }
        print("after!"}} // when calledprint("call foo!")
SomeOtherClass.foo(.b)

Copy the code

What should be the output of this code?

research

To answer this question, you need to understand the initialization timing of static var. Swift official documentation states as follows:

Stored type properties are lazily initialized on their first access. They are guaranteed to be initialized only once, even when accessed by multiple threads simultaneously, and they do not need to be marked with the lazy modifier.

Static var = static var = static var = static var = static var = static var = static var = static var = static var = static var It also guarantees that even multithreaded access will only be initialized once (so it can be used as a singleton). As a side note, a non-static lazy var is not guaranteed to be initialized only once under multithreaded access.

Doesn’t that make it very clear? So from our code, when we call foo, we pass a.b, so we don’t get to the.a branch, we don’t get to myStaticVar, and we don’t trigger lazy loading. Therefore, the console output should be:

call foo!
before!
after!
Copy the code

In fact, the debug compilation output does look like this. However, the output from the release compilation was surprising:

call foo!
initializing static var!
before!
after!
Copy the code

Print (” Into case a!” ), the break point does not stop. Print (“initializing static var!” ), the breakpoint will be stopped, and follow up the call stack, can be found in the print (StaticVarTestClass. MyStaticVar) this way, although the actual execution of the code haven’t entered the case a this branch.

What is the case with lazy loading? But the results are in sight, and the amount of data collected online confirms the harsh reality: Static Var lazy loading is not all that reliable, and in fact, its initialization timing is uncertain. The “lazy loading” mentioned in the documentation can only be loosely interpreted to mean that it will not be fully loaded as soon as the app starts, so there is no need to worry about performance. But in our case, the actual path does not access the variable; I’m just calling foo, and it’s involved in that function. It may be a compilation optimization that prepares static var for possible use, which triggers the initialization of static var.

If I use the code provided above to write a demo, it is likely to find that such results can not be reproduced, I and Driver Jin respectively wrote the demo did not reproduce; But in our project, it is stable, while the actual project is very complicated, I don’t know which point triggered this problem. Static var can affect cold startup performance, but the business logic should not rely on lazy loading. It is possible to preload an app without accessing it.

digression

Hamster had already given up on the company’s recommendation award, but this year’s unexpected success, so the heart of earning extra money is ready to move; Let me end my article with a small advertisement: Airbnb Beijing office hires a large number of iOS and Android engineers this year.

Q: What are the requirements of the position?

A: If it is A mandatory requirement, it is more than 3 years of iOS/Android development experience. Then I think it is better to have experience in A large or medium-sized factory or graduated from A university. It is easier to pass the resume of either of the above two

Q: Are there any English requirements?

A: Zero requirement! As long as the code does not write pinyin…

Q: What does the interview cover?

A: The actual job is 90% SWIFT, but the interview is not required. What I particularly liked about the iOS interview was that there were no intellectual questions, like “What are the steps of messaging?”… From the telephone interview to the on-site interview, all links are written code on the computer, and the topics are all common functions in the development work, solve the actual bugs in the project, there is no partial no wonder things. We’ll look at development proficiency, code structure design, problem solving.

Q: What about the salary? Welfare?

A: I guess the salary can be at least as good as BAT’s, plus A lot of stock. The company has been talking for years about going public next year, but there is some hope that it will. Benefits: 15 days annual leave + one week Christmas leave; High-end medical insurance, special needs of the third grade a hospital, free access to the international department, the birth of a child seems to be all inclusive, the company directly pay; Three weeks training at the head office, and then there are plenty of business trips. You can also visit San Francisco. The rest is just like a normal big company.

Q: Is there any opportunity to transfer to headquarters?

A: There is A chance, but no guarantee.

Q: I’d like to sign up/can YOU recommend a friend?

A: Take A message from me. I will tell you your email address, and then send a resume (In Chinese) to me. If successful, I will not promise any electronic products, but transfer 10,000 RMB to you in cash. What do you want to buy

Any questions, hamster is willing to help answer ~ you can add my QQ group hamster hole: 546948320 friends in Beijing are also welcome to come to the office to play! Just make an appointment with me in advance