——只燈片箋
此文記錄的是筆者在實(shí)際iOS開發(fā)工作中遇到并解決的一些小細(xì)節(jié)問題,以此記錄,持續(xù)更新,僅供參考。
-
Gzip和POST請求相關(guān)問題
1.導(dǎo)入頭文件(Ps:此處的是AFNetworking3.0)
#import "AFNetworking.h"
#import "AFgzipRequestSerializer.h"
2.封裝網(wǎng)絡(luò)請求:
-(void)request:(NSString *)url dic:(id)parameter success:(SuccessBlockType)successBlock failed:(FailedBlockType)failedBlock {
NSString *urlEncoded = [self urlEncode:url];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]init];
//增加一種類型,text/html類型
NSSet *set = manager.responseSerializer.acceptableContentTypes;
NSMutableSet *acceptSet = [NSMutableSet setWithSet:set];
[acceptSet addObject:@"text/html"];
[acceptSet addObject:@"text/xml"];
[acceptSet addObject:@"text/json"];
[acceptSet addObject:@"text/plain"];
manager.responseSerializer.acceptableContentTypes = acceptSet;
// 用以解決bug:NSURLErrorDomain code -1012
[manager.securityPolicy setAllowInvalidCertificates:YES];
// 接受gzip壓縮的json(普通的)
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
// 或者是:(服務(wù)器端返回的)
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
// 將parameters 進(jìn)行壓縮
manager.requestSerializer = [AFgzipRequestSerializer serializerWithSerializer:[AFJSONRequestSerializer serializer]];
//添加此方法,解決未注冊的https無法忽略的問題 warning:In order to validate a domain name for self signed certificates, you MUST use pinning.
manager.securityPolicy.allowInvalidCertificates = YES;
manager.securityPolicy.validatesDomainName = NO;
[manager POST:urlEncoded parameters:parameter progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//把解析好的數(shù)據(jù),即網(wǎng)絡(luò)返回的數(shù)據(jù),通過block回傳回去
if (successBlock) {
successBlock(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failedBlock) {
failedBlock(error);
}
}];
}
3.Gzip解決的關(guān)鍵代碼:
manager.requestSerializer = [AFgzipRequestSerializer serializerWithSerializer:[AFJSONRequestSerializer serializer]];
4.當(dāng)然,上面的操作完畢后,編譯,會提示這樣的錯誤:

錯誤的意思是:你有兩個相同的.m文件,然而,實(shí)際上一個相同的也沒有。
此處僅僅是沒有導(dǎo)入系統(tǒng)文件而已。
導(dǎo)入即可。

以上步驟均完成后,在后續(xù)調(diào)用的時候,POST的請求體內(nèi)的鍵值對就會被Gzip打包壓縮。
發(fā)送給服務(wù)器后,就會在服務(wù)器端解壓縮,獲取到請求體,從而服務(wù)器響應(yīng)請求內(nèi)容,反饋給你Gzip后的請求數(shù)據(jù)。
用AFNetworking封裝的Block網(wǎng)絡(luò)請求,會自動接受服務(wù)器Gzip后發(fā)送過來的數(shù)據(jù)。
-
TableViewCell的點(diǎn)擊
默認(rèn)狀態(tài)下,點(diǎn)擊cell后的狀態(tài)是這樣的:

而我們可能希望是這樣的(沒有選中的那個淺灰色提示):

