Briefly describe how to transition from Objective-C to Swift, objective-cswift

Source: Internet
Author: User
Tags closure definition

Briefly describe how to transition from Objective-C to Swift, objective-cswift

This article describes how to transition from Objective-C to Swift.

If you don't have much to say about it, please note that the development environment discussed in this article is Xcode 6 beta 2.

Single file structure VS interface-Implementation

One of the most notable changes is that the file structure "[interface]. h/[implementation]. m" in Objective-C is banned.

In fact, I personally support this file structure, because the method of getting and sharing class features through interface files is safe and simple, but now I have to face the reality that it no longer exists.

In Swift, interfaces and implementations are not separated into two files, we only need to rely on implementation to construct a class (and it is impossible to add any modifications to the accessibility when writing ).

If this change cannot be tolerated, consider the following:

Most obvious: intuition.

We can use beautiful documents to improve the readability of the class. For example, we can move all the elements we want to use as public to the beginning of a file, or use extensions to distinguish between public and private.

Another practical method is to add an underscore '_' before the private method and variable naming as the prefix.

The following is an example of a mix of the above two solutions:

<span style="font-size:14px;">01// Public02extension DataReader {03       04    var data { }05    func readData(){06        var data = _webserviceInteraction()07    }08}09   10// Private implementation11class DataReader: NSObject {    let _wsURL = NSURL(string: "http://theurl.com") func _webserviceInteraction()->String{        // ...    }}</span>

