最近兩個月的時間都忙于趕項目進度,都沒有時間好好總結,現在項目基本完成了,就剩下等待審核上線了,不過審核真的是相當坑,等審核結束了,我再寫一篇關于審核的文章,各種元數據被拒絕,簡直欲哭無淚,不過吃過虧了下次就長記性了,也算是一種學習吧,這邊先說一下在項目中遇到的一些問題
自定義TabBarController Push下一級Controller時 會報這樣的錯誤:Unbalanced calls to begin/end appearance transitions for <UIVIewController>
現在的app一般都需要自定義tabbar,這次也不例外,不過在push的過程中居然遇到了這么一個問題,之前都沒遇到過,可能是因為自定義的緣故,部分屬性需要自己設置,不然會報錯,解決方法如下:
自定義了TabBarController 之后必須實現以下
-(void)viewWillAppear:(BOOL)animated
{
[self.selectedViewController beginAppearanceTransition: YES animated: animated];
}
-(void) viewDidAppear:(BOOL)animated
{
[self.selectedViewController endAppearanceTransition];
}
-(void) viewWillDisappear:(BOOL)animated
{
[self.selectedViewController beginAppearanceTransition: NO animated: animated];
}
-(void) viewDidDisappear:(BOOL)animated
{
[self.selectedViewController endAppearanceTransition];
}
判斷字符串為空
既然是做項目,那么經常會出現填寫注冊以及登錄信息的,但是很多調皮的用戶,經常會用空來輸入,我們就需要對空進行判斷,空的情況有很多種,之前的話都是通過長度為0進行判斷的,不過這樣的判斷不夠全面,經常會有漏網之魚,所以寫了下面的一個判斷方法
+ (BOOL) isBlankString:(NSString *)string
{
if (string == nil || string == NULL) {
return YES;
}
if ([string isKindOfClass:[NSNull class]]) {
return YES;
}
if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0) {
return YES;
}
return NO;
}
使用信號量來解決代碼塊執行順序的問題
代碼塊是實際開發中經常會使用的,但是代碼塊的執行順序問題經常是很讓人頭疼的,在這次項目中,先要獲取到用戶的全部信息,然后才能進行相關的訂閱主題,但是獲取用戶的全部信息是一個代碼塊的方法,每次都沒有拿到需要的userid,就開始訂閱導致失敗,無論是放在代碼塊中或者代碼塊外面都不能解決,然后就想了一個信號量+隊列的辦法來解決,如下所示:
dispatch_semaphore_t signal = dispatch_semaphore_create(0);
dispatch_group_t group=dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
KLRootTabbarController *root=[[KLRootTabbarController alloc]init];
[root acceptfriendList];
});
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
self.userid = [_topic selectUseridWithUsername:[UserDefaultsUtils valueWithKey:USER_NAME] andFriendname:noti.userInfo[@"FriendUsernamer"]];
dispatch_semaphore_signal(signal);
});
dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
打開當前app的應用權限管理
app中的設置有一個跳轉到本身應用的權限管理界面的功能,實現代碼如下:
NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if([[UIApplication sharedApplication] canOpenURL:url]) {
NSURL*url =[NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:url];
}
時間戳的轉換
出于安全性的考慮,后臺說需要使用sessionID,設置的是6分鐘超時,每次獲取sessionid都會返回給我超時時間以及sessionid,但是后臺返回的是時間戳的格式,唉,萬惡的后臺,安卓常用的時間戳轉換好像和ios的相差1000,所以我下面乘上了1000才能夠順利的將時間戳進行轉換
-(long long)getDateTimeTOMilliSeconds:(NSDate *)datetime
{
NSTimeInterval interval = [datetime timeIntervalSince1970];
NSLog(@"轉換的時間戳=%f",interval);
long long totalMilliseconds = interval*1000 ;
NSLog(@"totalMilliseconds=%llu",totalMilliseconds);
return totalMilliseconds;
}
使用SSL證書連接MQTT服務器
這個問題是最頭疼的,困擾了我很久,因為無論是前端還是后臺都不了解SSL證書以及MQTT連接,所以只能摸石頭過河,連接MQTT還算順利,通過當前使用的比較多的第三方庫進行連接,ssl證書就相對坑很多了,后臺給了一個crt證書首先,然后通過鑰匙串轉換成cer證書,這樣我們才能夠使用,然后用MQTT第三方庫中自帶的SSL連接的方法進行連接就可以了(這邊和安卓不用,安卓的SSL連接方法和ios不太像,我一開始對著找,就是沒找到,然后怎么都連不上,后來翻閱文檔才找到了對應的方法)相關代碼如下:
MQTT使用ssl的連接方法
self.session = [KLMQTTSingleton shareInstance];
[self.session setSecurityPolicy:[self customSecurityPolicy]];
self.session.delegate = self;
[self.session connectAndWaitToHost:[UserDefaultsUtils valueWithKey:kIP] port:[[UserDefaultsUtils valueWithKey:kPORT] intValue] usingSSL:YES timeout:5];
設置獲取證書的方法
- (MQTTSSLSecurityPolicy *)customSecurityPolicy
{
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"cer"];//證書的路徑
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
MQTTSSLSecurityPolicy *securityPolicy = [MQTTSSLSecurityPolicy policyWithPinningMode:MQTTSSLPinningModeNone];
securityPolicy.allowInvalidCertificates = YES;
securityPolicy.validatesCertificateChain = YES;
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = @[certData];
return securityPolicy;
}