ios-@inerface 11 Standard notation

Source: Internet
Author: User
Tags deprecated modifiers

Summarize some of the specifications of the interface declaration, the introduction of the relevant macro, define the method useful modifiers, write the specification of the annotations, and finally write a qualified header file.

    • 1. Read and Write permissions
      • 1.1 Instance variable @public, @protected, @private keyword
      • The Readonly,readwrite keyword for the 1.2 property
    • 2. Forward statement
    • 3. Exposing only the necessary interfaces and implementations
      • 3.1 Do not expose any private methods that are only used inside the class
      • 3.2 Do not declare protocol in the header file that the class is following
    • 4.nullability description
    • 5. Defining enumerations
      • 5.1 Ns_enum
      • 5.2 Ns_options
      • 5.3 String Enumeration
    • 6. Use extern to provide read-only constants externally
    • 7. Provide private properties of the parent class to subclasses and categories
    • 8. Mark designated initializer
    • 9.API version Control
      • 9.1 Available
      • 9.2 Unavailable
      • 9.3 Deprecated
    • 10. Additional Modifiers
      • 10.1 generic type
      • 10.2 Ns_requires_super
      • 10.3 Ns_noescape
    • 11. Write a comment
      • 11.1 Single-line comment
      • 11.2 Multi-line comments
      • 11.3 Enumeration Comments
      • 11.4 Several annotation conventions
1. Read and Write permissions

The declarations in the. h file are for exposing to external interfaces, while private methods, private properties, and instance variables inside the class should be placed in the interface extension of the. m file.

1.1 Instance variable @public, @protected, @private keyword

These 3 keywords are used to decorate an instance variable and cannot be used to decorate a property. When an instance variable is used incorrectly, Xcode prompts you for an error.

Key Words Description
@private The scope can only be in its own class
@protected The scope is in its own class and inherits its own subclass, nothing is written, the default is this property.
@public The scope of the action is the largest, anywhere.

Example code:

//SearchManager.h@interface SearchManager : NSObject {    @public    NSInteger *state;    @public    NSInteger *timeout;    @protected id *searchAPI;    @private   id _privateIvar;}@end

Because private variables are exposed and there are no high-level keywords for @property, instance variables are rarely declared in the header file. Prefer to use @property.

The Readonly,readwrite keyword for the 1.2 property

The attributes in the header file are a collection of attributes that describe the object. When declaring @property, use ReadOnly in. h to allow external read-only permissions and use ReadWrite in. m to have read and write access to the internal.

Example code:

readonly) NSInteger * state;@end
//SearchManager.m@interface SearchManager : NSObject@property (nonatomic, readwrite) NSInteger * state;@end
2. Forward statement

When other classes are used in the @interface interface, do not import the header files of the class directly in. h, which will allow the use of this header file to also import these unnecessary other header files. The correct approach is @class to use the keyword to make a forward declaration. Of course, if you inherit the parent class, you still need to import the parent class's header file. Example code:

//SearchManager.h#import "SearchManagerBase.h"//导入父类的头文件@class LocationModel;//前向声明LocationModel类typedef void(^LocationSearchCompletionHandler)(LocationModel *location, NSError *error);@interface LocationSearchManager : SearchManagerBase- (void)searchLocationWithKeyword:(NSString *)keyword completionHandler:(LocationSearchCompletionHandler)completionHandler;@end

Using @class tells the compiler that a class exists, but it does not care about the specific implementation of the class, until the caller uses it in. m to import the class. Declare a class and a protocol, using @class and @protocol, respectively. There are two reasons to use a forward reference:

    • Improve compilation efficiency. If import is in place LocationModel.h , LocationModel.h all import will LocationModel.h need to be recompiled when the content changes. If. M is referenced SearchManager.h , but not used LocationModel , it increases unnecessary compilation and reduces development efficiency.
    • Resolve cross-reference issues. If the header file of Class A imports B, the header file of Class B imports a, which causes an error at compile time: "Can not find interface declaration", because OBJECTIVE-C does not allow cross-references.