所以,可以通過在代理方法中,輸入一段代碼即可。
關(guān)鍵代碼如下:
// 選中Cell的方法
#pragma mark - 選中Cell的方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 點(diǎn)擊后,取消當(dāng)前的選中狀態(tài)
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
-
NavigationController全屏返回
我們知道,NavigationController自帶有滑動回到上一級的功能。
但是,當(dāng)屏幕太大的時候,我們可能希望,隨便滑動視圖上某個位置就可回到上一級。
1.導(dǎo)入頭文件
#import <objc/runtime.h>
2.關(guān)鍵代碼部分:
//弄全屏
-(void)startFullScreen {
// 獲取系統(tǒng)自帶滑動手勢的target對象
id target = self.interactivePopGestureRecognizer.delegate;
// 創(chuàng)建全屏滑動手勢,調(diào)用系統(tǒng)自帶滑動手勢的target的action方法
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
// 設(shè)置手勢代理,攔截手勢觸發(fā)
pan.delegate = self;
// 給導(dǎo)航控制器的view添加全屏滑動手勢
[self.view addGestureRecognizer:pan];
// 禁止使用系統(tǒng)自帶的滑動手勢
self.interactivePopGestureRecognizer.enabled = NO;
}
// 什么時候調(diào)用:每次觸發(fā)手勢之前都會詢問下代理,是否觸發(fā)
// 作用:攔截手勢觸發(fā)
-(BOOL)handleNavigationTransition:(UIGestureRecognizer *)gestureRecognizer {
// 注意:只有非根控制器才有滑動返回功能,根控制器沒有。
return YES;
}
// 代理方法
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
// 判斷導(dǎo)航控制器是否只有一個子控制器,如果只有一個子控制器,肯定是根控制器
if (self.childViewControllers.count == 1) {
// 表示用戶在根控制器界面,就不需要觸發(fā)滑動手勢
return NO;
}
return YES;
}
-
點(diǎn)擊按鈕無法顯現(xiàn)預(yù)期效果
有些時候,我們可能會遇到按鈕點(diǎn)擊后無法執(zhí)行出一些預(yù)設(shè)的效果的狀態(tài)。
但是,如果,我們打印一句話,卻能顯示出來。
此時,可能,你的代碼里,出現(xiàn)了條件判斷語句中嵌套了條件判斷語句的狀態(tài)。
就好像像這樣:
if ([respondData[@"RS"] length] < 10) {
// 判斷是否能在錯誤信息中找到"password is wrong"
NSRange range = [respondData[@"ROWRS"] rangeOfString:@"password"];
// 如果能找到,則range.location != NSNotFound
if (range.location != NSNotFound) {
UIAlertController * currentAlert = [CECAlertEngine alertShow:@"密碼錯誤"];
// 彈出提示框;
[self presentViewController:currentAlert animated:true completion:nil];
}else {
UIAlertController * currentAlert = [CECAlertEngine alertShow:@"該賬戶尚未注冊"];
// 彈出提示框;
[self presentViewController:currentAlert animated:true completion:nil];
}
}
而這里,我們要做的是拆分出來?xiàng)l件判斷語句中嵌套的條件判斷語句,并加之return。
如此一來,就可以解決標(biāo)題所述問題。
推薦這樣:
// 判斷是否能在錯誤信息中找到"password is wrong"
NSRange range = [respondData[@"ROWRS"] rangeOfString:@"password"];
// 如果能找到,則range.location != NSNotFound
if ([respondData[@"RS"] length] < 10 && range.location != NSNotFound) {
UIAlertController * currentAlert = [CECAlertEngine alertShow:@"密碼錯誤"];
// 彈出提示框;
[self presentViewController:currentAlert animated:true completion:nil];
return;
}
else if ([respondData[@"RS"] length] < 10 && range.location == NSNotFound) {
UIAlertController * currentAlert = [CECAlertEngine alertShow:@"該賬戶尚未注冊"];
// 彈出提示框;
[self presentViewController:currentAlert animated:true completion:nil];
return;
}
總的來講,盡一切可能避免條件判斷語句中嵌套條件判斷語句。
-
AutoLayout下UIScrollView無法滾動問題
此處采用的是Masonry進(jìn)行的約束。
為什么會出現(xiàn)這個問題?
使用支持AutoLayout后,在ViewDidLoad之后,系統(tǒng)會重新計(jì)算控件的一些值,導(dǎo)致之前你所設(shè)置的contentSize被重置為(0,0)了。
解決方案很簡單:把設(shè)置contentSize的代碼放到viewDidAppear上即可。
//解決AutoLayout下ScrollView無法滾動問題
-(void)viewDidAppear:(BOOL)animated {
// 設(shè)置滾動視圖的滾動范圍
self.baseScrollView.contentSize = CGSizeMake(kSceenWidth, (kSceenWidth * 279 / 990) + 534);
[super viewDidAppear:animated];
}
修正:AutoLayout下UIScrollView無法滾動問題 最新最好的解決辦法
將所有的添加載scrollView上的控件,順序調(diào)整下,即可。
1.聲明scrollView,并添加到視圖。
2.添加其余控件到scrollView上。
3.用Mansory進(jìn)行AutoLayout布局。
示例代碼如下:
-(void)viewDidLoad {
[super viewDidLoad];
UIScrollView *baseScrollView = [[UIScrollView alloc] init];
[self.view addSubview:baseScrollView];
//maskView 這一段代碼 可以注釋掉 不影響效果
UIView *maskView = [[UIView alloc] init];
[baseScrollView addSubview:maskView];
[maskView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(baseScrollView);
}];
UILabel *testLabel = [[UILabel alloc] init];
testLabel.numberOfLines = 0;
[maskView addSubview:testLabel];
[testLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(maskView).offset(10);
make.top.equalTo(maskView).offset(10);
make.right.equalTo(maskView).offset(-10);
}];
testLabel.text = @"此處自行寫一段長長的文字做測試即可";
UIImageView *imageView = [[UIImageView alloc] init];
imageView.backgroundColor = [UIColor cyanColor];
[maskView addSubview:imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(testLabel.mas_bottom).offset(10);
make.left.equalTo(baseScrollView).offset(10);
make.right.equalTo(baseScrollView).offset(-10);
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
[baseScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
make.bottom.mas_greaterThanOrEqualTo(imageView.mas_bottom).offset(20);
}];
}
-
iOS關(guān)于SVN沖突問題
iOS關(guān)于SVN沖突問題:
Project /Users/XXX/Desktop/XXX/XXX/xxx.xcodeproj cannot be opened because the project file cannot be parsed.
解決方法的步驟:
1.在文件夾中找到 xxx.xcodeproj 文件,點(diǎn)擊右鍵,選擇顯示包內(nèi)容
2.雙擊打開 project.pbxproj 文件
3.找出沖突信息(用commad + f 快速搜索)
4.刪除 <<<<<<< ====== >>>>>> 這些行(hang)
5.保存,退出 (有時要clean 一下))
6.重新打開xxx.xcodeproj文件即可
-
在一堆條件判斷中做彈窗提示

