Overview
Since the launch of the WWDC 2015 and the Open source Swift 2.0, everyone's enthusiasm for Swift has soared again, while the envious startups ' friends talk about Swift's new features, as well as many developers who still need to stick to the objective-c language as I do at work. This year's WWDC introduced a few new features of the Objective-c language, or in the "Working with Swift" Topic, which underscores the marginalization of the language, but the new features are excellent, and next, this article will cover the following three main new features:
- nullability
- Lightweight generics *
- __kindof
nullability
However, nullability is not a new feature and has been supported from the previous version of LLVM 6.1 (Xcode 6.3). This short version of the Optional, without the?support of Swift and!grammar sugar, in the objective-c is very verbose:
1 2 3 |
@property (Strong, nonnull) Sark *sark; @property (nsarray *friends; NSString *) name; |
If it is used to modify a variable, the front has to double underline, put into the block inside is more strange, such as a Request of the Start method can be written as:
In addition to these two, there is a null_resettable to show setter nullable, but Getter Nonnull, the most intuitive example is the View property in Uiviewcontroller:
It can be set to nil, but invoking a getter triggers-loadViewthe creation and return of a non-nil view.
From the iOS9 SDK, it can be found that all the APIs in the header file have been added to the nullability related modifiers, to understand the use of this feature, flipping through several system header files is're far off. Interface Nullable is a few, so in order to prevent writing a large number of nonnull,foundation also provides a pair of macro, the object is wrapped in the default add nonnull modifier, only need to put nullable point to the line, slang called audited Regions:
1 2 3 4 5 6 7 |
ns_assume_nonnull_begin @interface sark: nsobject
Span class= "line" > @property (nonatomic, copy, Nullable) nsstring *workingcompany; @property (nonatomic, copy) nsarray *friends; -(Nullable nsstring *) gayfriend; @end ns_assume_nonnull_ END |
Nullability provides a type check of NULL values at the compiler level, giving warning when the type does not match, allowing developers to discover potential problems the first time. But I think the bigger point is to be able to describe the interface more clearly, is a protocol between the main and the tune, and it's clearer than how many documents are described, for example:
1 |
+ (instancetype)urlwithstring:(NSString *) urlstring; |
Nsurl this API before the addition of nullable, more explicitly pointed out that this interface may be due to the URLString format error and create a failure, the use of the natural consideration of the empty processing.
Not only the properties and objects in the method, for local objects, and even C pointers can be used with double underscore modifier, can be understood to be able to use the Const keyword where can be used nullability.
So nullability is, in general, writing ugly B, with a comfortable
Lightweight generics
Lightweight generics lightweight generics, lightweight because this is a pure compiler syntax support (LLVM 7.0), like nullability, without the help of any OBJC runtime upgrades, that is, the new syntax in Available on Xcode 7 and fully backwards compatible (lower IOS version)
A container with a generic type
This is undoubtedly the most significant improvement, and with generics you can finally specify the type of objects in the container class:
1 2 |
nsarray<nsstring *> *strings = @[@ "Yuan"]; nsdictionary<nsnumber *> *mapping = @{@ "a": @@ "B": @2}; |
After the ID of the return value is replaced with a specific type, the moving code hints come out:
If you add the wrong object to the generic container, the compiler will be unhappy:
The range of container types commonly used in the system adds generic support, even nsenumerator, which is a very nice improvement. Like nullability, I think the most important thing is to enrich the interface description information, and compare the following two kinds of wording:
1 2 |
@property (nsarray *imageurls; @property (nsarray<nsurl *> *imageurls; |
Don't think about it and know what's in the array below, avoiding the chaos of NSString and Nsurl.
Custom generic Classes
More fun than using a system generic container is to customize a generic class, and there's no documentation here, but it doesn't stop us from writing the test code, assuming we want to customize a Stack container class:
1 2 3 4 5 |
@interface Stack<objecttype>: nsobject -(void) Pushobject: (ObjectType) object; -(ObjectType) popobject; @property (nonatomic, ReadOnly) nsarray<objecttype> *allobjects; @end |
ThisObjectTypeis the placeholder of the incoming type, which can only be defined on the @interface (class declaration, Class extension, category), if you prefer T to be OK, this type is in the scope of the @interface and @end interval function, it can be used as a generic type for arguments, arguments, and even internal nsarray properties, which should say that everything is in line with expectations. We can also add type restrictions to ObjectType, such as:
1 2 3 4 |
Only generics that accept NSNumber * @interface stack<objecttype:nsnumber *>: NSObject Accept only generics that meet the Nscopying protocol @interface stack<objecttype:id<nscopying>>: NSObject |
If nothing is added, the expression accepts any type (ID), and the compiler generates an error when the type is not satisfied.
Instantiate a Stack, everything works fine:
For multi-parameter generics, separated by commas, the other is the same, you can refer to the Nsdictionary header file.
Covariance and inverse degeneration
When a class supports generics, their type changes, such as the following three objects appear to be Stack, but actually belong to three types:
1 2 3 |
* Stack*stringstack;//Stack<nsstring *> Stack*mutablestringstack;//Stack<nsmutablestring *> |
When two of these types do type conversions, the compiler needs to know which conversions are allowed and which are forbidden, for example, by default:
As we can see, a Stack that does not specify a generic type can be converted with any generic type, but after a generic type is specified, two different types cannot be strongly turned, and if you want to actively control the conversion relationship, you need to use generics for covariance and contravariance Modifier:
__covariant-Covariance, subtypes can be strongly transferred to parent type (Richter substitution principle)
__contravariant-Inverse degeneration, the parent type can be strongly transferred to subtype (WTF?)
Co-change:
Effect:
Inversion:
Effect:
Covariance is very well understood, and generics like Nsarray use covariant modifiers, and contravariance I haven't thought of any actual usage scenarios.
__kindof
__kindof This modifier is still very practical, solve a long-term small pain point, take the original UITableView this method:
1 |
-(ID)dequeuereusablecellwithidentifier:(NSString *) identifier; |
Using a pointer to the UITableViewCell subtype is used to receive the return value, so the API is designed so that the developer does not have to write explicit strong turns each time the egg hurts, the return value is defined as the ID type, and the API actually means to return a UITableViewCell Or an instance of the UITableViewCell subclass, the new __KINDOF keyword solves the problem:
1 |
-(__UITableViewCell *)dequeuereusablecellwithidentifier:(NSString *) identifier; |
The return value is clearly indicated and the user does not have to write a strong turn. To give an example with generics, the Subviews property of UIView is changed to:
1 |
@property (UIView *> *subviews; |
This way, there is no warning when writing the following code:
1 |
UIButton *button = view.subviews. Lastobject; |
Where to go
With these new features described above and historical updates such as instancetype , the type detection and type inference of Objective-c's ancient language has finally improved, and there are now fewer types of IDs in both interfaces and code. More potential type errors can be found by the static check of the compiler.
At the same time, the personal feel of the new version of Xcode on the inheritance chain constructor detection also strengthened,Ns_designated_initializer This macro is not a new face, you can use it to mark the same as Swift, the constructor and the convenient constructor.
Finally, with a piece of code that uses all the new features, Swift is a trend, and if you are still writing objective-c code for the time being, use all the new features, perhaps making your migration to the new language painless.
The source of this article: http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/
Objective-c new Features