Effective OBJECTIVE-C 2.0 52 effective ways to write high-quality iOS and OS X code---1-12

Source: Internet
Author: User
Tags error status code

* In other languages, a lot of work is done by compilers, while in OC it is performed at runtime. As a result, functions that can function properly in a test environment are in the working environment and may not be executed correctly because of invalid data processing. The best solution to avoid such problems is, of course, to write the code right from the start.

The first chapter is familiar with Objective-c

1th understand the origin of objective-c language
1. The difference between a message and a function call
The key difference is that, using the language of the message structure, the code that the runtime should execute is determined by the operating environment;
The language used by the function call is determined by the compiler. If the function called in the sample code is polymorphic, the
When running, follow the "virtual method table" (virrual table) to find out which function implementation should be performed.
The language of the message structure, whether polymorphic or not, is always run to find the method to be executed.
In fact, the compiler doesn't even care what type of object the message is received from. The object that receives the message is also subject to the
Run-time processing, whose process is called dynamic binding.
The important work of 2.OC is done by the "Runtime component" (runtime component) rather than the compiler, making
All the data structures and functions required for the object-oriented nature of OBJECTIVE-C are in the run-time component.
3. To understand the memory model, it is necessary to understand that the pointer in the Objective-c language is used to indicate the object. Want
Declare a variable so that it refers to an object, using the following syntax:
NSString *somestring = @ "the string";
This syntax is basically a copy of the C language, it declares a variable named somestring, whose type is
nsstring*, in other words, this variable is a pointer to NSString. Objects for all Objective-c languages
Must declare that the memory occupied by the object is always allocated in the heap space, and
Not allocated on stack, OBJECTIVE-C objects cannot be allocated on the stack:
NSString stackstring;
Error:intarface type cannot be statically auocated
The somestring variable points to a block of memory allocated to the heap, which contains a NSString object. So
Is that if you create another variable that points to the same address, then the object is not copied, just the two
The variable points to this object at the same time:
NSString *somestring= @ "the string";
NSString *anotherstring = Somest ring;
There is only one nsslring instance, but there are two variables pointing to this instance. Two variables are nsstring* type
, which indicates that the current "stack frame" is allocated two blocks of memory, and the size of each block of memory can be
The next pointer (4 bytes on a 32-bit computer, and 8 bytes on a 64-bit computer). These two pieces of memory
The same value is the memory address of the NSString instance.
4. Objective-c has abstracted the heap memory management. No need to allocate or dispose objects with malloc and free
The memory that is occupied. OBJECTIVE-C runtime Environment This part of the work is abstracted into a set of memory management architecture, called "
Reference count "
5. This structure is used throughout the system framework, because if you use the Objective-c object to do it, the sex
can be affected. Creating objects also requires additional overhead, such as allocating and freeing heap memory, compared to creating structs
such as If you only need to save an int, tloat, double, char, and so on "non-object Type" (Nonobject type),
Then it is usually possible to use the cgrect structure.
6. Key points
A objective-c is a superset of the object-oriented features added to the C language. Objective-c using dynamic Bindings
Message structure, which means that the object type is checked at run time. After receiving a message, you should
What code to do is determined by the run-time environment, not by the compiler.
• Understanding the core concepts of C language helps to write good objective-c programs. In particular, to master the memory model and pointers

2nd: Introduce as few other header files as possible in the header file of the class
1. When compiling a file that uses the Eocperson class, you do not need to know all the fine
sections of the Eocemployer class, just know that there is a class named Eocemployer. Fortunately, there is a way to tell the story.
Translator:
@class Eocemployer;
This is called "forward declaration" (forward declaring) of the class.
Now the Eocperson header file becomes this:
@class eocemployer;
@property (Nonatomic,strong) Eocemployer *employer;
The Eocperson implementation file needs to import the Eocemployer header file, because to use
Eocemployer, you must know all of its interface details.
2. Postpone the timing of the inductive header file as much as possible, only when there is a need, so you can reduce the number of header files that the class uses
need to introduce. Suppose this example introduces EOCEmployer.h to EOCPerson.h. Then
just introduce EOCPerson.h. All the content of EOCEmployer.h will be introduced. If this process continues
, there are many things that are not available at all, which will certainly increase compilation time.
3. Forward declaration also resolves the issue of two classes referencing each other.
4. However, it is sometimes necessary to introduce additional header files in the header file. If you write a class that inherits from a parent class,
must introduce a header file that defines that parent class. Similarly, if you want to declare a class that you write to conform to a protocol, the
protocol must have a full definition and cannot use forward declaration. A forward declaration can only tell the compiler that there is a protocol,
and at this point the compiler is aware of the methods defined in the protocol.
5. It is advisable to place the agreement (except for the entrustment agreement) in a separate header file.
6. Important
-do not introduce a header file unless it is necessary. In general, you should use the forward sound
Minlaiti and other classes in the header file of a class, and introduce the header files of those classes in the implementation file. Doing so minimizes the coupling of
between classes (coupling).
. It is sometimes impossible to use forward declarations, such as declaring a class to follow a protocol. In this case, try to move the declaration "
This class follows an agreement" to the "Class-continuation classification". If not, the
puts the protocol in a single header file and then introduces it.