遇到的問題是,如果不正確寫好邏輯,就會一直報錯,說是彈窗已經(jīng)提前聲明顯示過了,不過是空的。而實(shí)際的程序并沒有任何異樣。
后來,修改邏輯后就好了。所以,盡信書,不如無書。禪與Objective-C講到的一些東西是有用。但是,更要結(jié)合自己的實(shí)際。
所以,該用這樣
if ( ) {
}
else if ( ) {
}
else {
}
-
圖片不顯示的問題
如果,某天,你一臉懵逼的發(fā)現(xiàn),你的圖片剛開始測試的時候是顯示的。但是,后來突然某天抽了,不顯示了。
而且,你的寫法是這樣的:
[UIImage imageNamed:@"18"];
所以,當(dāng)你郁悶的時候,不妨看看,這樣的寫法:
[UIImage imageNamed:@"18.jpg"];
其實(shí),這里的問題很簡單,因?yàn)閕OS對.jpg格式的圖片支持并不是很好,如果是.png格式的圖片,則是毫無問題。所以,當(dāng)你的圖片格式是.jpg格式,請把名字寫全。免得郁悶自己。
-
環(huán)信集成問題
最近在做即時通訊,需要集成環(huán)信的SDK,但是,環(huán)信的SDK真的挺老的。
按照官方文檔走,即可。
需要注意的是,別看錯文檔。好幾次,我看著文檔郁悶半天,才發(fā)現(xiàn)自己看的是2.0的文檔。所以,要看的話,請看3.0文檔。
xxx.pch文件里,不要導(dǎo)入環(huán)信的頭文件,否則會運(yùn)行失敗,一堆的Error。
So,盡可能避免在pch頭文件內(nèi)一次性導(dǎo)入過多的.h文件,否則會出現(xiàn)莫名其妙的重復(fù)文件問題。
確切的做法是:在需要用到的地方進(jìn)行引用.h文件即可。可以避免一些不必要的麻煩出現(xiàn)。
一般錯誤提示為:
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
這里的錯誤提示。
前一句意思是:你缺失libssl這個庫文件。
后一句的意思是:你有兩個重復(fù)名字的文件。
以第一句為基準(zhǔn),因?yàn)樵?jīng)以第二句為基準(zhǔn),差點(diǎn)被坑慘。
修正,最新解決方案:
實(shí)際上,可以丟在頭文件里,只是需要注釋掉一部分東西,再添加一部分東西即可。也就是幾行代碼的問題而已。


按照圖中注釋掉后,即可。
接著,集成環(huán)信的UI界面,步驟如下:
1.到官網(wǎng)的SDK現(xiàn)在最新的iOS SDK。
網(wǎng)址:
http://www.easemob.com/download/im

2.EaseUI使用指南中下載EaseUI工程。
網(wǎng)址:
http://docs.easemob.com/im/300iosclientintegration/85easeuiguide#easeui_使用指南

