Several tips for swift development

Source: Internet
Author: User

is the so-called mastery of the same technology the best way is to use it to do a thing, so this time of the actual combat let me to the Swift understanding of a deeper layer, but also accumulated a number of use skills. Share one today: How to define a class variable (and a class constant) correctly.

Swift language is a bit uncomfortable for developers who come from a static language or a dynamic language, and many problems can not be solved in a way that has become commonplace.

How to define a class variable (and class constant) correctly

Swift supports using class Func to decorate a "class method", but does not use "class var" and "class let" to specify class variables and class constants, and once you try to do so, Xcode prompts you: Class variable not yet SUP Ported It's a pity ...

However, it can be seen from this hint that Class variable support is only a matter of time. So how do we accomplish this at this stage? You can't always use ugly workaround. Still, I learned from Apple's official example how to define a class-level constant and variable, which is a struct.

A demo, you'll see:

    1. Class MyClass {
    2. struct Constants {
    3. static Let name = "MyClass"
    4. }
    5. struct Variables {
    6. static var age = 0
    7. }
    8. }

It can then be called when called: MyClass.Constants.name and MyClass.Variables.age

Although the middle of a layer of Constants and Variables, but I think this is also very good, equivalent to have a Prefix, directly look at the code to know whether it is a constant or variable. If you do not like this way, you can also use the form of the computed property to simulate the real class variable (constant) call. Like what:

  1. Extension MyClass {
  2. class var name:string {
  3. get {
  4. return Constants.name
  5. }
  6. }
  7. class var Age:int {
  8. get {
  9. return Variables.age
  10. }
  11. set {
  12. Variables.age = newvalue
  13. }
  14. }
  15. }

Once this is defined, you can access class constants or modify class variables directly with Myclass.name and Myclass.age.

This approach is syntactically compatible with the class variables and class constants that will be supported in the future, but it's a bit of a hassle to write a bunch of getter and setter, and you can decide if you want to use this way.

About the demo code of this article, you can paste into "swift" this command-line tool to practice. The effect, as we want, is that constants are not allowed to be modified, variables can be modified, and all of these operations are performed on MyClass without the need for instantiation.

While it's still a little cumbersome to use Swift to do some of the usual tasks, as a young language, it's now really ready to write apps that are actually available in the production environment, and I'm sure it will get better with the next development.

PS: Now I just want to sourcekitservice a little bit less ...

Use optional to avoid abnormal pointer problems

Recently, in the process of developing with Swift, another problem has been encountered. Simply put, the system returns a non-nil value where the exception pointer (that is, pointing to the 0x0000 address, producing a kern_invalid_address exception) caused the APP's crash, which is a Bug in IOS UIKit.

This issue requires an upgrade of the SDK, but before the SDK upgrade, we can solve it through a small workaround. The ins and outs are this:

The biggest difference between IOS's Swift API and the Objective-c API is that you need to look at Objective-c's API documentation to see if the value returned by a system is probably nil.

For example, Uidatasourcemodelassociation, a Protocol for restoring UITableView and Uicollectionview locations, has two methods, one of which is:

  1. 1
  2. -(NSString *) Modelidentifierforelementatindexpath: (Nsindexpath *) idx InView: (UIView *) view
  3. Look at Objective-c This method, you are not aware that the system returned IDX is not possible nil, but a look at the Swift version, it is very obvious:
  4. 1
  5. Func Modelidentifierforelementatindexpath (_ Idx:nsindexpath, InView view:uiview), String
  6. IDX and InView, no? and!, so they are not Optional, so the value cannot be nil. If the IDX and InView may be nil, then it should be used! To be modified to warn the developer that this value may be nil, please use it carefully.
  7. 1
  8. Func Modelidentifierforelementatindexpath (_ idx:nsindexpath!, InView view:uiview!)

Swift, a more thorough API than Objective-c, is a document expression, which I like very much after a period of coding.

However, it is also the reason that the framework of the system is not completely evolved, and these APIs may still return nil values, but the API will not return nil because it is flagged, so the swift_dynamiccastclassunconditional exception occurs, which results in the APP Crash

That is Modelidentifierforelementatindexpath this method returns a pointer to the 0X0000000000000000 object if it should return a value. Then Swift in the packaging value of the time, failed to package success occurred crash.

So how to avoid the problem caused by the App crash? Actually very simple, only need to manually wrap this 0x0000 object with Optional, and then judge whether it is nil, there will be no problem. For example, this code:

    1. Let Optionalidx = Optional (idx)
    2. if Optionalidx = = Nil {
    3. return "do something"
    4. }

At the beginning of this problem I was also very distressed, and then suddenly thought, is it possible to use Optional to package this abnormal pointer again check is nil, a try really can. So the problem is solved.