3rd: Multi-use literal syntax (essentially syntax sugar), and less of the equivalent method (dynamic and static init party
Method)
1. Create a string
NSString *string = @ "the string";
This shortens the source code length, Make it easier to read.
2. Create a number
NSNumber *number = @1;
It is useful to represent numeric values in literal quantities. Doing so makes the NSNumber object neat because
contains only numeric values in the declaration and no extra syntactic components
3. Create an array (no nil in array elements)
Nsarray *animals = @[@ "Cat" "Dog" "Mouse"
Remove object from array
NSString *dog = animals[1];
4. Create dictionary
Nsdictionary *persondata =
@{@ "name": @ "Matt" @ "Age": @ 28}; The keys and values in the
Dictionary must be OC objects, which are encapsulated in the NSNumber real
Example
Access dictionary
nsstring *lastname = persondata[@ "Name" in front of the number);
5. Variable group and mutable dictionary modification
mutablearray[1]= @ "dog";
mutabledictionary[@ "name"]= @ "Galloway";
6. Important
-you should use literal syntax to create a string , values, arrays, dictionaries. This is more concise than the usual method
for creating such objects.
-the element that corresponds to the key of the array subscript or dictionary RJ should be accessed by removing the label operation.
-When creating an array or dictionary with literal syntax, if there is nil in the value. Throws an exception, so make sure that the value
does not contain nil.

4th: Multi-use type constants, less # define preprocessing directives (macros)
1. Do not use the # define animation_duration 0.3
and use the static const NSTIMEINTERVAL Kanimationduration = 0.3;
The benefit of the latter is the inclusion of type information.
2. If you do not intend to expose a constant, you should define it in an implementation file that uses the constant
3. External publication Constants
. h files: extern const Nstimeinterval eocanimatedviewanimationduration;
. m file: const nstimeinterval eocanimatedviewanimationduration = 0.3;
4. Important
. Do not define constants with preprocessing directives. The defined constants do not contain type information, and the compiler simply performs a find-and-replace operation on this basis before the
compiles. Even if a constant value is redefined, the compiler does not generate a police
message, which results in inconsistent constant values in the application.
-Use the static const in the implementation file to define constants that are visible only within the compilation unit. Because such constant
quantities are not in the global symbol table, you do not need to prefix their names.
One uses Extem in the header file to declare global constants and to define their values in the relevant implementation file. This constant
is to appear in the global symbol table, so its name should be separated, usually prefixed with the class name associated with it.

5th: Use enumerations to represent States, options, status codes, styles
1. When an error status Code or Composable option is represented by a series of constants, it is advisable to use an enumeration to name it.
2. Key points
-An enumeration should be used to indicate the state of the state machine, the options passed to the method, and the status code equivalent, giving these values a
Easy-to-understand name.
-If the option passed to a method is expressed as an enumeration type, and multiple options can be used simultaneously, the
Each option value is defined as a power of 2 to combine it by a bitwise OR operation.
-Use Ns_enum and Ns_options macros to define the enumeration type and indicate its underlying data type. Do this
You can ensure that the enumeration is implemented with the underlying data type chosen by the developer, without using the compiler's chosen
Type.
-Do not implement the default branch in a switch statement that handles enumeration types. In this case, after adding the new enumeration
, the compiler prompts the developer: The switch statement does not handle all enumerations.

Chapter II object, message, run-time
The process of passing data between objects and performing tasks is called message delivery.

6th: Understanding the concept of attributes
1. The property is an OC feature that encapsulates the data in an object. The OC object will usually
The data it needs is saved as a variety of instance variables. Instance variables are generally accessed through "access methods". which
, a "Get Method" (getter) is used to read the value of a variable, whereas a set method (setter) is used to write a variable value.
Developers can make the compiler automatically write property-related access methods. This feature introduces a new "dot language
To make it easier for developers to access the data stored in them according to the class object.
2. With attributes, the compiler automatically writes out a set of access methods to access the given name in the given type
The variable. The compiler will also automatically add an instance variable of the appropriate type to the class, and precede the property name with a row
Line as the name of the instance variable.
3. There is no difference between using point syntax and direct call access methods.
4. In the implementation file, the name of the instance variable can be specified by @synthesize syntax:
@synthesize name = _myname, but this is not recommended.
5. In the implementation file, the @dynamic keyword can be used to prevent the compiler from automatically generating access methods and actual
Example variable. And if you access the properties in your code, the compiler does not issue a warning message.
@dynamic name;
6. attributes (which affect the access method generated by the compiler)
1> atomicity (nonatomic)
Reasons to use Nonatomic: the overhead of using a sync lock in iOS can cause performance problems.
2> read/write permissions (readwrite,readonly)
3> Memory Management Semantics (assign,strong,weak,unsafe_unretained,copy)
*assign "Set method" only performs a reduction for "scalar type" (for example, cgfloat or Nslnteger, etc.)
Single-assignment operation.
*strong This trait indicates that the attribute defines an "owning relationship". When you set a new value for this property, the set
Method preserves the new value and releases the old value before setting the new value up.
*weak This trait indicates that the attribute defines a "non-owning relationship." When you set a new value for this property, the set
Method neither preserves the new value nor releases the old value. This trait is similar to assign, but the object referred to in the attribute is
When destroyed, the property value is also emptied.
*unsafe_unretained The semantics of this trait are the same as assign, but it applies to "Object Types", baby
The trait expresses a "non-owning relationship" ("not reserved", unretained). When the target object has been destroyed,
, the property value is not automatically emptied ("unsafe".) Unsafe), this is different from weak.
The *copy of this trait is similar to that of strong. However, the set method does not retain the new value, but instead
Its "copy" (copy). When the attribute type is nsstring*, this trait is often used to protect its encapsulation.
Because the new value passed to the set method might point to an instance of a nsmutablestring class. This class is
A subclass of NSString that represents a string that can modify its value, and if the string is not copied, then set the
After the property is placed, the value of the string may be changed without the object's knowledge. So, this is
To copy a "immutable" (immutable) string, ensure that the string value in the object does not inadvertently
Changes. As long as the object used to implement the property is "mutable" (mutable), you should set the new property value
Copy a
7. Method name (the method name of the access method can be specified by the following attributes)
1> getter=<name> bool Type joins the IS prefix
@property (Nonatomic,getter = isOn) BOOL on;
2> setter=<name> not used
8. Key points
-You can use the @property syntax to define the data that is encapsulated in the object.
-Specify the correct semantics for storing data through "traits".
-When setting an instance variable corresponding to a property, be sure to follow the semantics declared by that property.
-The Nonatomic property should be used when developing iOS programs, and the atomic property can severely affect performance