3.打開下載的文件夾,從中拖需要的文件到自己的工程內(nèi)。
EaseUIResource.bundle

EaseUI

Resource

此時編譯,會有一堆什么runtime之類的報錯。
需要在pch文件里的首尾部分,添加如下代碼:

余下的還有error,請自行解決。
我在開發(fā)中遇到的問題是MBProgress之類的東西的error,注釋掉error部分就行了,良好運(yùn)行,簡單粗暴。
-
SVN命令行將工程導(dǎo)入到服務(wù)器
另注:SVN首次從本地導(dǎo)入到SVN服務(wù)器的時候,有時可能不支持http協(xié)議。
打開終端,輸入如下命令行:
svn import /Users/cecdata/Desktop/08.12/DoctorApp https://xxx.xxx.xx.xxx/svn/xxxxx/ --username=xxxxx --password=xxxxx -m "修改了注冊頁的彈窗提醒,并繼承過環(huán)信SDK,調(diào)試bug完畢"
-
極光推送SDK集成問題
極光推送相對環(huán)信,更加簡單點(diǎn)。但是,需要配置證書。特別是描述文件。
遇到的問題是這樣的。推送測試消息,成功。但是接收數(shù)為0。
后臺打印是這樣的。

其實(shí),這個問題解決,倒也簡單。
只需要把配置好的描述文件(Provisioning Profiles)導(dǎo)進(jìn)來(從開發(fā)者中心下載下來,雙擊安裝即可)。需要注意的是,你必須保證你的工程中的Bundle Identifier跟開發(fā)者賬號配置的AppID是一致的。否則,這也會是導(dǎo)致崩潰的原因。
因?yàn)橐昧谁h(huán)信的SDK,所以,做了這樣的操作。
SDK 不支持 bitcode,在 Build Settings → Linking → Enable Bitcode 中設(shè)置 NO。
如果進(jìn)行了上面的操作,那么接下來就該這樣操作。


另:需要注意,從鑰匙串導(dǎo)出的.p12文件,盡可能為英文或者數(shù)字命名,否則,也會不定性錯誤。
集成完極光SDK,出現(xiàn)這樣的后臺打印。

這里的錯誤提示很簡單。就是告訴你,約束錯了。我什么都沒干,哪來的約束錯誤。不搭理它,重新?lián)Q個真機(jī)運(yùn)行,毫無問題。再換回來,也是毫無問題。就這樣,問題解決了。所以,盡可能,clean一下,再運(yùn)行。
-
scrollView高度動態(tài)變化
近來做項(xiàng)目,遇到需要根據(jù)scrollView上添加的視圖控件的高度動態(tài)變化狀況,來對scrollView的高度進(jìn)行動態(tài)變化。
此處,顯而易見的就會想到AutoLayout。原理很簡單,就是在scrollView添加一層類似于蒙版層的東西,填充scrollView (當(dāng)然,你也可以不加這一類蒙版層)。不過,個人感覺,為了穩(wěn)妥起見,添加為好。特別是用xib的小伙伴們。
從網(wǎng)上也看了頗多,挺麻煩。就想著自己簡化來寫。
此處示例的是一個小測試demo的全部代碼。
//引入Masonry頭文件
#import "Masonry.h"
-(void)viewDidLoad {
[super viewDidLoad];
UIScrollView *baseScrollView = [[UIScrollView alloc] init];
[self.view addSubview:baseScrollView];
[baseScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
//maskView 這一段代碼 可以注釋掉 不會影響高度動態(tài)變化以及滾動效果
UIView *maskView = [[UIView alloc] init];
[baseScrollView addSubview:maskView];
[maskView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(baseScrollView);
}];
UILabel *testLabel = [[UILabel alloc] init];
testLabel.numberOfLines = 0;
[baseScrollView addSubview:testLabel];
[testLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(baseScrollView).insets(UIEdgeInsetsMake(20, 10, 0, 10));
}];
testLabel.text = @"/*此處,請自己動手,寫一段特別長的文字,來用做測試*/";
}
-
The file * couldn't be opened because you don't have permission to view it.
當(dāng)你休息了一個周末回來,打開你的工程,跑起來,卻莫名其妙的報了這樣的錯誤:“The file * couldn't be opened because you don't have permission to view it”錯誤信息。
你一定非常納悶,哪里出問題了,明明你上周五離開的時候,還是運(yùn)行良好無誤的。
解決方案:
Window --> Projects --> 在下面框框左面選擇你的項(xiàng)目名字 --> 在右面有一個delete,點(diǎn)擊刪除即可。不會影響你的文件,刪除后相當(dāng)于從0編譯第一次速度會慢一點(diǎn)而已。

