[IOS] Swift beginner's Manual: optional type (Optionals)

Source: Internet
Author: User

[IOS] Swift beginner's Manual: optional type (Optionals)

 

A few weeks ago (Translator's note: the original article was published in June 24), Apple released a brand new programming language: Swift. Since then, I have been reading the official Swift manual and reading the Xcode6 betaPlayingLearning. I began to like Swift's conciseness and syntax. I learned this brand new language with my team and compared it with the Objective-C old guy with 30 years of history. At the same time, we are also trying to explore how to make it easy for beginners to master Swift.

Two weeks ago, we released the basic Swift tutorial. In the next few weeks, we will write a series of tutorials to introduce the new features of Swift. This week, let's look at the optional type (Optionals ).

Overview

In the previous tutorial, I mentioned the concept of the optional type, but I did not explain it in detail.

So what is an optional type?

In Swift, when we declare a variable, it is non-optional by default, that is, you must specify a value not nil. If you want to set a non-optional variable to nil, the compiler will tell you: "Hey, you can't set it to nil ". That's right:

var message: String = Swift is awesome! // OKmessage = nil // compile-time error

Of course, the error message provided by the compiler is not so friendly.Could not find an overload for ‘__conversion’ that accepts the supplied argumentsThis error occurs. Similarly, the variables declared in the class are optional by default:

class Messenger {    var message1: String = Swift is awesome! // OK    var message2: String // compile-time error}

Inmessage2You will get a compilation error because it has no initial value. It may be surprising to those friends who are coming along the way from Objective-C. In Objective-C, this is not a problem at all:

NSString *message = @Objective-C will never die!;message = nil;class Messenger {    NSString *message1 = @Objective will never die!;    NSString *message2;}

However, you can declare an uninitialized variable in Swift. Swift provides an optional type to indicate no value. You only need to add a question mark after the declared type?You can:

class Messenger {    var message1: String = Swift is awesome! // OK    var message2: String? // OK}

You can also assign values to optional types of variables. If no value is assigned, the value is automatically set to nil.

Reason

Why is it designed like this? Apple officially explained that Swift is a secure language. As shown in the preceding example, the optional types of Swift are compiled to prevent some common runtime errors. Let's take a look at the example below for better understanding.

For example, the following code is available in Objective-C:

- (NSString *)findStockCode:(NSString *)company {    if ([company isEqualToString:@Apple]) {        return @AAPL;    } else if ([company isEqualToString:@Google]) {        return @GOOG;    }    return nil;}

In the above method, you can usefindStockCodeMethod to obtain the stock code. Obviously, only Apple and Google queries will return the value, and nil will be returned in other cases.

Suppose we will call this method in the following code:

NSString *stockCode = [self findStockCode:@Facebook]; // nil is returnedNSString *text = @Stock Code - ;NSString *message = [text stringByAppendingString:stockCode]; // runtime errorNSLog(@%@, message);

This Code does not have any problems during compilation, But if you enter Facbook, nil will be returned, resulting in a runtime error.

In Swift, errors are not required during running. Swift will prompt an error message during compilation. We can rewrite the above Code in Swift:

func findStockCode(company: String) -> String? {   if (company == Apple) {      return AAPL   } else if (company == Google) {      return GOOG   }   return nil}var stockCode:String? = findStockCode(Facebook)let text = Stock Code - let message = text + stockCode  // compile-time errorprintln(message)

In the above Code,stockCodeIs defined as an optional type, which means it can have a string value or nil. If the Code cannot be compiled, an error is prompted:value of optional type String? is not unwrapped.

As you can see in the example, the optional types of Swift enhance nil detection and provide developers with the check during compilation. reasonable use of the optional types can effectively improve the code quality.

Force resolution

Slow and slow. I have mentioned many advantages, but the Code has not been compiled! Don't worry, we need to check.stockCodeIf it is nil or not, modify the Code as follows:

var stockCode:String? = findStockCode(Facebook)let text = Stock Code - if stockCode {    let message = text + stockCode!    println(message)}

Similar to Objective-C, we first check it to see if it has a value. If it is not nil, we can add an exclamation point!Then Xcode will know: "Well, I can use this value ". In Swift, we call it forced resolution (forced unwrapping) and use an exclamation point to forcibly obtain the true values of the optional types.

Return to the above Code. We checked to see if the variable is nil before force resolution. This is no different from the common nil detection in Objective-C. What if I forget to check? See the following code:

var stockCode:String? = findStockCode(Facebook)let text = Stock Code - let message = text + stockCode!  // runtime error

In this way, we will not get compilation errors, because we use forced resolution, and the compiler has assumed that this optional type must have a value. Obviously, this is an error. The following error occurs during running:

fatal error: Can’t unwrap Optional.None
Optional binding

In addition to forced resolution, optional binding is a more recommended resolution solution. You can use optional binding to check whether a value of an optional type has a value. If there is a value, it is parsed and stored in a temporary variable.

Put the code here! Let's take a look at the following sample code using the optional binding:

var stockCode:String? = findStockCode(Facebook)let text = Stock Code - if let tempStockCode = stockCode {    let message = text + tempStockCode    println(message)}

In the codeif let(Orif var) Is two Optional keywords. Translated into human language, probably like this: "IfstackCodeIt has a value and stores its valuetempStackCodeAnd then continue to execute the following code block. If it has no value, skip the subsequent code block ." BecausetempStockCodeIs a new constant, So you no longer need to add!Suffix.

You can put the method call inifSo the code looks more concise:

let text = Stock Code - if var stockCode = findStockCode(Apple) {    let message = text + stockCode    println(message)}

Here,stockCodeIt is no longer an optional type and can be used directly. IffindStockCodeIf nil is returned by the method, the code block following it will be skipped.

Optional chain

Before interpreting the optional chain, we must make some minor modifications to the original code. We create a new class calledStock, It hascodeAndpriceTwo optional types of attributes.findStockCodeFunction is used to returnStockObject instead ofStringObject:

class Stock {    var code: String?     var price: Double? }func findStockCode(company: String) -> Stock? {    if (company == Apple) {        let aapl: Stock = Stock()        aapl.code = AAPL        aapl.price = 90.32        return aapl    } else if (company == Google) {        let goog: Stock = Stock()        goog.code = GOOG        goog.price = 556.36        return goog    }    return nil}

Next, we usefindStockCodeThe function looks up the stock code and then calculates the total price required for purchasing 100 shares:

if let stock = findStockCode(Apple) {    if let sharePrice = stock.price {        let totalCost = sharePrice * 100        println(totalCost)    }}

The Return Value of the function is an optional type. We can check whether there is a value through the optional binding. Obviously, the stock price is also an optional type, so we continue to useif letTo check whether it has a value.

The above Code has no problems, butifNesting is too troublesome. If you have multiple layers of optional types, the following situations may occur:

if let x = xxx() {    if let x = xxx() {        if let x = xxx() {            if let x = xxx() {                if let x = xxx() {                    if let x = xxx() {                        if let x = xxx() {                            if let x = xxx() {                                if let x = xxx() {                                    if let x = xxx() {                                        if let x = xxx() {                                            if let x = xxx() {                                            }                                                }                                    }                                }                            }                           }                    }                        }            }        }    }   }

Er, the above Code is self-written, but not in the original text.

Besidesif letYou can use optional links to simplify the code. We can use question marks to concatenate multiple optional types:

if let sharePrice = findStockCode(Apple)?.price {    let totalCost = sharePrice * 100    println(totalCost)}

The optional chain provides another way to access variables, and the code now looks more clean and tidy. The above is just a basic usage. For more in-depth study, refer to the official documentation.

Interaction between Swift and Objective-C

The available types in Swift are very powerful, although it may take some time to get familiar with them. Optional types make your code clearer and avoid nil problems.

Swift has APIs designed to interact with Objective-C. When we need to interact with APIs of UIKit or other frameworks, you will certainly encounter optional types. The following lists some optional types that may be encountered in UITableView:

func numberOfSectionsInTableView(tableView: UITableView?) -> Int {    // Return the number of sections.    return 1}func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {    // Return the number of rows in the section.    return recipes.count}func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {    let cell = tableView.dequeueReusableCellWithIdentifier(Cell, forIndexPath: indexPath) as UITableViewCell    cell.textLabel.text = recipes[indexPath.row]    return cell}
Summary

For a developer, it is necessary to understand the working principle of the optional type. This is why we write an article specifically to introduce the optional types. It helps developers discover hidden problems during the compilation phase to avoid runtime errors. When you get used to this syntax, you will enjoy the charm of the optional type.

Enjoy the wonderful world. Awesome. (That's right.)

 

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.