FOUNDATION_EXTERN
定义
#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif
表示 extern 全局变量,此时并没有分配内存,需要在.m文件中实现,此时为了支持C和C++混编(__cplusplus 是C++编译器内部定义的宏,在C++中,需要加 extern"C" 或包含在 extern "C" 块中),注意,此时外界是可以修改这个值,详细 extern 用法可自行查询相关资料,本文不详谈。
用法如下:
FOUNDATION_EXTERN NSString *name;// h文件
const NSString *name = @"gitKong";// m文件
FOUNDATION_EXPORT,FOUNDATION_IMPORT
定义
#if TARGET_OS_WIN32
#if defined(NSBUILDINGFOUNDATION)
#define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
#else
#define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
#endif
#define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)
#else
#define FOUNDATION_EXPORT FOUNDATION_EXTERN
#define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
用法如下:
用法跟 FOUNDATION_EXTERN 一样,不再举例。
NS_NONATOMIC_IOSONLY
定义
// Marks APIs whose iOS versions are nonatomic, that is cannot be set/get from multiple threads safely without additional synchronization
#if !defined(NS_NONATOMIC_IOSONLY)
#if TARGET_OS_IPHONE
#define NS_NONATOMIC_IOSONLY nonatomic
#else
#if __has_feature(objc_property_explicit_atomic)
#define NS_NONATOMIC_IOSONLY atomic
#else
#define NS_NONATOMIC_IOSONLY
#endif
#endif
#endif
用法如下:
@property (NS_NONATOMIC_IOSONLY,copy) NSString *className;
NS_NONATOMIC_IPHONEONLY
定义
// Use NS_NONATOMIC_IOSONLY instead of this older macro
#if !defined(NS_NONATOMIC_IPHONEONLY)
#define NS_NONATOMIC_IPHONEONLY NS_NONATOMIC_IOSONLY
#endif
历史原因,等同 NS_NONATOMIC_IOSONLY,苹果建议使用NS_NONATOMIC_IOSONLY
用法如下:
用法和NS_NONATOMIC_IOSONLY
一样
NS_REQUIRES_SUPER
#ifndef NS_REQUIRES_SUPER
#if __has_attribute(objc_requires_super)
#define NS_REQUIRES_SUPER __attribute__((objc_requires_super))
#else
#define NS_REQUIRES_SUPER
#endif
#endif
摘自文档:
- Some Objective-C classes allow a subclass to override a particular method in a parent class but expect that the overriding method also calls the overridden method in the parent class. For these cases, we provide an attribute to designate that a method requires a “call to super” in the overriding method in the subclass.
- This attribute can only be applied the method declarations within a class, and not a protocol. Currently this attribute does not enforce any placement of where the call occurs in the overriding method (such as in the case of -dealloc where the call must appear at the end). It checks only that it exists.
用法如下:
- (void)oc_method_mustCallSuper NS_REQUIRES_SUPER;// 父类中声明
- (void)oc_method_mustCallSuper{
[super oc_method_mustCallSuper];// 子类中实现需要调用super
}
NS_DESIGNATED_INITIALIZER
定义
#ifndef NS_DESIGNATED_INITIALIZER
#if __has_attribute(objc_designated_initializer)
#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
#else
#define NS_DESIGNATED_INITIALIZER
#endif
#endif
摘自原文: To clarify the distinction between designated and secondary initializers clear, you can add the NS_DESIGNATED_INITIALIZER macro to any method in the init family, denoting it a designated initializer. Using this macro introduces a few restrictions:
- The implementation of a designated initializer must chain to a superclass init method (with [super init…]) that is a designated initializer for the superclass.
- The implementation of a secondary initializer (an initializer not marked as a designated initializer within a class that has at least one initializer marked as a designated initializer) must delegate to another initializer (with [self init…]).
- If a class provides one or more designated initializers, it must implement all of the designated initializers of its superclass.
用法如下:
- (instancetype)initWithClassName:(NSString *)name NS_DESIGNATED_INITIALIZER;// 方法声明
- (instancetype)initWithClassName:(NSString *)name{// 方法实现
if (self = [super init]) {
self.className = name;
}
return self;
}
此时编译器就会出现警告,原因很简单,本类中实现了 NS_DESIGNATED_INITIALIZER 那么必须实现父类的 NS_DESIGNATED_INITIALIZER 方法
实现父类的 init 方法,因为 init 也是NS_DESIGNATED_INITIALIZER 修饰
- (instancetype)init{
self.className = @"";
return self;
}
当然,此时毫无疑问会出现编译警告,原因很简单,本类中实现了 NS_DESIGNATED_INITIALIZER ,那么构造方法中必须调用NS_DESIGNATED_INITIALIZER 方法,因此这里就有个大坑,操作不慎容易造成循环调用,下面会解释
实现父类的
init
方法并调用NS_DESIGNATED_INITIALIZER
修饰的方法
- (instancetype)init{
return [self initWithClassName:@"gitKong"];
}
- (instancetype)initWithClassName:(NSString *)name{
if (self = [super init]) {
self.className = name;
}
return self;
}
NS_UNAVAILABLE、UNAVAILABLE_ATTRIBUTE
定义
#if !defined(NS_UNAVAILABLE)
#define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE
#endif
/*
* only certain compilers support __attribute__((unavailable))
*/
#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
#else
#define UNAVAILABLE_ATTRIBUTE
#endif
摘自原文:This declaration is never available on this platform.
用法如下:
- (void)sayHi NS_UNAVAILABLE;
NS_AVAILABLE、NS_DEPRECATED 等
定义
#include <CoreFoundation/CFAvailability.h>
#define NS_AVAILABLE(_mac, _ios) CF_AVAILABLE(_mac, _ios)
#define NS_AVAILABLE_MAC(_mac) CF_AVAILABLE_MAC(_mac)
#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)
#define NS_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) CF_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, __VA_ARGS__)
#define NS_DEPRECATED_MAC(_macIntro, _macDep, ...) CF_DEPRECATED_MAC(_macIntro, _macDep, __VA_ARGS__)
#define NS_DEPRECATED_IOS(_iosIntro, _iosDep, ...) CF_DEPRECATED_IOS(_iosIntro, _iosDep, __VA_ARGS__)
#define NS_DEPRECATED_WITH_REPLACEMENT_MAC(_rep, _macIntroduced, _macDeprecated) API_DEPRECATED_WITH_REPLACEMENT(_rep, macosx(_macIntroduced, _macDeprecated)) API_UNAVAILABLE(ios, watchos, tvos)
#define NS_ENUM_AVAILABLE(_mac, _ios) CF_ENUM_AVAILABLE(_mac, _ios)
#define NS_ENUM_AVAILABLE_MAC(_mac) CF_ENUM_AVAILABLE_MAC(_mac)
#define NS_ENUM_AVAILABLE_IOS(_ios) CF_ENUM_AVAILABLE_IOS(_ios)
#define NS_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, ...) CF_ENUM_DEPRECATED(_macIntro, _macDep, _iosIntro, _iosDep, __VA_ARGS__)
#define NS_ENUM_DEPRECATED_MAC(_macIntro, _macDep, ...) CF_ENUM_DEPRECATED_MAC(_macIntro, _macDep, __VA_ARGS__)
#define NS_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep, ...) CF_ENUM_DEPRECATED_IOS(_iosIntro, _iosDep, __VA_ARGS__)
#define NS_AVAILABLE_IPHONE(_ios) CF_AVAILABLE_IOS(_ios)
#define NS_DEPRECATED_IPHONE(_iosIntro, _iosDep) CF_DEPRECATED_IOS(_iosIntro, _iosDep)
...
NS_ENUM、NS_OPTIONS
定义
/* NS_ENUM supports the use of one or two arguments. The first argument is always the integer type used for the values of the enum. The second argument is an optional type name for the macro. When specifying a type name, you must precede the macro with 'typedef' like so:
typedef NS_ENUM(NSInteger, NSComparisonResult) {
...
};
If you do not specify a type name, do not use 'typedef'. For example:
NS_ENUM(NSInteger) {
...
};
*/
#define NS_ENUM(...) CF_ENUM(__VA_ARGS__)
#define NS_OPTIONS(_type, _name) CF_OPTIONS(_type, _name)
摘自原文:Use
__has_feature(objc_fixed_enum)
to determine whether support for fixed underlying types is available in Objective-C .
用法就不再举例,相信大家都用烂了~
NS_ASSUME_NONNULL_BEGIN、NS_ASSUME_NONNULL_END
定义
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#pragma clang assume_nonnull begin
#pragma clang assume_nonnull end
用法如下:(Xcode10创建文件默认添加)
//NS_ASSUME_NONNULL_BEGIN
#pragma clang assume_nonnull begin
@interface MacrosIntroduction:NSObject
@property (nonatomic,assign) FLSystemEnum systemEnums;
@property (nullable, nonatomic,copy) NSString *xxx;
@end
#pragma clang assume_nonnull end
//NS_ASSUME_NONNULL_END
最后
- 本文摘自,感谢作者的努力!