Document directory
- NSNumber
- NSArray
- NSDictionary
Apple made significant improvements to Objective-C and LLVM compilers at WWDC 2012 this year. The new features added by Objective-C are as follows:
1. Method order independence
The Objective-C class consists of the declared file h and the implemented file m. All public methods are declared in the h file. The private method can be written in the m file, however, in the early compilation environment, you need to pay attention to the method sequence. For example, the following code will give a warning in the early compilation environment:
Class and method declaration:
@interface ObjcNewFeatures : NSObject -(void)doSomething:(NSString *) text; @end
Implementation:
@implementation ObjcNewFeatures -(void)doSomething:(NSString *)text{ NSLog(@"%@", [text stringByAppendingFormat:[selfgetCode]]); } -(NSString *)getCode{ return@"Unicode"; } @end
During early compilation, the following occurs: warning: instance method '-getCode:' not found...
This is because, according to the compilation order, the compiler does not know that there is a getCode method after doSomething, so it will give a warning. There are multiple solutions. For example, you can put the getCode method before doSomething, or declare the private method in advance, as shown below: add in the m file:
@interface ObjcNewFeatures() -(NSString *)getCode; @end
The new version of the compiler adds new features to LLVM and changes the method of sequential compilation. First, scan the method declaration and then compile the implementation part. In this way, both public and private methods are irrelevant to the order. Currently, the latest version of XCode 4.3.3 uses the default compiler Apple LLVM compiler 3.1. The above code runs normally in the latest compiling environment.
2. How can we define an enumeration type in Objective-C before OS X v10.5? As follows:
typedef enum { ObjectiveC, Java, Ruby, Python, Erlang } Language;
This method is simple and clear, and it is not complicated to use, but there is a problem that the data range of its enumerated values is fuzzy. This value may be very large, negative, and cannot be defined. In OS X v10.5 and iOS, you can write as follows:
enum { ObjectiveC, Java, Ruby, Python, Erlang }; typedef NSUInteger Language;
The advantage of this method is that the data type of this enumeration is determined, and the unsigned integer. Second, because we use NSUInteger, we do not need to consider the 32-bit and 64-bit issues. The problem is that the data type and enumeration constant are not explicitly correlated.
In XCode4.4, you can write enumeration as follows:
typedef enum Language : NSUInteger{ ObjectiveC, Java, Ruby, Python, Erlang }Language;
The enumerated data type NSUInteger is bound while listing the enumerated content. This brings enhanced type check and better code readability. Of course, for general development, the enumeration type may not involve complex data, and there is no big problem when using the previous two methods. In any case, after XCode4.4 is released, we can try a new method. 3. Attribute Synthesis
Every developer is familiar with property. We need to define attributes for the class and write the getter and setter methods. So how do we process attributes in Objective-C? It is easy to define attributes in the H file:
@property (strong) NSString *name;
Then, use the @ synthesize command in the m file to implement the attribute accessor method and define the instance variable ivar:
@synthesize name = _name;
@ Synthesize indicates that, if no overload is performed, the compiler automatically generates the getter and setter methods for the class instance variable _ name based on the read/write attributes. Of course, you can also use the @ dynamic command to specify the relevant methods for this attribute to be implemented by developers.
Does this seem simple? But there is no simplest, only simpler. In XCode4.4, We can omit @ synthesize name =Name; this line is completely implemented by the compiler. That is to say, after declaring the attribute name in the H file, you can directly use the getter and setter methods of this attribute in the implementation file and use instance variables.Name. In addition, the compiler automatically determines whether the setter method is provided based on the readable and writable attributes.
In this case, if you declare the @ dynamic attribute, what should the compiler do? All synthesize-related features will no longer work. You need to implement attributes-related methods on your own.
Take a look at the new features of attribute synthesis:
Unless explicitly stated, the property-related accessor method (getter and setter) will be automatically generated.
Unless all accessor methods provide instance variables, instance variables (such as _ name) are automatically generated.
If @ synthesize is used and the strength variable name is not provided, it is automatically generated.
If @ dynamic is used, automatic merging is invalid and must be implemented by the developer.
Core Data NSManagedObject and its subclass do not use the default attribute merging function.
4. Simplified syntax
Many people who have just switched from other programming languages to Objective-C will feel a crash when they see a long function name. However, as I mentioned in the previous article, this syntax makes message transmission like an English sentence, this greatly enhances readability. For example, if you want to initialize a floating point number, you need to write it like this:
NSNumber value = [NSNumber numberWithFloat:123.45f];
From this sentence, we can clearly understand the meaning of the code, but do we need to do the same with simple assignment statements? In this new feature, Apple adopts a compromise processing method, which is short for many basic types to simplify the syntax. After the simplification, we will find that these simplified Objective-C are more like the syntax of dynamic languages such as Python and Ruby. Next we will introduce them one by one:
NSNumber
Simplify the previous writing:
NSNumber *value; value = [NSNumber numberWithInt:12345]; value = [NSNumber numberWithFloat:123.45f]; value = [NSNumber numberWithDouble:123.45]; value = [NSNumber numberWithBool:YES];
Simplified statement:
NSNumber *value; value = @12345; value = @123.45f; value = @123.45; value = @YES;
The packing expression can also be written in a similar way:
NSNumber *piOverSixteen = [NSNumber numberWithDouble: ( M_PI / 16 )]; NSString *path = [NSString stringWithUTF8String: getenv("PATH")];
Can be abbreviated:
NSNumber *piOverSixteen = @( M_PI / 16 ); NSString *path = @( getenv("PATH") );
For a string expression, note that the expression value must not be NULL. Otherwise, an exception is thrown.
NSArray
For NSArray initialization, there are a lot of writing methods, which will not be listed here. Let's look at the new writing method directly.
NSArray * array; array = @ []; // empty array = @ [a]; // array of an object = @ [a, B, c]; // array of multiple objects
It is very simple, and there is no need to remember a bad nil when initializing arrays of multiple objects. Now let's take a look at how the compiler handles the declaration of arrays of multiple objects:
Array = @ [a, B, c]; code generated by the compiler: id objects [] = {a, B, c}; NSUInteger count = sizeof (objects) /sizeof (id); array = [NSArray arrayWithObjects: objects count: count];
Well, the compiler has already done this simple and repetitive work for us, so we can solve the real problem with peace of mind :) but note that if a, B, if the c object has nil, an exception will be thrown during runtime, which is different from the original processing method. Be careful when coding.
NSDictionary
Similarly, there are many initialization methods for the data structure of the dictionary. Let's look at the new method:
NSDictionary * dict; dict ={}; // empty dictionary dict =@{ k1: o1}; // dictionary dict containing a key-Value Pair =@{ k1: o1, k2: o2, k3: o3}; // dictionary containing multiple key-value pairs
Finally, let's take a look at the restrictions on simplified data structure of the container class: The containers built using the above method are immutable. If you need to generate a variable container, you can pass the-mutableCopy message. For example
NSMutableArray *mutablePlanets = [@[ @"Mercury", @"Venus", @"Earth", @"Mars", @"Jupiter", @"Saturn", @"Uranus", @"Neptune" ] mutableCopy];
You cannot assign values directly to the constant array. The solution is to assign values to the class method (void) initialize, as shown below:
@implementation MyClass static NSArray *thePlanets; + (void)initialize { if (self == [MyClass class]) { thePlanets = @[ @"Mercury", @"Venus", @"Earth", @"Mars", @"Jupiter", @"Saturn", @"Uranus", @"Neptune" ]; } }
No constant dictionary
5. Object subscript
The simplified syntax of the container makes it easy to think that the array and Dictionary data can be accessed through the underlying method. For example, for Arrays:
NSArray *array = @[ a, b, c ];
We can write as follows:
Id obj = array [I]; // obtain the array object by subscript. Replace the original method with array objectAtIndex: I]; array [I] = newObj; // You can also assign values directly to an array object. Replace original statement: [array replaceObjectAtIndex: I withObject: newObj];
For dictionaries:
NSDictionary *dict = @{ k1 : o1, k2 : o2, k3 : o3 };
We can write as follows:
Id obj = dict [k2]; // obtain the o2 object. Replace the original format with [dic objectForKey: k2]; dic [k2] = newObj; // assign values to objects whose keys are k2 again. Replace the original syntax with [dic setObject: newObj forKey: k2].
At the same time, as long as the preset subscript method is implemented, the container class we have defined can access data using the following method. The implementation method is as follows:
Subscript method of array type
- (elementType)objectAtIndexedSubscript:(indexType)idx; - (void)setObject:(elementType)object atIndexedSubscript:(indexType)idx;
Dictionary subscript Method
- (elementType)objectForKeyedSubscript:(keyType)key; - (void)setObject:(elementType)object forKeyedSubscript:(keyType)key;
Note that indexType must be an integer and elementType and keyType must be object pointers.
Summary
The new features of the language are introduced here. With the new version of Objective-C, you can get these new features, write more concise code, and avoid some common traps. One more thing, these syntax features are completely backward compatible. The Code Compiled using the new features can run the compiled binary program in any previously released OS.
As Apple's Mac, iPhone, and iPad sales soar, apps on the App Store formed a huge App empire, this complete ecosystem also effectively promotes the rapid development of the development language Objective-C, which maintains the characteristics of object-oriented, message transmission, and dynamic language, at the same time, we are constantly working on subtraction. The simplified syntax will greatly improve developers' efficiency, allowing developers to focus more on creativity and App implementation.
Every language is inseparable from its specific environment. Just like Lisp, Smalltalk, C, C ++, Java, C #, okay, now it's -- Objective-C.