日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

块语法Block在MVC思维的妙用之多重M层代理传值

發布時間:2024/9/30 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 块语法Block在MVC思维的妙用之多重M层代理传值 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? 注:以下代碼均來自真實項目案例。

? ?

? ?在項目開發中,經常避免一些與系統工具交互的功能需求。比如說開啟藍牙,開啟相機,通訊錄功能,還有數據加密等等。

? ?由于這些功能的實現沒有實例化的必要,并且又是許多項目都共用的功能,所以一般我們會作為類的靜態方法去作為自己的工具類。

??

? 以下是一段將字典的鍵值對導入通訊錄的靜態方法代碼。

? 假如說現在有一個這樣的邏輯流程,C層按鈕交互,將頁面某個數據加密導入通訊錄。

? 讓我們以MVC的思維梳理一下整過流程。

? 在這整個事件中,有三個參與者。頁面(C層),加密(M層),通訊錄導入(M層)。

? 為了簡寫,我們把頁面(C)定義為A,加密(M層)定義為B,通訊錄導入(M層)定義為C。

? 結果也有三種,第一種是導入失敗,第二種是能夠導入成功但是通訊錄中已經存在該聯系人(需要提示A【用戶】該次導入是否要覆蓋掉已經存在的聯系人),第三種是能夠導入成功并且通訊錄中沒有該聯系人。

? 方案也有三種,第一種是A將加密導入通訊錄指令告知B,B執行加密命令后再將數據傳遞給C,C進行通訊錄導入將結果告知B,B再告知C。 實現上為了簡潔可以將該邏輯代碼封裝為B的一個方法,B調用C的靜態方法將返回參數通過自己的方法告知A,B和C的兩個方法返回參數為int類型123分別表示三種情況。

? 第二種方案跟第一種方案類似,主要是由于int類型的表述結果不夠直觀,可以通過回調代理去執行,如-(void)setAddressSuccess ? ?-(void)setAddresFaild ??-(void)setAddresExist ?代理方式更為直觀,便于開發人員自身檢測以及維護人員維護。

? 第三種方案是A將處理三種結果的代碼塊作為Block參數送給B,B執行完加密之后將A交于自己的Block送給C,C在執行完導入操作之后直接執行Block,不需要將自己的結果告知任何人。


? ?以下代碼是第二種方案和第三種方案融合處理,主要為了便于看到各種方案的利與弊。

? ?首先是C的靜態方法

+ (BOOL)SetAddressBookWithInfo:(NSMutableDictionary *)info RePetBlock:(void (^)(void))block

{

? ? //獲取通訊錄信息

? ? ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(nil, nil);

? ? // ABRecordRef是一個屬性的集合,相當于通訊錄中聯系人的對象

? ? ABRecordRef person = ABPersonCreate();

? ? //寫入名字

? ? NSString *firstName = [info objectForKey:@"firstName"];

? ? // 保存到聯系人對象中,每個屬性都對應一個宏,例如:kABPersonFirstNameProperty

? ? ? ? // 設置firstName屬性

? ? ? ? ABRecordSetValue(person, kABPersonFirstNameProperty, (__bridge CFTypeRef) firstName, NULL);

? ? //寫入圖片

? ? if(![[info objectForKey:@"image"] isKindOfClass:[NSNull class]])

? ? {

? ? ? ? UIImage *image = [UIImage imageNamed:@"icon80-80.png"];

? ? ? ? NSData *data = UIImageJPEGRepresentation(image, 1.0);

? ? ? ? ABPersonSetImageData(person, (__bridge CFDataRef) data, NULL);

? ? }

? ? //寫入公司

? ? if([info objectForKey:@"company"])

? ? {

? ? ? ? ABRecordSetValue(person, kABPersonOrganizationProperty, (__bridge CFTypeRef) [info objectForKey:@"company"], NULL);

? ? }

? ? //寫入公司地址

? ? if([info objectForKey:@"companyAddress"])

? ? {

? ? ? ? ABMutableMultiValueRef multiAddress = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);

? ? ? ? NSMutableDictionary *addressDictionary = [[NSMutableDictionary alloc] init];

? ? ? ? [addressDictionary setObject:[info objectForKey:@"companyAddress"] forKey:(NSString *) kABPersonAddressStreetKey];

? ? ? ? ABMultiValueAddValueAndLabel(multiAddress, (__bridge CFTypeRef)(addressDictionary), kABWorkLabel, NULL);

?? ? ? ?

? ? ? ? //設置address

? ? ? ? ABRecordSetValue(person, kABPersonAddressProperty, multiAddress, nil);

? ? }

? ? //寫入電話

? ? NSMutableArray *phones = [NSMutableArray arrayWithCapacity:0];