-
蒲公英上傳打包出現(xiàn)的問題:
Error:
Provisioning profile does not match bundle identifier: The provisioning profile specified in your build settings (“xxxxxxxxx”) has an AppID of “com.xxx.xxxxxx” which does not match your bundle identifier “com.xxx.xxxxxx.xxxxx”.
解決方案:


-
緩存未清除問題:
Error:
ld: warning: directory not found for option '-L/Users/xxx/Desktop/xxxxxx/xxx/xxx/Classes/IMSDKLib/HyphenateFullSDK/lib/3rdparty'
ld: warning: directory not found for option '-L/Users/xxx/Desktop/xxxxxx/xxx/xxx/Classes/IMSDKLib/HyphenateFullSDK/lib'
ld: warning: directory not found for option '-L/Users/xxx/Desktop/xxxxxx/xxx/xxx/Classes/EaseUI/EMUIKit/3rdparty/DeviceHelper/VoiceConvert/opencore-amrnb'
ld: warning: directory not found for option '-L/Users/xxx/Desktop/xxx/xxx/xxx/Classes/EaseUI/EMUIKit/3rdparty/DeviceHelper/VoiceConvert/opencore-amrwb'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解決方法:
紅色框內(nèi),全部清除掉,即刪掉編譯報warning的路徑即OK


-
環(huán)信集成的錯誤:ld: library not found for -lopencore-amrwb
編譯階段就會報這樣的錯。
解決辦法:
project->general->linked frameworks and Libraries
找“ -lopencore-amrwb” ,然而,實(shí)際是找不到的。因?yàn)?,其對?yīng)的是:libopencore-amrwb

紅色框內(nèi)為細(xì)節(jié)注意問題
點(diǎn)擊之后,你會發(fā)現(xiàn),這個文件在文件夾內(nèi)是實(shí)際存在的。
接下來的解決方法就是:
把它丟出工程外,但是要注意,不是丟到垃圾簍。

然后,選中你要添加進(jìn)的文件夾。按快捷鍵alt + command + A,會打開finder,選擇你剛才移除的文件夾,點(diǎn)擊Add,即可。
之后,之前報錯的路徑問題,就可解決。估摸著,應(yīng)該是 linked frameworks and Libraries 會自動更新的緣故。
-
關(guān)于Xcode 8創(chuàng)建的storyBord、Xib在Xcode 7中無法打開的問題
錯誤是這樣的:
This version does not support documents saved in the Xcode 8 format.
Open this document with Xcode 8.0 or later.


解決辦法:
對于StoryBord:
可以用文本編輯器打開xib文件,將document中的toolsVersion和plugln中的version改正原來xib文件中的值,同時刪除
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"
對于Xib:
用編輯器將Xib里面的下面一句話刪除掉才能打開:
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-
Xcode編譯錯誤:ld: 5 duplicate symbols for architecture arm64
錯誤是這樣的:
ld: 5 duplicate symbols for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解決辦法:
Xcode編輯時報:2 duplicate symbols for architecture arm64
1.查看自己項(xiàng)目中是否有重復(fù)命名的文件
(一般就是這個問題,如果項(xiàng)目中排查后,沒有發(fā)現(xiàn)。
那就該項(xiàng)目所在的文件是否有重復(fù)命名的文件,刪除一個就可以了,排查的目標(biāo)一般都在報錯前面列舉出來。)
2.再查看是否在編輯#improt頭文件時候,不小心把.h誤寫成.m
-
iOS·SVN出錯
iOS:SVN出錯 Description : The working copy is locked due to a previous error
錯誤打印如下:
Description : The working copy is locked due to a previous error. Suggestion : Clean the working copy and then retry the operation. Technical Information
===================== Error : V4WorkingCopyLockedError Exception : ZSVNWorkingCopyLockedException Causal Information ==================
Description : Working copy '/Users/cecdata/Desktop/SmartGoBeta/SmartGo_IOS' locked.
Status : 155004 Description : '/Users/cecdata/Desktop/SmartGoBeta/SmartGo_IOS/SmartGo_Simple_3.0' is already locked. Status : 155004
解決方法如下:
使用CornerStone工具update最新SVN代碼報錯:The working copy is locked due to a previous error,不僅無法上傳,也無法更新,錯誤提示被鎖。