7th: Try to access the instance variable directly within the object
1. Use direct access (_NAME) When reading instance variables, and
Use Properties (self.name) to make
differences when setting instance variables
1> Direct access is faster
2> Direct Access does not call its Set method
3> Direct Access does not trigger KVO notifications. Whether this creates a problem, and also depends on the specific object behavior
4> through properties to help troubleshoot related errors, because you can give the Get method and/or Set method
A new breakpoint to monitor the caller of the property and the timing of its access.
2. There is a reasonable compromise, that is, when you write an instance variable, it is done by its "set method", and
is accessed directly when the instance variable is read. This method can not only improve the speed of the read operation, but also can control the write operation of the
sex. The primary reason for writing instance variables through the set method is that
ensures that the memory management semantics of the relevant properties are enforced. However, there are several
issues to be aware of when choosing this approach.
1> How do I set property values in the initialization method? The
accesses the instance variable directly because the child class may overwrite the set method.
If the instance variable being initialized is declared in the parent class, and we cannot access the instance variable directly in the subclass
, then we need to call the Set method
2> lazy Initialization
In this case, the property must be accessed through the Get method, otherwise, Instance variables are never initialized.
3. Important
* When reading data inside an object, it should be read directly through the instance variable, while writing the data should be written through the property
.
* In the initialization method and the Dealloc method, the data should always be read and written directly through the instance variable. The
* Sometimes uses lazy initialization techniques to configure a piece of data, in which case the data needs to be read through the property.