? ? NSMutableArray *phonesName = [NSMutableArray arrayWithCapacity:0];

? ? ? ? if(![[info objectForKey:[NSString stringWithFormat:@"phone%d",i]] isKindOfClass:[NSNull class]])

? ? ? ? {

? ? ? ? ? ? [phones addObject:[info objectForKey:[NSString stringWithFormat:@"phone%d",0]]];

? ? ? ? ? ? [phonesName addObject:[NSString stringWithFormat:@"phone%d",0]];

? ? ? ? }

? ??

?? ?

? ? if(phones.count != 0 || phonesName.count != 0)

? ? {

? ? ? ? // ABMultiValueRef類似是Objective-C中的NSMutableDictionary

? ? ? ? ABMultiValueRef mv = ABMultiValueCreateMutable(kABMultiStringPropertyType);

? ? ? ? // 添加電話號碼與其對應的名稱內容

? ? ? ? for (int i = 0; i < [phones count]; i ++) {

? ? ? ? ? ? ABMultiValueIdentifier mi = ABMultiValueAddValueAndLabel(mv, (__bridge CFStringRef)[phones objectAtIndex:i], (__bridge CFStringRef)[phonesName objectAtIndex:i], &mi);

? ? ? ? }

? ? ? ? // 設置phone屬性

? ? ? ? ABRecordSetValue(person, kABPersonPhoneProperty, mv, NULL);

? ? }

?? ?

? ? //寫入郵箱

? ? if([info objectForKey:@"email"])

? ? {

? ? ? ??

? ? ? ? ABMultiValueRef em = ABMultiValueCreateMutable(kABPersonEmailProperty);

? ? ? ? ABMultiValueIdentifier ma = ABMultiValueAddValueAndLabel(em, (__bridge CFTypeRef)([info objectForKey:@"email"]), (__bridge CFStringRef)@"email", &ma);

? ? ? ? ABRecordSetValue(person, kABPersonEmailProperty, em, NULL);

? ? }

//

//? ? //寫入網址

//? ? if([info objectForKey:@"url"])

//? ? {

//? ? ? ? NSMutableArray *y = [NSMutableArray arrayWithObjects:[info objectForKey:@"url"],@"http://www.ucardpro.com", nil];

//? ? ? ? NSMutableArray *z = [NSMutableArray arrayWithObjects:@"個人主頁",@"Ucard官網", nil];

//? ? ? ? ABMultiValueRef url = ABMultiValueCreateMutable(kABPersonURLProperty);

//? ? ? ? for (int i = 0; i < [phones count]; i ++) {

//? ? ? ? ? ? ABMultiValueIdentifier ur = ABMultiValueAddValueAndLabel(url, (__bridge CFStringRef)[y objectAtIndex:i], (__bridge CFStringRef)[z objectAtIndex:i], &ur);

//? ? ? ? }

//? ? ? ? ABRecordSetValue(person, kABPersonURLProperty, url, NULL);

//? ? }

//

//? ? //寫入日期

//? ? NSDate *date = [NSDate date];

//? ? NSDateFormatter *f = [[NSDateFormatter alloc] init];

//? ? f.dateFormat = @"yyyyMMdd HH:mm:SS";

//? ? NSString *s = [NSString stringWithFormat:@"名片導入時間:%@ ? 導入來自Ucard",[f stringFromDate:date]];

//? ? NSLog(@"%@",s);

//? ? ABRecordSetValue(person,kABPersonNoteProperty, (__bridge CFTypeRef)(s), NULL);

?? ?

? ? //寫入前檢查是否聯系人已存在

? ? if([ZxkSetAddressBook examineAddressWithName:firstName] == NO)

? ? {

? ? ? ? block();

? ? ? ? return NO;

? ? }

? ? // 獲取通訊錄中所有的聯系人

? ? NSArray *array = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);

? ? // 遍歷所有的聯系人并刪除

? ? for (id obj in array) {

? ? ? ? ABRecordRef people = (__bridge ABRecordRef)obj;

? ? ? ? NSString *first = (__bridge NSString *)ABRecordCopyValue(people, kABPersonFirstNameProperty);

? ? ? ? if ([first isEqualToString:firstName])

? ? ? ? {

? ? ? ? ? ? ABAddressBookRemoveRecord(addressBook, people, nil);

? ? ? ? }


? ? }

?? ?

? ? // 將新建的聯系人添加到通訊錄中

? ? ABAddressBookAddRecord(addressBook, person, NULL);

?? ?

? ? if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {

? ? ? ? dispatch_semaphore_t sema = dispatch_semaphore_create(0);

? ? ? ? ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {


? ? ? ? ? ? ? ? dispatch_semaphore_signal(sema);

?? ? ? ? ? ?

? ? ? ? });

? ? ? ? dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

? ? }

? ? else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {

? ? ? ? // The user has previously given access, add the contact

? ? ? ? if(ABAddressBookSave(addressBook, NULL))

? ? ? ? {

? ? ? ? ? ? return YES;

?? ? ? ? ? ?

? ? ? ? }

? ? }

? ? else {

? ? ? ? // The user has previously denied access

? ? ? ? // Send an alert telling user to change privacy setting in settings app

? ? ? ? UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"導入失敗,請在設置-隱私中檢查是否有權限訪問您的通訊錄" delegate:self cancelButtonTitle:@"確認" otherButtonTitles:nil];

? ? ? ? [alert show];

? ? }

? ? return NO;

}



以下是B的加密操作,部分核心代碼有刪減

//通訊錄加密

-(void)encryptWithAccountList:(AccountList *)list RePetBlock:(void(^)(void))block

{

? ? if([ZxkSetAddressBook SetAddressBookWithInfo:[dic mutableCopy] RePetBlock:block] == YES)

? ? {

? ? ? ? if(self.delegate && [self.delegate respondsToSelector:@selector(setAddressSuccess:)])

? ? ? ? {

? ? ? ? ? ? [self.delegate setAddressSuccess:self.accountList.remark];

? ? ? ? }

? ? }

}



最后是A的按鈕交互代碼

-(void)buttonClick

__block NSArray *arr = self.p_tableArr;

? ? ? ? __block int select = self.p_didSelect;

? ? ? ? __block AccountViewController *v = self;

? ? ? ? __block UIAlertView *alt;

? ? ? ? [self.encrypt encryptWithAccountList:[self.p_tableArr objectAtIndex:self.p_didSelect] RePetBlock:^

?? ? ? ? {

?? ? ? ? ? ? self.p_alertBlock = ^(NSInteger buttonIndex)

?? ? ? ? ? ? {

? ? ? ? ? ? ? ? ?

?? ? ? ? ? ? ? ? if(buttonIndex==1)

?? ? ? ? ? ? ? ? {

?? ? ? ? ? ? ? ? ? ? AccountList *list = [arr objectAtIndex:select];

?? ? ? ? ? ? ? ? ? ? [v setAddressSuccess:list.remark];

?? ? ? ? ? ? ? ? }

?? ? ? ? ? ? };

?? ? ? ? ? ? alt = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"tip",nil) message:NSLocalizedString(@"setaddressTips", nil) delegate:v cancelButtonTitle:NSLocalizedString(@"cancel", nil) otherButtonTitles:NSLocalizedString(@"ok",nil), nil];

?? ? ? ? ? ? [alt show];

? ? ? ? ? ? ?

?? ? ? ? }];



以下是B的結果回調代理 部分核心代碼有刪減

#pragma mark - AddressbookEncryptDelegate

- (void)setAddressSuccess:(NSString *)firstName

{


?? ?

? ? [self.navigationController pushViewController:self.p_peoplePicker animated:YES];

? ?

}






? ?以上實現既有代理也有Block,可以看到代理實現的過程較為繁雜,而Block實現更加的便捷直觀,根據上一章節在Block中講到的系統UIAlertView的集中代碼用法,這一整個過程不需要任何的回調代理,也不需要任何的邏輯判斷,實際上只需三個Block代碼快就可以完成,第一個是處理UIAlertView交互的bLOCK,一個是處理三種結果情況的Block,一個是組合前兩個Block之后的最終Block。?

? 也許從實現來看,三種方法都可以達到目的,但是在MVC的思維中前兩種實現方法都存在M層越界的情況。

? 在這個過程中,作為數據層,B的職責只是加密,C的職責只是導入,A作為Controller層主要是想拿到C的處理結果來做下一步的邏輯。第一種方案和第二種方案的實現中,由于C都是把自己的結果先交給B,B再交給A,所以這里存在A把自己與B無關的機密信息泄漏給了B,因為是B先知道這三種結果,A后知道。所以從理論來講,這里可能會存在B操作不當沒有正確的把C的結果告知A。當然,由于以上過程較為簡單,一般不會出現這種情況。而由于C作為一個工具類的靜態方法,無法做到代理告知,這也是一個問題。

??

? Block語法在這個過程中的好處就是:當Controller的某一個命令需要多個Model層協調進行的時候,Controller只需要將自己對最終結果處理的邏輯代碼寫在這個命令傳達之前,并且準確的交由真正那個能夠給自己明確答復的Model層去直接執行命令,既能夠集中自己的邏輯代碼,也避免了其他M層作為傳聲筒傳遞結果的重復代碼。

??

??





與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的块语法Block在MVC思维的妙用之多重M层代理传值的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。