iOS Code Practice Summary

Source: Internet
Author: User


Reprint Address: http://mobile.51cto.com/hot-492236.htm

In the last one months in addition to dedicated time and energy refactoring, there is a need to add functionality of the module, because of the code in the project more historical factors, the first thing is often the refactoring of the code, found that many of the previous code is not aware of the time when writing a lot of things, such as the global variable chaos , the method does not have the level sense, randomly adds, does not understand the business situation, by patching the way realizes the function and so on.

AD:

A few months after the completion of the MVVM/RAC study, has been silently in the project code refactoring, write code more, after a period of time to find their own code style and code quality has greatly improved. The past few years in a small company responsible for the iOS client later responsible for the client's research and development work, the clutter is more distracting, so by the time of last year, the code is not too much. In the new company for more than half a year, is currently only a small role in writing code, so energy is basically writing business code and amateur learning the messy technology above.

In the last one months in addition to dedicated time and energy refactoring, there is a need to add functionality of the module, because of the code in the project more historical factors, the first thing is often the refactoring of the code, found that many of the previous code is not aware of the time when writing a lot of things, such as the global variable chaos , the method does not have the level sense, randomly adds, does not understand the business situation, by patching the way realizes the function and so on. So I decided to write an article, I think the practice of the need to pay attention to some of the matters, a concrete summary of share to everyone.

Reduce Object Properties

This is one of the easiest ways to improve the quality of your code, and a lot of code looks messy at a glance, with dozens of different object variables defined inside, which makes it impossible to separate the different logic. One is defined in the wrong way, and many of the inexplicable internal variables are exposed to the header file, so that the external caller does not know at all how public can manipulate the method. In fact, through my own experience of refactoring, most of these can be replaced by local variables or __block variables.

1. Minimize the exposure of variables or methods in the header file, and use extension or category in. m files, or in a dedicated private header file

The less information is exposed in the header file, the better, and all unnecessary information is not exposed.

In the extension of M files, define conforms protocol and object properties, and for the definition of object properties, use Getter/setter.

2. Use local variables or __block variables instead

Local variables do not need to say more, need to write code when the idea is clear, after writing in the commit even if review must check again, to their own code quality is responsible, code review often check out redundant or obsolete code. Do not add an extra object property, do not leave commented out code, do not leave no use of code, these are basic skills, but many developers just do not, or write code without love, so a lot of obsolete code, I refactor the code, although not familiar with the business, But most modules can remove one-tenth of the code and a lot of object properties, this is simply not enough intentions.

With regard to the use of the __block variable, this is the most unsatisfactory part of Android development, this feature is simply too damn cool.

Here, for example, some variables are returned when using block

Again, for example, I need to record the top coordinate of a pan gesture at the beginning of the Headerview, combined with the RAC, which would have required a global variable to record the value, and use the __block variable to get it done.

3. You can avoid circular references as much as possible

There's a place where a lot of developers will overlook that when using _xxx object variables in a block, the block will retain the self pointer, accidentally causing a circular reference to occur. So by using local variables, you can stifle this problem in the cradle.

Reduce and Modularize object messages

1. Reducing object messages

Reducing the action message for the UI, thanks to block and RAC, or Blockskit, allows us to replace the previous Target-action model with a block by hook, and the UI and Action code finally work together to make the whole logic compact, When you look at the code, you don't have to jump. There is the daily development, write their own various protocol or transfer Target/selector place, try to use block to replace, believe me, this will make the code good read a lot.

2. Modular

Use "#pragma mark-xxx" to split the boundaries between different logic to make the entire file read more structured. There is a I now most commonly used is to set the shortcut keys for Xcode, CTRL + 6 display the document structure of the shortcut to: Command + J, search to quickly jump to the corresponding message and module, to try to avoid the document structure display more than two screen, more than two screen description a little more, You must have thought about refactoring.

I am accustomed to the general division of the modules are: Life Cycle,ui helper,datasource/delegate, according to the function of the module, and so on, as follows is my recent refactoring of a viewcontroller document structure