8th: Understanding the concept of "object equivalence"
1. In general, two different types of objects are always unequal (unequal)
2. Equivalence Judgment method Isequaltostring:,isequaltoarray:, Isequaltodictionary:
3. Important
• If you want to detect the equivalence of objects, provide "isequal:" with the hash method.
• The same object must have the same hash code, but the same object is not necessarily the same for two hash codes.
• Do not blindly detect each attribute individually, but rather develop a detection scheme (such as an identifier) according to your specific needs
• When writing a hash method, you should use an algorithm that is fast and has a low probability of collision with the hash code.

9th: Hide Implementation Details in "Class family mode"
1. Immutable classes, such as Nsarray and Nsmutablearray, define methods that are common to all arrays, and
Mutable classes define methods that apply only to mutable arrays.
2. Determine if an object is located in the class family Maybeanarray is Kindofclass:[nsarray class]
3. Rules to be followed for new subclasses
The 1> subclass should inherit the abstract base class from the class family.
To write a subclass of a Nsarray class family, you need to inherit from the base class of the immutable variable group or the group of variables
The 2> subclass should define its own way of storing data.
When developers write Nsarray subclasses, they are often blocked on this issue. Subclasses must use an instance variable to save
The objects in the array are placed. This seems to be different from what we expected, and we thought Nsarray would certainly save those
object, so there is no need to save another copy of the class. But remember, Nsarray itself is nothing but a bag.
Shell outside of other hidden objects, it simply defines some of the interfaces that all arrays need to have. For this self-
Defined array subclasses, you can use Nsarray to save their instances.
The 3> subclass should overwrite the method in the parent document that indicates the need to overwrite.
In each abstract base class, there are methods that subclasses must override. For example, to write a nsarray
class, you need to implement the count and the "Objectatlndex:" method. Like Lastobject, this method does not require real
Now, because the base class can implement this method based on the first two methods.
The specification to be followed when implementing subclasses in a class family is usually defined in the document of the base class, which should be preceded by the code
Look.
4. Key points
-Class Family mode hides implementation details behind a simple set of common interfaces.
-class families are often used in system frameworks.
-Be careful when inheriting subclasses from the common abstract base class of a class family, if you have a development document, you should read it first.

10th: Use associative objects to store custom data in existing classes
Points
-You can connect two objects by using the "associative objects" mechanism.
-You can specify memory management semantics when defining an association object to mimic the "owning relationship" that is used to define the attribute and
"Non-owning relationship".
-the association object should be used only when other practices are not available, which is often introduced in difficult-to-find
Bug

11th: Understanding the role of objc_msgsend
1.id returnvalue = [Someobject messagename:parameter];
Someobject is the recipient, MessageName: Is the method name, the method name and the parameter together are called the message
The compiler will turn this message into a function like this
ID returnvalue = Objc_msgsend (Someobject, @selecotr (messagename:
), parameter);
If a method is found, it jumps to its implementation code.
2. Key points
-The message consists of a receiver, a method name, and a parameter. Send a message to an object is also equivalent to the object "
Invoke method ".
-All messages sent to an object are handled by the dynamic message dispatch system, which detects the corresponding party
and execute its code.

12th: Understand the message forwarding mechanism (what happens when an object receives a message that cannot be read)
1. Message forwarding is initiated when the object receives a message that cannot be read (msg forwarding)
Mechanism whereby the programmer can tell the object how to handle an unknown message by this procedure
2.
3. Key points
-If the object cannot respond to a selector, it enters the message forwarding process.
-Through the dynamic method parsing function at run time, we can add it to the class when we need to use a method.
-Objects can transfer certain selector that they cannot interpret to other objects for processing.
-After the above two steps, if you still can't handle selector, then start the complete message forwarding mechanism.

Effective OBJECTIVE-C 2.0 52 effective ways to write high-quality iOS and OS X code---1-12

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.