Fortunately, this kind of pit is not enough to let me go crazy step, I can continue to use Swift happy to write down ...

How to design a network request with Swift thinking

In the recent process of developing apps with Swift, the biggest experience is that I began to think with "swift thinking. When I first started using Swift, I just applied its grammar, and my mind was still objective-c thinking.

This time, with the mastery of Swift's basic features, I began to consciously learn and try out some of the features of Swift, which is called "swift thinking." Swift has a lot of proprietary (OBJECTIVE-C) patterns, and today I'll start with a very simple example:

How to design a network request with Swift thinking.

Students who have done network applications should know that when we make a network request, there are usually two results: one is a failure, an error is returned, one is a success, and the result is returned. Of course there will be more complex situations, such as: 1, the network request itself failure (such as network timeout), 2, the API side returned the internal result type failure (such as incorrect password). Here we don't subdivide.

In the traditional Objective-c project, there are several cases of dealing with this anomaly, mainly:

Direct Judgment Nserror

    1. Nserror *error = nil;
    2. ID result = [API dosomething:&error];
    3. if (Error! = nil) {
    4. NSLog ("Oh error!")
    5. }

This kind of processing is too straightforward, generally blocking the current thread, and therefore not recommended. The more commonly used is the following two kinds:

Handled by the Success,failture block.

    1. [API dosomethingwithsuccess:^ (ID result) {
    2. NSLog (@"seems good")
    3. } failure:^ (Nserror *error) {
    4. NSLog (@"Oh error!")
    5. }];

This is a relatively good point, through the block and internal implementation, you can do not block the current thread, when there is a result of processing. In the corresponding Block processing the corresponding condition: success or failure. However, this design still has a bit of a flaw, because it is the processing of the results scattered in different blocks, if I need to deal with the unified process regardless of success or failure, then need to call separately, not too intuitive. So, we have a third model.

Handled by a unified Completionhander block.

    1. [API dosomethingwithcompletionhandler:^ (id result, nserror *error) {
    2. if result! = Nil {
    3. NSLog (@"seems good")
    4. }
    5. if Error! = Nil {
    6. NSLog (@"Oh error!")
    7. }
    8. }];

The process of using Completionhandler to unify successful results and error failures should be the first to design, including the system's own API. Especially suited to the need to dispose of all situations in a Block.

Swift Network Request Processing

A simple list of three kinds of objective-c under the common network request class processing method, looks good, then the Swift mode is what, can do better? Yes, I think so.

There is a great enum mechanism in Swift, and all enumerations can be of any type, and can be of a different type. This means that we can wrap a result-based enum in Swift, such as:

  1. Enum Result {
  2. Case Error (nserror)
  3. Case Value (JSON)
  4. Init (_ E:nserror, _ V:json) {
  5. if let ex = e {
  6. Self = result.error (ex)
  7. } Else {
  8. Self = result.value (v)
  9. }
  10. }
  11. }

This is my real world code, used in my Weibo client.

The code is simple, I define an Enum object named "result", which wraps two cases, one is value, it is a JSON value when the network request succeeds, and the second error is a Nserror value that contains the specific error message when the network request fails.

In this way, the two possible situations under a network request are successfully packaged in a result object, which is either a result of success or a failure error, and there will never be results and errors at the same time. As a result, our network request processing code can be designed to be much simpler:

    1. Api.dosomethingwithcompletionhandler ({result), Void in
    2. switch (result) {
    3. Case let . Error (e):
    4. NSLog ("Oh error!")
    5. Case let . Value (JSON):
    6. NSLog ("seems good")
    7. }
    8. })

Seems to be the same as the second pattern in front of objective-c? It seems like a third kind? It is called mixed mode. Let me briefly say what the benefits of this model are:

First, we use the Switch condition to judge this one-to-one mode, we can reduce the occurrence of many errors, to ensure that the condition branch judgment will not be a problem, and secondly, we are still only in a Closure (here is replaced by Swift terminology, instead of objective-c Block) processing one of our request results result, so we can do some of the results of the unified processing, to ensure the unity of our logic.

This is what I think of the benefits of the Swift model.

Resources:

Http://zhidao.baidu.com/question/1669192806399603427.html
Http://zhidao.baidu.com/question/1047411913542707699.html
Http://zhidao.baidu.com/question/264028518446024725.html
Http://zhidao.baidu.com/question/1669192870606144187.html
Http://zhidao.baidu.com/question/1669256295134138147.html
Http://zhidao.baidu.com/question/489517469334454852.html
Http://zhidao.baidu.com/question/264028518512175285.html

Several tips for swift development

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.