1.寫一個類不想他被子類繼承
attribute((objc_subclassing_restricted))
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
NS_ASSUME_NONNULL_BEGIN
__attribute__((objc_subclassing_restricted))//禁止該類被繼承
@interface AAA : UIView
-(void)mustUseMethod;
@end
NS_ASSUME_NONNULL_END
2.提示子類必須調(diào)用父類方法
objc_requires_super 在父類的方法后面添加,那么子類調(diào)用該方法必須實(shí)現(xiàn)[super thisMethod],否則會黃色警告
@interface Father : NSObject
- (void)mustUseMethod __attribute__((objc_requires_super));
@end
@interface Child : TestObject
@end
@implementation BBB
-(void)mustUseMethod{
//[super mustUseMethod];
警告信息:(不報錯)
Method possibly missing a [super mustUseMethod] call
}
@end
**3 constructor / destructor **
Objective-C最后還是轉(zhuǎn)譯成C語言,當(dāng)然還有constructor / destructor
加上這兩個屬性的函數(shù)會在分別在可執(zhí)行文件(或 shared library)load 和 unload 時被調(diào)用,可以理解為在 main()函數(shù)調(diào)用前和 return 后執(zhí)行
實(shí)際上constructor會在+load之后執(zhí)行
因為 dyld(動態(tài)鏈接器)最開始會先通知 objc runtime 去加載其中所有的類,每加載一個類時,它的 +load 隨之調(diào)用,全部加載完成后,dyld 才會調(diào)用所有的 constructor 方法
__attribute__((constructor)) static void beforeMain() {
NSLog(@"before main");
}
__attribute__((destructor)) static void afterMain() {
NSLog(@"after main");
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"execute main");
}
return 0;
}
執(zhí)行結(jié)果:
debug-objc[23391:1143291] before main
debug-objc[23391:1143291] execute main
debug-objc[23391:1143291] after main
constructor后邊添加設(shè)置優(yōu)先級,控制執(zhí)行順序
__attribute__((constructor(101))) static void beforeMain() { NSLog(@"before main");
}
__attribute__((constructor(100))) static void beforeMain1() { NSLog(@"before main1");
}
__attribute__((destructor)) static void afterMain() { NSLog(@"after main");
}
執(zhí)行結(jié)果:
2019-10-12 15:48:24.015908+0800 Food[4561:144694] before main1
2019-10-12 15:48:24.016491+0800 Food[4561:144694] before main
2019-10-12 15:48:24.017145+0800 Food[4561:144694] execute main
4 overloadable 可以允許同名函數(shù)的產(chǎn)生
__attribute__((overloadable)) void testMethod(int age) {NSLog(@"%@", @(age));};
__attribute__((overloadable)) void testMethod(NSString *name) {NSLog(@"%@", name);};
__attribute__((overloadable)) void testMethod(BOOL gender) {NSLog(@"%@", @(gender));};
int main(int argc, char * argv[]) {
@autoreleasepool {
testMethod(18);
testMethod(@"lxz");
testMethod(YES);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
執(zhí)行結(jié)果:
2019-10-12 16:01:04.491366+0800 Food[4724:150619] 18
2019-10-12 16:01:04.491510+0800 Food[4724:150619] lxz
2019-10-12 16:01:04.491632+0800 Food[4724:150619] 1
5.objc_runtime_name屬性可以在編譯時,將Class或者Protocol指定為另一個名字
__attribute__((objc_runtime_name("TestObject")))
@interface AAA : NSObject
@end
int main(int argc, char * argv[]) {
@autoreleasepool {
NSLog(@"--%@",NSStringFromClass([AAA class]));
NSLog(@"----%@",NSClassFromString(@"TestObject"));
}
}
6.通過cleanup屬性,可以指定給一個變量,當(dāng)變量釋放之前執(zhí)行一個函數(shù)。指定的函數(shù)執(zhí)行時間,是在dealloc之前。在指定的函數(shù)中,可以傳入一個形參,參數(shù)就是cleanup修飾的變量,形參是一個地址。
static void releaseBefore(NSObject **object) {
NSLog(@"AAA-------%@", *object);
}
int main(int argc, char * argv[]) {
@autoreleasepool {
{
AAA *object __attribute__((cleanup(releaseBefore))) = [AAA new];
}
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
執(zhí)行結(jié)果:
2019-10-12 16:20:24.230282+0800 Food[5057:162194] AAA-------<AAA: 0x6000021c81d0>
2019-10-12 16:20:24.230633+0800 Food[5057:162194] AAA-dealloc
7.如果某個變量未使用,會提示unused xxx,可以通過unused消除這個警告
int main(int argc, char * argv[]) {
@autoreleasepool {
AAA *object __attribute__((unused)) = [AAA new];
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}