Although we cannot modify the visibility of each element in the class, we can try to make some access "more difficult ".
A special method is to use Nested classes to hide the private part (at least automatically hide it). The following is an example:
<span style="font-size:14px;">import UIKitclass DataReader: NSObject {    // Public ***********************    var data:String?{        get{return private.internalData}    }    init(){     private = DataReaderPrivate()    }    func publicFunction(){     private.privateFunc()    }       // Private **********************    var private:DataReaderPrivate    class DataReaderPrivate {      var internalData:String?        init(){         internalData = "Private data!"        }        func privateFunc (){}   }}</span>

We put the private implementation into a private constant instance, and then use the "normal" class implementation to act as an interface. However, the private part is not truly hidden, but a private keyword must be added during access:

<span style="font-size:14px;">let reader = DataReader()reader.private.privateFunc()</span>

The question is: is it worthwhile to write the code in order to hide the private part in the end?

My advice is to use detailed documents or a little extension before the visibility changes (Apple is busy with this.

Constants and variables

When writing Objective-C, I will rarely use the const keyword, even if I know some data, it will not change. However, in Swift, Apple recommends that developers spend more time thinking about using constants (let) instead of variables (var. So be sure to understand what your variables are to do. You will use constant frequency as you have never imagined.

Simplified writing

Let's take a look at the following two lines of code in pipeline and compare the differences:

<span style="font-size:14px;">let wsURL:NSURL = NSURL(string:"http://wsurl.com");vslet wsURL = NSURL(string:"http://wsurl.com")</span>

In the first two weeks of my first access to Swift, I forced myself not to add semicolons at the end of each line of code (but I won't add points when I write Objective-C ).

Type inference can be used to assign a type based on the definition of a variable. Compared with redundant languages such as Objective-C, this type of inference can be circled here.

We should use a consistent naming method. Otherwise, it is difficult for other developers (including yourself) to speculate on the Type through an extremely bad naming:

<span style="font-size:14px;">let a = something()</span>

A more reasonable name is as follows:

<span style="font-size:14px;">let a = anInt()</span>

Another change is about the arc number. They no longer need to pair:

<span style="font-size:14px;">if (a > b){}     vs   if a > b {}</span>

However, remember that the part we write in parentheses is considered as an expression, which does not mean that writing is always correct. When binding variables, we cannot use parentheses like the following:

<span style="font-size:14px;">if (let x = data){} // Error! if let x = data {} // OK!</span>

It is not necessary to use the types to judge and delete semicolons and parentheses. However, we can consider using the above suggested method to write Swift code, which will improve the readability of the code and reduce some input.

Optional Value

How many times are we confused about how to set the function return value? I have used NSNotFound,-1, 0, and custom return values to indicate that the returned value is null.

Now the value options can solve the problem of null returned values. We only need to add a question mark after the data type.

We can write as follows:


<span style="font-size:14px;">class Person{    let name:String    let car:Car? // Optional value    init(name:String){        self.name = name    }}   // ACCESSING THE OPTIONAL VALUE ***********var Mark = Person(name:"mark")// use optional binding if let car = Mark.car {    car.accelerate()}// unwrap the valueMark.car?.accelerate()</span>

This example uses an optional value to describe "someone has a car". It indicates that the car feature may not exist because it indicates that someone has no car.

Then we can use optional binding or unwrap to obtain its value.

If an attribute is not set to an optional value and we do not assign a value to it, the compiler will immediately get upset.

Once initialized, there is no chance to set non-optional attributes.

Therefore, we should first consider the relationship between the attributes of the class and other parts, and what changes will happen when the class is instantiated.

These improvements have completely changed the way a class is conceived.

Optional Value Package splitting

You will find the value of choice difficult to comprehend, because you will not understand why the compiler prompts you to unpack it before use.

Mark. car?

I suggest you think of the optional value as a struct (it will be easier to understand if it is a struct), including a set value. But other items (wrap) are wrapped outside ). If the value is defined, You can unwrap it and get the value you want. Otherwise, you will get a null value (nil ).

Use exclamation point "! "To forcibly split the package, regardless of whether the value is defined, this is risky, because the application will collapse if the value is not defined.

Delegation Mode

After years of writing Objective-C and Cocoa code, I think most people have developed a hobby for using the delegate mode. Note! We can still retain this kind of hobby. Below is a very simple example:

<span style="font-size:14px;">@objc protocol DataReaderDelegate{    @optional func DataWillRead()    func DataDidRead()}class DataReader: NSObject {          var delegate:DataReaderDelegate?    var data:NSData?       func buildData(){        delegate?.DataWillRead?() // Optional method check        data = _createData()        delegate?.DataDidRead()       // Required method check    }}</span>

Here we use a simple @ optional to replace respondToSelector to check whether the delegate method exists.
<span style="font-size:14px;">delegate?.DataWillRead?()</span>

Note that the @ obj prefix must be added before the Protocol, because @ optional is used later. At the same time, the compiler will also report a warning message here to prevent you from adding @ obj.

To implement the protocol, we need to build a class to implement it and assign it in the way that we used it in OC.

<span style="font-size:14px;">class ViewController: UIViewController, DataReaderDelegate {                                   override func viewDidLoad() {        super.viewDidLoad()                   let reader = DataReader()        reader.delegate = self    }       func DataWillRead() {...}    func DataDidRead() {...}}</span>

Target-Action Mode

Another common design pattern: Target-action pattern. We can still implement it in Swift as we use it in OC.

<span style="font-size:14px;">class ViewController: UIViewController {    @IBOutlet var button:UIButton    override func viewDidLoad() {        super.viewDidLoad()                   button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)    }       func buttonPressed(sender:UIButton){...}}</span>

The only difference here is how to define a selector. We can use a string like the following to decode the method prototype:
<span style="font-size:14px;">Selector("buttonPressed:")</span>

Single-piece Mode

Love and hate. The single-piece mode is still one of the most common design modes.

We can use GCD and dispatch_once to implement it. Of course, we can also use the let keyword to implement thread security.

<span style="font-size:14px;">class DataReader: NSObject {           class var sharedReader:DataReader {                   struct Static{            static let _instance = DataReader()        }                   return Static._instance    }...}</span>

Let's take a quick look at this Code:

1. sharedReader is a static compound attribute (we can also replace it with a method ).

2. Static attributes cannot be reconstructed when the class is implemented. Therefore, because internal types are allowed, we can add a struct here.

3. _ instance is a constant, which will not be overwritten and ensures thread security.

You can refer to the usage of the following DataReader singleton:

<span style="font-size:14px;">DataReader.sharedReader</span>

Structure and enumeration

The structure and enumeration in Swift are very fascinating. You won't find anything like them in other languages.

Supported methods:

<span style="font-size:14px;">struct User{    // Struct properties    let name:String    let ID:Int    // Method!!!    func sayHello(){        println("I'm " + self.name + " my ID is: \(self.ID)")    }}   let pamela = User(name: "Pamela", ID: 123456)pamela.sayHello()</span>

As you can see, here the struct uses initialization, And this is automatically created by Swift (we can add some custom implementations ).

The enumeration type syntax is a little harder than we have used.

The keyword case is required for its definition:

<span style="font-size:14px;">enum Fruit {   case orange  case apple}</span>

In addition, enumeration is not limited to int type:

<span style="font-size:14px;">enum Fruit:String {   case .orange = "Orange"  case .apple = "Apple"}</span>

It can also be more complex:

<pre name="code" class="plain"><span style="font-size:14px;">enum Fruit{    // Available Fruits    case orange    case apple           // Nested type    struct Vitamin{        var name:String    }           // Compound property    var mainVitamin:Vitamin {          switch self{    case .orange:        return Vitamin(name: "C")              case .apple:        return Vitamin(name: "B")        }    }}    let Apple = Fruit.applevar Vitamin = Apple.mainVitamin</span>

 

In the above section, we added an internal Vitamin and a composite mainVitamin for the Fruit enumeration class. In addition, such a structure can also initialize the elements in the class according to the enumerated values ...... Are you already dazzled?

Mutable and immutable classes

In OC, we always use mutable and immutable classes. For example? NSArray and NSDictionary. In Swift, we do not distinguish data like this. Instead, we only need to replace it with the definition of constants and variables.

The data variable can be changed, but the value of the array constant cannot be changed. Therefore, write down this formula:

"Let = immutable. var = mutable ".

Block and Closure

I like block syntax very much because it is quite simple and easy to remember.

<Br>

By the way, because Cocoa has become a habit for many years, sometimes I prefer to use blocks to replace simple commissioned jobs. This is a flexible and quick method and is very practical.

In Swift, the block is opposite to the closure. The function of closures is extremely powerful, and Apple is doing a great job in simplifying it, which is easy to implement.

The examples in the official document can only make me speechless.

It is defined as follows:

<span style="font-size:14px;">reversed = sort(names, { (s1: String, s2: String) -> Bool in    return s1 > s2})</span>

Then, it is reconstructed like this:

<span style="font-size:14px;">reversed = sort(names, >)</span>
Therefore, we can implement a closure, a write-down parameter ($0, $1), and a direct operation function (>) in different ways because of the existence of Type judgment ).

In this article, I plan to traverse the closure usage, but I would like to say a few words about how to obtain the value in the closure.

In OC, we define a variable like _ block so that we can prepare to press it into a block. However, these are not necessary in closures.

We can use and modify the surrounding values. In fact, closures are designed very smartly, so they are enough to obtain external elements for internal use. Each retrieved element is copied or referenced. If the closure modifies its value, a reference is created; otherwise, a copy is generated.

If the closure references an instance that contains or calls the closure itself, we will go into a loop with strong reference.

Let's take a look at the example:

<span style="font-size:14px;">class Person{    var age:Int = 0           @lazy var agePotion: (Int) -> Void = {        (agex:Int)->Void in            self.age += agex    }           func modifyAge(agex:Int, modifier:(Int)->Void){11        modifier(agex)    }   }   var Mark:Person? = Person()Mark!.modifyAge(50, Mark!.agePotion)Mark = nil // Memory Leak</span>

This agePotion closure references itself and ensures strong references to the current instance. At the same time, the instance maintains a reference to the closure of the queue. BOOM ~~~ We entered a circular strong reference.

To avoid this situation, we need to use the Capture List. This List maintains the weak reference of the instance we want to use. The syntax is very simple. You only need to add [unowned/strong self] before the closure definition, and then you will get a weak reference without a master to replace the previous strong reference.
<span style="font-size:14px;">@lazy var agePotion: (Int) -> Void = {     [unowned self](agex:Int)->Void in         self.age += agex}</span>
No weak reference

In OC, we know how weak references work. The same is true in Swift, which is basically unchanged.

So what is a non-master reference. I took a closer look at the introduction of this keyword, because it clearly illustrates the definition of the relationship between classes.

Let's briefly describe the relationship between Person and bank account BankAccount:

1. A person can have a bank account (optional ).

2. A bank account belongs to a person (required ).

<span style="font-size:14px;">We can describe this relation with code: class Person{    let name:String    let account:BankAccount!           init(name:String){        self.name = name        self.account = BankAccount(owner: self)    }}  class BankAccount{    let owner:Person           init(owner:Person){        self.owner = owner    }}</span>

This write relationship creates a reference loop. The first solution adds a weak reference to the "BankAccount. owner" attribute. However, a non-primary reference is also used as the constraint: This attribute must have a value and cannot be blank (the second point in the previous list is satisfactory ).

Well, there is no more to say about the no-master reference. In fact, it is just like a weak reference that does not add a role to the reference, but it ensures a non-null value for it.

Finally, you will find that the more experiments and tests that Swift consumes, the clearer the value. View More >>>



How does Objective-C use the Swift class?

2.16.apple.com/..h.html

To learn the swift language, do you need to learn objective-c?

Clearly tell you: No.

Swift was developed by Apple to replace ObjC. If he still needs to have the ObjC foundation for learning, it would be so sad...
Furthermore, it is easier for a novice programmer to learn swift than other programming languages.

I hope my answer will help you! ^ O ^

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.