3. Expose only the necessary interfaces and implementations 3.1 do not expose any private methods that are used only within the class

The header file only declares those public methods that are used externally, and is designed with testability in mind and a single duty. Private methods are defined only within the class, and for the sake of differentiation, it is recommended to prefix the private method, for example - (void)p_myPrivateMethod . Because Apple declares in its code specification that Apple has an underlined method prefix, as it NS UI does with these class name prefixes, it is not recommended that our private methods use underscores directly as prefixes. Otherwise, when you inherit the class of cocoa touch, it is possible to overwrite the private method of the parent class, causing errors that are difficult to debug.

3.2 Do not declare protocol in the header file that the class is following

Example code for the error :

readonly) NSInteger * state;@end

UITableViewDelegateIt is the protocol that is used within the class and is not necessarily exposed to the outside, so it should be placed in the. m file. The NSCoding characteristics of the class are described to tell the external class that the archive can be used, so it should be placed in the header file.

4.nullability description

When declaring, you can use the following keywords to describe whether an object can be nil.

Key Words Description
Nullable Nullable, used to describe the OBJC object
Nonnull Not nullable, used to describe the OBJC object
Null_unspecified Indeterminate, used to describe the OBJC object
Null_resettable Set is nullable, get is not empty. For property only
_nullable Nullable, used to describe the C pointer and block
_nonnull Not NULL, used to describe the C pointer and block
_null_unspecified Indeterminate, used to describe the C pointer and block

Example code:

//SearchManager.h#import "SearchManagerBase.h"@class LocationModel;typedef void(^LocationSearchCompletionHandler)(LocationModel *_Nullable location, NSError *_Nullable error);@interface LocationSearchManager : SearchManagerBase- (void)searchLocationWithKeyword:(nonnull NSString *)keyword completionHandler:(LocationSearchCompletionHandler _Nonnull)completionHandler;@end

If you empty a value with a nonnull adornment, the compiler gives a warning. At development time, most of the time, nonnull is used, so Apple provides a pair of macros NS_ASSUME_NONNULL_BEGIN and a NS_ASSUME_NONNULL_END quick retouching, a property written in two macros, and a method that uses nonnull adornments. Example code:

//LocationSearchManager.h#import "SearchManagerBase.h"@class LocationModel;NS_ASSUME_NONNULL_BEGINtypedef void(^LocationSearchCompletionHandler)(LocationModel *_Nullable location, NSError *_Nullable error);@interface LocationSearchManager : SearchManagerBase- (void)searchLocationWithKeyword:(NSString *)keyword completionHandler:(LocationSearchCompletionHandler)completionHandler;@endNS_ASSUME_NONNULL_END
5. Defining enumerations

For the difference between Ns_enum and Ns_options, refer to here. In simple terms, Ns_options provides a bitmask-based feature.

5.1 Ns_enum

Example code:

typedef NS_ENUM(NSInteger,SearchState) {    SearchStateNotSearch,    SearchStateSearching,    SearchStateSearchFinished,    SearchStateSearchFailed};
5.2 Ns_options

Sample code, reference NSKeyValueObserving.h :

typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {    NSKeyValueObservingOptionNew,    NSKeyValueObservingOptionOld,    NSKeyValueObservingOptionInitial,    NSKeyValueObservingOptionPrior};

When used, you can | combine multiple option:

forKeyPath:@"title" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL];
5.3 String Enumeration

When a dictionary is passed as a parameter, or as a return value, it is often difficult to provide a dictionary key directly, and now a string enumeration is used to solve the problem. Sample code, reference NSKeyValueObserving.h :