MVVM && RAC

My own use of the MVVM mentality is too cool to say that MVVM does not necessarily need to use RAC, but the data binding, in iOS is KVO, it is recommended to try, I myself feel this basically mvvm the core of things, even Android The SDK also has to introduce this feature. The logical abstraction of the data part is placed in the ViewModel and then the data in the UI and the ViewModel is binding, which does not reduce the amount of code, but it can greatly simplify the development of the complexity of the logic, no longer have to rewrite the-setxxx: method to update a whole bunch of irrelevant UI, about UI development, and then talk about the new one later. Here's my own understanding, some people say that RAC affects performance, the callback stack is too deep, this is true, but the personal feeling racobserver is based on KVO implementation, call time is synchronous call, so the impact on the performance is limited, there will be no call order problem, So I dare to use the data binding in the development of the list, after the practice fortunately, there is no impact on the user experience.

With regard to RAC, even if you do not use RAC, there are some things that are definitely worth your introduction in the project, such as @weakify (self)/@strongify (self), which is done by precompiling, by setting a local variable self to cover the global self, In order to avoid circular references, it is necessary to pay attention to the problem when the block level is deep, http://stackoverflow.com/questions/21716982/ EXPLANATION-OF-HOW-WEAKIFY-AND-STRONGIFY-WORK-IN-REACTIVECOCOA-LIBEXTOBJC.

RAC/MVVM, I have just started to study, wrote two articles, is my own summary, understand that there are shortcomings, with reference to you: http://blog.csdn.net/colorapp/article/details/ 46524893,http://blog.csdn.net/colorapp/article/details/46537729. You can learn through the reference links of articles in my blog.

UI Development

1. Overriding setter method and code Block Evaluation C extension syntax

Override the UI's Getter method, put UI initialization in getter, lighten the load of-viewdidload, and make the whole page clear, and can be used by using GCC Code Block Evaluation C Extension ({...}) Syntax, the logic of structuring local variable initialization and processing. For this syntax, refer to my previous blog: http://blog.csdn.net/colorapp/article/details/47006771. About setter code style, you can refer to an article written by others, http://casatwy.com/ Iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html, after discussing this question before in our Q Group, I also very much agree with this way of writing the UI.

For example, in-viewdidload, as a logical entry, the code becomes less but clearer, and the code is as follows:

Then rewrite the Bgview getter method, including view and frame which can be used ({...}) Syntax enables code to be structured in a hierarchical format:

2. Development of complex UI

Sometimes when we develop business, product requirements are often very complex, cool UI plus a variety of comprehensive logic to consider, the result is the code of the Long Code farm, and we usually work to face most of this kind of problem. On this issue, my solution, modular Ui/custom View/child view controller to solve.

(1) Combined view

This concept is borrowed from Android. Refactoring when looking at the code in the project, found that everyone used to do the UI, the concept is not very strong, feel that the UIView view hierarchy understanding is not enough. For example, a complex UI that directly stacks all the subviews directly onto Super view, the result is that adjusting the subview frame is very difficult. My personal approach is to first block the complex UI, from left to right or from top down, putting the various UI elements on top of different container view, and then combining these container view onto Super view, the benefits are obvious, first the UI is clean and clear. , it's not that hard to read. The second is that you calculate the coordinates or set the constraints will be very simple, because when you adjust a UI element, you only need to consider it with the container view that contains its coordinate relationship, rather than through a lot of uninteresting calculations with the outermost Super View Association. There is also the ability to make full use of auto layout and autoresiziingmask These UI tools, the use of the time will be very convenient. Then there is the combination of racobserver this tool, you can easily do according to data to update the UI.

For example, it was a page that I reconstructed a few times before in our project, and this homepage list has a high performance requirement. Not using auto layout, but not using auto layout is not a very clean reason to write it.

This is my layering of a uitableviewcell, the outermost layer consists of the container view of the icon view/right View/bottom view, and the right view container view is Top View/right Middle View/right bottom view these sub container view combinations, while the specific UI elements are placed in these sub container view. This way the UI code is presented in a hierarchical style that init/layoutsubviews only needs to maintain the relationship between self and container view, while the UI element that shows the data only has a coordinate relationship with sub container view. Let's take a look at the code implementation of the Right view Container view:

