1.調(diào)試技巧重寫description方法打印類的成員屬性
#import <objc/runtime.h>
-(NSString *)description{
unsigned int count = 0;
NSMutableString *str = [NSMutableString string];
Ivar *ivars = class_copyIvarList([self class], &count);
for(int i =0;i < count;i ++)
{
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
id value = [self valueForKey:ivarName];
//如果是最后一個變量去掉","
if (i == count -1) {
[str appendFormat:@"%@=%@",ivarName,value];
}else{
[str appendFormat:@"%@=%@,",ivarName,value];
}
}
free(ivars);
return [NSString stringWithFormat:@"%@{%@}",[super description],str];
}
2.自動歸檔解檔
//存
- (void)encodeWithCoder:(NSCoder *)aCoder{
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([TXModel class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
free(ivars);
}
//取
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([TXModel class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
free(ivars);
}
return self;
}
```
>注意:通過上面的幾個demo的演示,就不在此重復一些runtime的其他類似黑魔法了(獲取方法/屬性等等..)
3.攔截交換系統(tǒng)方法(NSObject加分類方法)
用處:分類中最好是不能重寫父類方法的,這時候要實現(xiàn)全局修改某個系統(tǒng)方法加上自己的邏輯判斷,只能用交換系統(tǒng)的方法更好.
還可以攔截系統(tǒng)奔潰.
```
@interface UIView (MethodSwizzling)
/**
* 交換對象方法
*/
+ (void)zh_swizzleInstanceSelector:(SEL)origSelector swizzleSelector:(SEL)swizzleSelector;
/**
* 交換類方法
*/
+ (void)zh_swizzleClassSelector:(SEL)origSelector swizzleSelector:(SEL)swizzleSelector;
@end
@implementation UIView (MethodSwizzling)
+ (void)zh_swizzleInstanceSelector:(SEL)origSelector swizzleSelector:(SEL)swizzleSelector {
// 獲取原有方法
Method origMethod = class_getInstanceMethod(self,origSelector);
// 獲取交換方法
Method swizzleMethod = class_getInstanceMethod(self,swizzleSelector);
BOOL isAdd = class_addMethod(self, origSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (!isAdd) {
method_exchangeImplementations(origMethod, swizzleMethod);
}else {
class_replaceMethod(self, swizzleSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
}
}
+ (void)zh_swizzleClassSelector:(SEL)origSelector swizzleSelector:(SEL)swizzleSelector
{
// 獲取原有方法
Method origMethod = class_getClassMethod(self,origSelector);
// 獲取交換方法
Method swizzleMethod = class_getClassMethod(self,swizzleSelector);
// 添加原有方法實現(xiàn)為當前方法實現(xiàn)
BOOL isAdd = class_addMethod(self, origSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (!isAdd) {
method_exchangeImplementations(origMethod, swizzleMethod);
}
}
```
>注意:實現(xiàn)load類方法 --- 類被加載運行的時候就會調(diào)用
當類加載進內(nèi)存的時候調(diào)用,而且不管有沒有子類,都只會調(diào)用一次,在main函數(shù)之前調(diào)用
```
+ (void)load
{
[self zh_swizzleInstanceSelector:@selector( setBackgroundColor:)swizzleSelector:@selector( setMyBackgroundColor:)];
}
- (void)setMyBackgroundColor:(UIColor *)color{
NSLog(@"%s",__FUNCTION__);
//此處沒有遞歸而是調(diào)用系統(tǒng)的setBackgroundColor
[self setMyBackgroundColor:[UIColor orangeColor]];
}
```
4._cmd的一種巧妙用方法(分類中關(guān)聯(lián)屬性對象)
之前需要定義一個這樣的const void *key,_cmd 是隱藏的參數(shù),代表當前方法的 selector,可以代替這個key.
之前寫法:
```
const void *webCacheKEY = "webCache";
-(void)setCurrentURL:(NSString *)currentURL{
//關(guān)聯(lián)對象
//參數(shù)1:要被關(guān)聯(lián)的對象
//參數(shù)2:關(guān)聯(lián)的KEY
//參數(shù)3:關(guān)聯(lián)的值
//參數(shù)4:關(guān)聯(lián)策略(內(nèi)存引用)
objc_setAssociatedObject(self, webCacheKEY, currentURL, OBJC_ASSOCIATION_COPY);
}
-(NSString *)currentURL{
//參數(shù)1:要被關(guān)聯(lián)的對象
//參數(shù)2:關(guān)聯(lián)的KEY
return objc_getAssociatedObject(self, webCacheKEY);
}
```
之后寫法:
```
-(void)setCurrentURL:(NSString *)currentURL{
objc_setAssociatedObject(self, _cmd, currentURL, OBJC_ASSOCIATION_COPY);
}
-(NSString *)currentURL{
return objc_getAssociatedObject(self, _cmd);
}
```
5.背景漸變色
```
- (void)viewDidLoad {
[super viewDidLoad];
[self.view.layer addSublayer:[self backgroundLayer]];
}
//背景漸變色
-(CAGradientLayer *)backgroundLayer{
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.view.bounds;
gradientLayer.colors = @[(__bridge id)[UIColor purpleColor].CGColor,(__bridge id)[UIColor redColor].CGColor];
gradientLayer.startPoint = CGPointMake(0.5, 0);
gradientLayer.endPoint = CGPointMake(0.5, 1);
gradientLayer.locations = @[@0.65,@1];
return gradientLayer;
}
```
6.調(diào)試代碼執(zhí)行時間
```
#define TICK NSDate *startTime = [NSDate date];
#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow]);
TICK
// 代碼塊
TOCK
```
7.程序啟動過程中各個階段所消耗的時間
在工程的scheme中添加環(huán)境變量DYLD_PRINT_STATISTICS = 1,這樣在調(diào)試時,可以在控制臺打印出程序啟動過程中各個階段所消耗的時間。
8.KVC集合運算符
KVC集合運算符允許在valueForKeyPath:方法中使用key path符號在一個集合中執(zhí)行方法。可以直接求出總數(shù)/最大值/最小值/平均值
```
@interface TestModel : NSObject
@property (nonatomic, assign) double price;
@end
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *priceArray = @[@"1",@"2",@"3",@"4",@"5"];
NSMutableArray *dataArray = [NSMutableArray array];
for (NSInteger i = 0; i < priceArray.count; ++i) {
TestModel *testModel = [[TestModel alloc] init];
testModel.price = [priceArray[i] doubleValue];
[dataArray addObject:testModel];
}
id count1 = [dataArray valueForKeyPath:@"@count"]; // 5
id count2 = [dataArray valueForKeyPath:@"@sum.price"]; // 15
id count3 = [dataArray valueForKeyPath:@"@avg.price"]; // 3
id count4 = [dataArray valueForKeyPath:@"@max.price"]; // 5
id count5 = [dataArray valueForKeyPath:@"@min.price"]; // 1
NSLog(@"%@,%@,%@,%@,%@",count1,count2,count3,count4,count5);
NSArray *array = [NSArray arrayWithObjects:@"2.0", @"2.3", @"3.0", @"4.0", @"10", nil];
id sum = [array valueForKeyPath:@"@sum.floatValue"];
id avg = [array valueForKeyPath:@"@avg.floatValue"];
id max = [array valueForKeyPath:@"@max.floatValue"];
id min = [array valueForKeyPath:@"@min.floatValue"];
NSLog(@"%@,%@,%@,%@",sum,avg,max,min);
}
```
9.抗鋸齒的兩種方法
第一種:
```
self.view.layer.allowsEdgeAntialiasing = YES;
```
第二種:
```
self.view.layer.borderColor = [UIColorclearColor].CGColor;
self.view.layer.borderWidth = 1.f;
```
10.調(diào)節(jié)UINavigationBar的leftBarButtonItem離左邊的距離
```
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back-button-whiteArrow.png"] style:UIBarButtonItemStylePlain target:self action:@selector(logoutBarBtnPressed:)];
UIBarButtonItem *fixedBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
fixedBarButtonItem.width = -15;
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:fixedBarButtonItem, buttonItem, nil];
```