//使用NS_STRING_ENUM宏,定义了一个枚举类型typedef NSString * NSKeyValueChangeKey NS_STRING_ENUM;FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeKindKey;FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeNewKey;FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeOldKey;FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeIndexesKey;FOUNDATION_EXPORT NSKeyValueChangeKey const NSKeyValueChangeNotificationIsPriorKey;//使用泛型,声明了change参数用到的key,是在NSKeyValueChangeKey的枚举范围中- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;
6. Use extern to provide read-only constants externally

It's not about @interface, but it's all about the head file.

//SearchManager.hextern NSString *const SearchErrorDomain;extern NSInteger SearchDefaultTimeout;@interface SearchManager : NSObject@end
//SearchManager.mNSString *const SearchErrorDomain = @"SearchErrorDomain";const NSInteger SearchDefaultTimeout = 20;@interface SearchManager()@end
7. Provide private properties of the parent class to subclasses and categories

Because the header files of the class only store those properties and methods that are exposed to the external, you encounter obstacles when you encounter these situations:

    • In subclasses or categories, you want to use the parent class to define a private property in. M.
    • In the header file of the class, the attribute is readonly, but in the subclass or category, the ReadWrite permission is required. Since these properties are not exposed in the header file, it is necessary to create a separate private header file to hold the attributes that need to be exposed to subclasses and categories. You can refer to Apple's official UIGestureRecognizerSubclass.h . Example code:
readonly) SearchState state;@end
//SearchManager.m@interface SearchManager()///内部使用,有读写权限@property (nonatomic, assign) SearchState state;///只在内部使用的私有属性@property (nonatomic, strong) id searchAPI;@end
 ///private properties and private methods that are exposed to subclasses and categories//searchmanagerinternal.h///restrict the use of this header file, Prevent misuse by other classes  #ifdef searchmanager_protected_access #import " SearchManager.h "@interface Searchmanager ()///In internal.h, re-declared as ReadWrite permission @property (nonatomic, ReadWrite, assign) Searchstate state;///exposes private properties @property (Nonatomic, strong) ID searchapi;///exposes private methods-(void) P_privatemethod; @end  #else  #error only being included by Searchmanager ' s subclass or category!< Span class= "hljs-comment" > #endif       
///category的实现文件//SearchManager+Category.m///声明私有头文件的使用权限#define SEARCHMANAGER_PROTECTED_ACCESS///导入私有头文件#import "SearchManagerInternal.h"@implementation SearchManager(Category)- (void)categoryMethod {    //拥有了读写权限    self.state = SearchStateSearching;    //可以访问私有属性    [self.searchAPI startSearch];    //可以使用私有方法    [self p_privateMethod];}@end

SearchManagerInternal.hIn fact, it is also public, other classes can be imported and used, only in the development of the contract. If you want to restrict the import of other classes and prompt for errors, Internal.h you can use the following methods:

#ifdef MYCLASS_PROTECTED_ACCESS//声明部分#else#error Only be included by MYCLASS‘s subclass or category!#endif

This generates a compilation warning if it is accidentally imported in another class Internal.h and cannot be used directly. The disadvantage is that it needs to be used everywhere Internal.h #define MYCLASS_PROTECTED_ACCESS .

8. Mark designated initializer

Specifies the initialization method, which is the initialization method that receives the most parameters, which is called by other initialization methods, and is designed to ensure that the instance variables are initialized correctly by all initialization methods. Add a macro to the back of the method NS_DESIGNATED_INITIALIZER . Thus, when you subclass this class, the compiler gives a warning if the designated initializer of the parent class is not correctly called in the initialization method of the subclass. Instance code:

@interface WKWebView : UIView- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;@end

For more detailed instructions on designated initializer, refer to:

    • OBJECTIVE-C Supplements: Designated initializer
    • Several principles of correctly writing designated initializer
9.API version Control

When updating an interface, or developing the framework, it is necessary to indicate the version information that informs the user of the platform limitations of this interface, the operating system version, whether it is available, whether it has been deprecated, and so on. Apple gives a few of its own macros to mark the version, and Xcode warns you when it detects an error. Just add the corresponding macro to the method name.