With regard to performance, thanks to iOS, we do not have the problem of the deep performance of the page in Android, and the UI can be layered with ease.

(2) Custom view

For very complex and relatively independent or reusable UI, use custom view subclasses in a timely manner. For a simple display UI, we simply need to make it through a combination view. But sometimes, we will encounter some contain both animation, logic is more complex situations, this time using a combination of view to achieve, on the one hand, easy to confuse the logic, the document structure of the file becomes very complex, in short, the object of the number of messages. This time, we can use custom view to achieve, in fact, this is a combination of view, but we have these combined view into a class, only expose a small number of interfaces to external calls. If this custom view appears in more than one business module, then it is necessary to use a separate file to accommodate this class, if it is only one use of this module can be directly written in the file of the business module, there is no need for all the classes are a separate file, we would like this "internal class "Come and get it."

When to use custom view instead of combination view, I think for a long time, you think the combination view code is very messy, don't be polite, packaging for a custom view on the line. A few of the problems I've encountered recently are when I use Uicollectionview to do part of the UI, along with many other UI elements, I'll write a custom view. For example, the following file, the UI to slide a left and right view of the image using Photoview this custom view for packaging, the internal use of Uicollectionview to implement a relatively independent module, This time the control can actually be packaged as a relatively independent module, with subclasses I feel more appropriate.

(3) Container View Controller

This usage is not familiar to many developers or is not much use, but the actual business, the technology is very useful, can greatly improve the development efficiency. Unfamiliar with this part of the knowledge, you can refer to my previous blog: http://blog.csdn.net/colorapp/article/details/45765601. For businesses with relatively independent business logic and lifecycle requirements, use the child view controller to wrap, and if the parent view Contrller is very close to the child view controller, use the view Model and block to interface with the parent view controller and the child View controller.

There are many advantages to using the child view Controller to develop the UI instead of the custom view, and I personally think that the greatest advantage is that it is easy to take advantage of the view controller's life cycle and view Controller Hierarchy, For example, in the-viewwillappear/-viewdiddisappear to do some operations, such as direct access to uinavigationcontroller pointers and so on. The previous practice is to invoke the custom view method in the corresponding life cycle of the view controller, passing the Self.navigationcontroller pointer to the custom view, and so on. So you can not just wrap the UI-related code into the Child view controller, you can also put the network request, data processing these logic into the child view controller, so that it can avoid the more than 1k rows of view The controller was there.

After using MVVM, there is a more beneficial use, such as the public some data, before we pass the object to pass, so the problem is very prone to confusion, this time we are passing viewmodel can avoid this problem, ViewModel is responsible for both the network request and the data processing, and what the parent view controller and the child View controller need to do is to viewmodel the binding.

Auto Layout/masonry

In some non-list pages where performance requirements are not so strong, we can use auto layout extensively to develop the UI, taking full advantage of the UI based on the data's adaptive capabilities, and the steps to tweak the UI in container view are not required. There was a time when I didn't want to develop iOS at all, for the simple reason that the Android layout and the visible way of development are very convenient, and with artifacts like as, I feel less efficient than iOS. I started using auto Layout since the project's minimum support changed to iOS6, but I felt it was a relief for UI development, although it was a bit of a hassle.

As for masonry this framework, before I have certain doubts about this, I dare not use, so I read the source code, found that the packaging is very thin very ingenious, a lot of design ideas are also worthy of reference, the source of interest can refer to my blog: http://blog.csdn.net/ colorapp/article/details/45030163. After I read the source code, I tried to use mansory to develop a page showing the information, it felt so good!

The advantage is that after you set the UI data, you don't have to think about the update UI, so the world is instantaneous .... , here's a simple example of me, combining ({...}) syntax and RAC, you can set the data on the UI using the simplest name of the label, which is definitely a relief for our UI development.

