面向切面編程簡(jiǎn)介
就是在不需要改變?cè)创a邏輯的前提下,給系統(tǒng)的方法增加一些邏輯進(jìn)去,并且這個(gè)邏輯是在整個(gè)程序的生命周期之內(nèi)都能夠應(yīng)用.
1.方法的交換
首先在寫一個(gè) NSObject 的分類,在分類里定義一個(gè)交換方法的方法.利用 runtime 獲取需要交換的方法,以及我們自己定義的去交換系統(tǒng)的方法的方法;得到這兩個(gè)方法之后,就把方法交換.
+(void)aop_changeMethod:(SEL)oldMethod newMethod:(SEL)newMethod
{
//系統(tǒng)的方法
Method oldM = class_getInstanceMethod([self class], oldMethod);
//自己定義與系統(tǒng)方法去交換的方法
Method newM = class_getInstanceMethod([self class], newMethod);
//交換方法
method_exchangeImplementations(oldM, newM);
}
2.利用 AOP 進(jìn)行權(quán)限控制
問(wèn)題情況:
在一個(gè) app 中,當(dāng)用戶點(diǎn)擊的個(gè)人信息頁(yè)面的時(shí)候,我們需要做一個(gè)權(quán)限控制.如果用戶已經(jīng)登陸,則可以順利進(jìn)入個(gè)人主頁(yè).如果沒(méi)有登陸,則需要彈出一個(gè)用戶登陸界面讓用戶登陸.登陸成功才能進(jìn)到下一個(gè)頁(yè)面.
解決問(wèn)題:
在用戶點(diǎn)擊"我的"模塊的時(shí)候,對(duì)用戶是否登陸進(jìn)行判斷.因?yàn)橛昧藢?dǎo)航控制器包裝,所以用戶點(diǎn)擊進(jìn)入下一頁(yè)是 push的方式 .我們只要在pushViewController:animated:
方法中對(duì)用戶是否登陸進(jìn)行判斷.所以利用 aop 的思想,自己定義一個(gè)方法aop_pushViewController:animated:
交換系統(tǒng)的pushViewController:animated:
方法,然后在自己定義的方法中進(jìn)行判斷,這樣就實(shí)現(xiàn)了不改變?cè)创a的前提對(duì)方法進(jìn)行功能增加.
代碼:
/**
* 系統(tǒng)會(huì)在所有方法執(zhí)行之前調(diào)用load方法,并且只會(huì)調(diào)用一次
* 我們可在load方法中,編寫一些只需要執(zhí)行一次的配置相關(guān)邏輯
*/
+(void)load
{
[UINavigationController aop_changeMethod:@selector(pushViewController:animated:) newMethod:@selector(aop_pushViewController:animated:)];
}
-(void)aop_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//1.在執(zhí)行真正的push之前添加一些其他邏輯
NSLog(@"push 執(zhí)行之前執(zhí)行一些列代碼");
//進(jìn)行權(quán)限判斷,如果已經(jīng)登錄的用戶可以隨意push任何頁(yè)面
if(self.viewControllers.count > 0){
NSUserDefaults * df = [NSUserDefaults standardUserDefaults];
//取出用戶信息
NSString * name = [df objectForKey:@"name"];
//哪些頁(yè)面需要驗(yàn)證才能進(jìn)入
NSString * path = [[NSBundle mainBundle] pathForResource:@"auth.plist" ofType:nil];
NSArray * tmp = [NSArray arrayWithContentsOfFile:path];
//遍歷需要驗(yàn)證的頁(yè)面,
for(NSString * className in tmp)
{
//模擬用戶的驗(yàn)證
if([className isEqualToString:NSStringFromClass([viewController class])])
{
if(name == nil || name.length < 6)
{
//驗(yàn)證不通過(guò),就進(jìn)入用戶登陸界面
GPLoginViewController * loginView = [[GPLoginViewController alloc] init];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:loginView];
[self presentViewController:nav animated:YES completion:nil];
return;
}
}
}
}//end if (self.viewControllers.count > 0)
//2.沒(méi)有登錄的就跳入登錄頁(yè)面
[self aop_pushViewController:viewController animated:animated];
//2.在原邏輯執(zhí)行之后,添加一些邏輯代碼
NSLog(@"push 執(zhí)行之后執(zhí)行一些列代碼");
}
新手,文章存在不足,感謝大家批評(píng)指正!