9.1 Available

Declares the minimum supported operating system version of this interface. When your interface uses the APIs of the new system, such as the uialertcontroller above iOS8, but the deployment target of the project is iOS7, the version information of this interface needs to be marked to allow the user to be compatible. Example:

//SearchManager.htypedef NS_ENUM(NSInteger,SearchState) {    SearchStateNotSearch,    SearchStateSearching,    SearchStateSearchFinished,    SearchStateSearchFailed} NS_ENUM_AVAILABLE_IOS(2_0);//此枚举在iOS2.0以上才能使用NS_CLASS_AVAILABLE_IOS(2_0) //此类在iOS2.0以上才能使用@interface SearchManager : NSObject- (void)reSearch NS_AVAILABLE_IOS(5_0);//此方法在iOS5.0以上才能使用@end

These macros have a corresponding version of the platform, such as Ns_available_mac, Ns_available_ios, Ns_available_iphone. IOS10 has started to provide a new available macro API_AVAILABLE that unifies MacOS, IOS, WatchOS, tvOS, and several platforms.

API_AVAILABLE(macos(10.10))API_AVAILABLE(macos(10.9), ios(10.0))API_AVAILABLE(macos(10.4), ios(8.0), watchos(2.0), tvos(10.0))
9.2 Unavailable

Declares that this interface is not available, and most of the time it is used to declare the platform limit. Example:

@interface SearchManager : NSObject- (void)searchInWatch NS_UNAVAILABLE;//不能用此接口- (void)searchInHostApp NS_EXTENSION_UNAVAILABLE_IOS;//extension里不能用此接口- (void)search __TVOS_PROHIBITED;//tvOS里不能用此接口,可修饰枚举,类,方法,参数@end

IOS10 begins with the new unavailable macro API_UNAVAILABLE :

API_UNAVAILABLE(macos)API_UNAVAILABLE(watchos, tvos)
9.3 Deprecated

Declares that this interface has been deprecated and can be annotated with an alternate interface. Xcode gives a warning when the deployment target version number is set to a version number that is greater than or equal to the deprecated method. Example:

"UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead")@interface UIAlertView : UIView@end
//注明废弃API@interface UIViewController : UIResponder- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0);@end
//注明废弃枚举typedef NS_ENUM(NSInteger, UIStatusBarStyle) {    UIStatusBarStyleDefault                                     for use on light backgrounds    UIStatusBarStyleLightContent     NS_ENUM_AVAILABLE_IOS(7_0) = 1, // Light content, for use on dark backgrounds        UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,    UIStatusBarStyleBlackOpaque      NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,}

IOS10 begins with the new deprecated macros API_DEPRECATED and API_DEPRECATED_WITH_REPLACEMENT . The former can indicate the reason for abandonment, the latter can indicate an alternative interface.

API_DEPRECATED("No longer supported", macos(10.4, 10.8))API_DEPRECATED("No longer supported", macos(10.4, 10.8), ios(2.0, 3.0), watchos(2.0, 3.0), tvos(9.0, 10.0))API_DEPRECATED_WITH_REPLACEMENT("-setName:", tvos(10.0, 10.4), ios(9.0, 10.0))API_DEPRECATED_WITH_REPLACEMENT("SomeClassName", macos(10.4, 10.6), watchos(2.0, 3.0))
10. Additional Modifier 10.1 generics

When declaring, adding a generic adornment to an object of the collection type, you can declare the data type stored in the collection. For example:

@property (nonatomic, strong) NSMutableArray<NSString *> *myArray;

When you myArray put a non- NSString * type object in, the compiler gives a warning.

@property(nonatomic, strong) NSMutableArray<__kindof UIView *> * viewArray;

_kindofSubclasses that are only qualified for storage types UIView , and therefore can also be stored, UIView for example UIButton . More detailed introduction, reference: New charm of objective-c language--nullability, generic set and type extension