Say something about auto layout:

1. The first problem is that if a view is not a leaf view, then this uiview, if hidden, is still work, so it will leave a blank and will not be as convenient as setting up gone in Android. Domestic sunny Big God open source a good way to solve, https://github.com/forkingdog/UIView-FDCollapsibleConstraints. Here is my previous solution, comparison of soil forcing, direct sub-type:

2. Problems with animations

Using auto layout has a big problem is animation, by changing the constraints to animate, has always been my headache, so generally encountered this kind of problem, I will try to avoid using auto layout to solve, but use frame way to do. can refer to Objc.io above an article: http://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/.

3. The problem of multi-line Uilabel

IOS7 and the following operating systems, Uilabel display multi-line text is not enough, you need to set the Uilabel preferredmaxlayoutwidth to a fixed value to display multiple lines. It is no longer necessary to set this up after iOS8.

4. Uiscrollview issues and constraints ambiguity and other issues

Refer to my article: http://blog.csdn.net/colorapp/article/details/47007143

This place, my suggestion is to choose the realization way according to the specific question: Spring & structs or Auto layout, the kind of problem-solving is more concise and quick to use that kind of, not necessarily fixed in a behavior, especially the development of the page has a lot of animation.

Comments

Do not write a bunch of Chinese comments, code do not appear a large number of Chinese, OC has enough wordy, do not write code so wordy. In addition to the public functions or methods of providing services, business code only at some key points on the line, do not need a large number of Chinese, so too low, code self-explanatory, needs to be annotated, can be done by Meow's Xcode plugin, https://github.com/ Onevcat/vvdocumenter-xcode.

And for the appearance of pinyin naming code of the people, can master the words, do not hesitate, open it. Here spit a groove, before the company has such a friend, not I recruit, the boss shoved to me.

Use the new grammar of OC

OC has a lot of new syntactic sugars that can greatly improve our efficiency, refer to Apple guide:https://developer.apple.com/library/ios/releasenotes/objectivec/ Modernizationobjc/adoptingmodernobjective-c/adoptingmodernobjective-c.html.

For example, when printing numbers, we can print with @ (XXX), use typedef ns_enum when defining enumerations, use Instancetype instead of IDs, and so on. and recently to the annual skill slot Refresh day, IOS 9 released, OC has some new syntax, to learn more use it.

Processing of JSON data

Beginners tend to be slightly confused by this, such as the server returned the data format is incorrect, including NULL, it is easy to cause the project to crash. This problem can be solved using mantle, a lot of brothers are using this, I have never used. Before writing a small framework on GitHub, Https://github.com/lihei12345/CYJSONValidator, which is also used within our project, the effect is good, used to parse the data, Verify the type of data and whether it is null, to ensure that the data types are parsed. You can also set some default values when a key may not exist.

As an example:

Block

Using block instead of delegate, this is not much to say, the code becomes very compact, reduce the number of file messages, the main thing is that the relationship is not so close. For a large number of delegate methods to consider using protocol implementation, this time block too much also affect reading.

At the same time, for the transfer of Target/selector, also try to use block bar, this reading is too inconvenient to find.

Submit Code

Timely stage, this is very important, the development process often need to be more often than the previous step of the code, so as to ensure that their own changes are correct. If you have some minor problems, you can even find the historical version.

Commit in time, each complete a relatively complete demand, on commit, small submission is a good habit.

PR code review To do a good job, to spend a lot of time to do, if there are conditions, it is best to open a summary of each version.

RAC Encapsulation Network request

The returned signal to avoid side effect, but replay/replaylazily is not used because Dispose is not called.

Use the Raccommand encapsulation request to view these articles: http://codeblog.shape.dk/blog/2013/12/05/ reactivecocoa-essentials-understanding-and-using-raccommand/,https://github.com/reactivecocoa/reactivecocoa/ issues/963,https://github.com/reactivecocoa/reactivecocoa/issues/1326.

Combine Raccommand and Takeuntil: to encapsulate a request that can be cancel

iOS Code Practice Summary

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.