10.2 Ns_requires_super

NS_REQUIRES_SUPERMacros are used to declare subclasses when this method of the parent class is overloaded, the method of the parent class needs to be called. For example:

- (void)viewWillAppear:(BOOL)animated NS_REQUIRES_SUPER;
10.3 Ns_noescape

NS_NOESCAPEUsed to modify the block type parameters in the method, for example:

@interface NSArray: NSObject- (NSArray *)sortedArrayUsingComparator:(NSComparator NS_NOESCAPE)cmptr@end

The function is to tell the compiler that cmptr the block sortedArrayUsingComparator: will be executed before the method returns, rather than being saved and executed at some point later. Similar to this implementation:

- (void)performWithLock:(NS_NOESCAPE void (^)())block {  // exposed as @noescape to Swift    [myLock lock];    block();    [myLock unlock];}

Once the compiler knows, it will do some optimizations, such as removing some extra pairs self of captures, retain, and release operations. Because the block's survival is limited to this method, there is no need to retain it within the block self . For a more detailed introduction, refer here.

11. Write a comment

A header file is a document that requires users to quickly know what the class does. A good method name can be quickly understood by the user, but most of the time it requires a corresponding comment. Once you've written a formatted comment, when the cursor rests on the method name and property, the comment appears in the quick Help bar on the right side of Xcode, and the option comment box pops up when you press and hold and click.

11.1 Single-line comment

Used directly on the previous line of a method or property declaration /// , followed by annotations, and compatible with Xcode and Appledoc. Xcode is also supported //! , but Appledoc is not supported.

readonly) NSInteger * state;@end
11.2 Multi-line comments

Multi-line annotations are used:

/** 注释内容*/

XCODE8 provides shortcut keys for quickly generating formatted comments: option + command + / . If the method has parameters, the @param keyword is added automatically to describe the corresponding parameter. Apple provides the official Headdoc syntax, but many of them have been invalidated in Xcode, and some keywords are incompatible with appledoc. Here are a few of the keywords that are still valid in Xcode:

/** 演示苹果headDoc的语法。这里可以写方法简介  @brief 方法的简介(appleDoc不支持此关键字) @discussion 方法的详细说明  @code //示例代码(这个在Xcode里常用,但是appleDoc不支持此关键字) UIView *view; @endcode  @bug       存在的bug的说明 @note      需要注意的提示 @warning   警告 @since     iOS7.0 @exception 方法会抛出的异常的说明  @attention 注意,从这里开始往下的关键字,appleDoc都不支持 @author    编写者 @copyright 版权 @date      日期 @invariant 不变量 @post      后置条件 @pre       前置条件 @remarks   备注 @todo      todo text @version   版本 */- (void)sampleMethod;

In Xcode, you'll see this:

11.3 Enumeration Comments

If you want to give an enumeration comment, you need to comment before each enumeration value, in the following format:

///搜索状态typedef NS_ENUM(NSInteger,SearchState) {    ///没有开始搜索    SearchStateNotSearch,    ///搜索中    SearchStateSearching,    ///搜索结束    SearchStateSearchFinished,    ///搜索失败    SearchStateSearchFailed};
11.4 Several annotation conventions

What you need to comment on:

    • Try to add a description to the class, even if there is a sentence.
    • Indicate the default values for some parameters and properties, such as time-outs.
    • If the property is KVO compatible, that is, externally you can use KVO to listen to this property, which is declared in the property comment.
    • The callback block parameter needs to describe the thread in which the callback is located, avoiding the need for the user to make redundant thread judgments in the block.
    • If necessary, describe the preconditions that are required to use this API to prevent them from being called incorrectly.
    • The use of method Swizzling API for uniform form of labeling, easy to encounter runtime bug when troubleshooting.
Reference
    • blog.sunnyxx.com/2014/04/13/...
    • blog.sunnyxx.com/2015/06/12/...

[email protected] 11 standard notation

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.