前言
做iOS開發(fā)這么長(zhǎng)時(shí)間以來(lái)蔬胯,遇到過(guò)不少難題朋截,也踩過(guò)不少坑蛹稍,本來(lái)沒(méi)想過(guò)要寫這篇文章,但是鑒于以下三點(diǎn)部服,筆者決定對(duì)遇到過(guò)的并且還能回憶起來(lái)的問(wèn)題做個(gè)記錄
- 每次問(wèn)題解決后唆姐,滿滿的成就感,但是當(dāng)下一次再遇到時(shí)廓八,又是一臉懵逼奉芦。這個(gè)問(wèn)題我好像見過(guò),但就是不記得怎么解決??剧蹂,記錄下來(lái)方便以后查閱
- 每次面試的時(shí)候声功,面試官總會(huì)問(wèn)我,你在開發(fā)中遇到過(guò)哪些問(wèn)題宠叼,怎么解決的先巴?問(wèn)題嘛,挺多的冒冬,但是你要我敘述嘛伸蚯,我......我......我居然一時(shí)想不起來(lái),迷之尷尬??(面試官當(dāng)時(shí)想法:一看就是個(gè)沒(méi)工作經(jīng)驗(yàn)偽造簡(jiǎn)歷的)简烤,冤枉啊??
- 為遇到同樣問(wèn)題的開發(fā)者提供一個(gè)參考
那些遇到過(guò)的問(wèn)題與踩過(guò)的坑
1.手機(jī)錄音或通話時(shí)剂邮,app界面整體下移
當(dāng)你的iphone在錄音或者通話時(shí),打開app你會(huì)發(fā)現(xiàn)乐埠,整個(gè)界面都下移了20像素抗斤,這個(gè)問(wèn)題對(duì)于scrollView囚企、tableView等可以垂直滾動(dòng)的視圖可能沒(méi)有太大影響,但是對(duì)于那些不能滾動(dòng)的視圖瑞眼,就有可能底部被遮蓋20像素
筆者在網(wǎng)上查閱了資料龙宏,也試過(guò)多種方法,這個(gè)問(wèn)題依然存在伤疙,最后筆者不得不使用大絕招來(lái)解決银酗,何為大絕招?很簡(jiǎn)單徒像,位置尺寸寫死黍特。項(xiàng)目中導(dǎo)航控制器是自定義的,在自定義的類中添加如下代碼就OK了
2.點(diǎn)擊導(dǎo)航欄下方也會(huì)觸發(fā)導(dǎo)航欄按鈕的點(diǎn)擊事件
如圖所示锯蛀,每次想選中右上角的圖片灭衷,結(jié)果總是觸發(fā)“取消”事件,明明沒(méi)有點(diǎn)到導(dǎo)航欄上面去旁涤,問(wèn)題的原因不清楚翔曲,解決方法創(chuàng)建一個(gè)UINavigationBar的分類,重寫hitTest方法
如果觸摸點(diǎn)不在它上面劈愚,就不讓它接收用戶交互瞳遍,然后使用系統(tǒng)的事件處理方法去處理
3.輸入中文時(shí)限制字符長(zhǎng)度
限制字母、數(shù)字菌羽、符號(hào)等其他非中文字符的長(zhǎng)度大家應(yīng)該都知道咋整掠械,但如果是中文輸入法,這就比較蛋疼了注祖。舉個(gè)例子猾蒂,限制長(zhǎng)度為5,輸入“我愛寫代碼”氓轰,當(dāng)已經(jīng)輸入“我愛寫”兩字婚夫,然后輸入“代碼”時(shí)就會(huì)出現(xiàn)如下情況
根本寫不進(jìn)去啊,這是為什么呢署鸡?因?yàn)檩斎氲钠匆粢脖挥?jì)算在了字符串長(zhǎng)度之內(nèi)案糙,導(dǎo)致輸入“da”以后就不能繼續(xù)輸入了,可通過(guò)下面的辦法解決
4.修改導(dǎo)航欄顏色
這個(gè)問(wèn)題對(duì)有經(jīng)驗(yàn)的開發(fā)者來(lái)說(shuō)不是問(wèn)題靴庆,但是當(dāng)年筆者剛?cè)胄袝r(shí)时捌,確實(shí)被這個(gè)問(wèn)題折騰了好久。比如想設(shè)置導(dǎo)航欄的顏色為藍(lán)色
self.navigationController.navigationBar.backgroundColor = [UIColor blueColor];
運(yùn)行炉抒,然后......??這特么是藍(lán)色奢讨?筆者確定自己不是色盲
后來(lái)才知道,設(shè)置導(dǎo)航欄的背景色焰薄,需要設(shè)置barTintColor而不是backgroundColor
self.navigationController.navigationBar.barTintColor = [UIColor blueColor];
5.界面莫名其妙下移
這個(gè)問(wèn)題跟上面的問(wèn)題一樣拿诸,都是比較基礎(chǔ)的問(wèn)題扒袖,有經(jīng)驗(yàn)的人都知道如何解決,但是筆者曾經(jīng)也被折磨過(guò)
為什么下面textView的內(nèi)容不是從最上面開始的亩码,而且還不能滾上去季率,當(dāng)初真的被這種情況折騰的死去活來(lái)的,改frame描沟,改約束飒泻,都沒(méi)效果。后來(lái)才知道吏廉,當(dāng)有導(dǎo)航控制器時(shí)泞遗,系統(tǒng)會(huì)默認(rèn)將第一個(gè)添加的scrollView或其子類視圖的內(nèi)容下移64個(gè)像素,下面的textView是先添加的席覆,所以其內(nèi)容被下移了史辙,而上面的卻沒(méi)有,解決方法是在控制器里加上下面這句代碼
self.automaticallyAdjustsScrollViewInsets = NO;
6.GCD組函數(shù)
筆者在開發(fā)中遇到過(guò)這樣一個(gè)功能佩伤,某個(gè)界面列表上面是企業(yè)髓霞,下面是聯(lián)系人,而且獲取企業(yè)列表與聯(lián)系人列表的接口不是同一個(gè)畦戒,必須等企業(yè)跟聯(lián)系人列表數(shù)據(jù)都獲取完畢后才能刷新,于是就用到了GCD組函數(shù)
然而問(wèn)題來(lái)了结序,[[IBOSServer shared]...]這玩意兒是封裝好的障斋,并且是個(gè)異步函數(shù),大家應(yīng)該都知道徐鹤,異步函數(shù)不會(huì)阻塞線程垃环,不用等里面的內(nèi)容執(zhí)行完就返回了,這就導(dǎo)致數(shù)據(jù)還沒(méi)拿到返敬,就開始執(zhí)行notify里面的代碼了遂庄。后來(lái)筆者發(fā)現(xiàn),原來(lái)GCD組函數(shù)還有一種用法劲赠,完美解決問(wèn)題
7.UISearchController
iOS8才出來(lái)的涛目,用來(lái)替換UISearchBar + UISearchDisplayController的組合方式,項(xiàng)目中有用到搜索功能凛澎,于是筆者就嘗試著用了一下UISearchController霹肝,將搜索框添加到了tableView的tableHeaderView上。然而當(dāng)點(diǎn)擊搜索框準(zhǔn)備搜索時(shí)塑煎,神奇的事情發(fā)生了
??搜索框居然飛到九霄云外去了沫换,好難過(guò),這不是我要的那種結(jié)果最铁,結(jié)果.....
怎么解決呢讯赏?在控制器里加上下面這句代碼就OK了垮兑,至于為什么,呵呵??漱挎,不知道
self.definesPresentationContext = YES;
8.自定義相機(jī)照片截取
這個(gè)問(wèn)題說(shuō)難不難系枪,說(shuō)簡(jiǎn)單也不簡(jiǎn)單,筆者當(dāng)時(shí)確實(shí)花了很長(zhǎng)一段時(shí)間才弄清楚识樱,但是當(dāng)問(wèn)題解決后桨踪,感覺(jué)這特么也不復(fù)雜啊轧抗,之前怎么就沒(méi)整明白呢
問(wèn)題是這樣的,在使用自定義相機(jī)拍完照后,需要對(duì)圖片的指定區(qū)域(藍(lán)色方框內(nèi)的區(qū)域)進(jìn)行截取然后上傳积糯,這里存在兩個(gè)問(wèn)題
- 拍攝時(shí)你所看到的區(qū)域,跟實(shí)際拍出來(lái)的區(qū)域是不一樣的
上圖就是實(shí)際拍出來(lái)的圖片湃累,明顯比拍攝時(shí)看到的圖片要長(zhǎng)栅干,不過(guò)寬度是一樣的
- 照片的坐標(biāo)系與我們平時(shí)開發(fā)所使用的坐標(biāo)系是不一樣的
開發(fā)中所使用的視圖坐標(biāo)系是以左上角為原點(diǎn)的,橫向?yàn)閤軸宏榕,縱向?yàn)閥軸拓诸,而拍攝出來(lái)的照片是以右上角為原點(diǎn)的,橫向?yàn)閥軸麻昼,縱向?yàn)閤軸
我們先來(lái)看一幅圖
由于拍攝時(shí)所看到視圖寬高比與實(shí)際拍攝出來(lái)的圖片的寬高比并不一致奠支,所以導(dǎo)致圖片經(jīng)過(guò)等比例縮放到寬度一樣時(shí),高度有一部分超出了我們的可視范圍抚芦,首先倍谜,我們要計(jì)算出超出部分的高度
//_cameraView為相機(jī)視圖,即拍攝時(shí)看到圖片的區(qū)域
CGFloat scale = image.size.width / _cameraView.width;//計(jì)算出縮放的比例
CGFloat showImageH = image.size.height / scale;//縮放后圖片的高度
CGFloat offsetY = (showImageH - _cameraView.height) * 0.5;//上下超出的部分是相等的叉抡,所以*0.5得出上面超過(guò)的部分
超出部分的高度計(jì)算完后尔崔,我們就要來(lái)計(jì)算藍(lán)色方框(_circleView,_cameraView的子控件)的坐標(biāo)了
x:(offsetY+_circleView.y) * scale褥民,別忘了乘以縮放比例
y:_circleView.x * scale季春,因?yàn)閏ircleView在父控件中水平居中,所以_circleView在父控件中的x值乘以縮放比就是在圖片坐標(biāo)系中的y值
width:_circleView.height * scale
height:_circleView.width * scale
然后根據(jù)計(jì)算好的frame截取圖片就ok了
CGRect rect = CGRectMake(x, y, width,height);
CGImageRef tailorImageRef = CGImageCreateWithImageInRect(photo.CGImage, rect);
UIImage *tailorImage = [UIImage imageWithCGImage:tailorImageRef];
9.修改cell側(cè)滑按鈕的顏色
想實(shí)現(xiàn)cell的側(cè)滑功能很簡(jiǎn)單消返,實(shí)現(xiàn)tableView的代理方法就行了 载弄,但是系統(tǒng)提供的側(cè)滑按鈕的顏色貌似只有兩種,一個(gè)紅色一個(gè)灰色侦副,那如果想修改為下圖的藍(lán)色呢侦锯?
當(dāng)我們側(cè)滑cell的時(shí)候,cell的狀態(tài)會(huì)發(fā)生改變秦驯,就會(huì)觸發(fā)cell的TransitionToState方法尺碰,那么我們?cè)谶@個(gè)方法里就可以修改按鈕的顏色了
如圖所示,在這個(gè)方法里打印cell的subView會(huì)看到4個(gè)子視圖,其中UITableViewCellDeleteConfirmationView就是側(cè)滑按鈕的父視圖亲桥,然后循環(huán)遍歷它的子視圖洛心,就能找到我們要修改顏色的按鈕了
- (void)didTransitionToState:(UITableViewCellStateMask)state {
for (UIView *subview in self.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"UITableViewCellDeleteConfirmationView")]) {
for (UIButton *btn in subview.subviews) {
NSString *title = [btn titleForState:UIControlStateNormal];
if ([title isEqualToString:@"編輯"]) {
btn.backgroundColor = [UIColor colorWithRed:0.192 green:0.667 blue:0.969 alpha:1.000];
}
}
}
}
}
10.添加圓角的三種方式
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
imageView.image = [UIImage imageNamed:@"timg.jpeg"];
1.設(shè)置layer的cornerRadius
imageView.layer.cornerRadius = 100;
imageView.layer.masksToBounds = YES;
2.使用圖形上下文繪制
UIGraphicsBeginImageContextWithOptions(imageView.frame.size, NO, [UIScreen mainScreen].scale);
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:100] addClip];
//[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
[imageView drawRect:imageView.bounds];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image = image;
3.設(shè)置layer的mask
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:100];
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
layer.path = path.CGPath;
imageView.layer.mask = layer;
使用bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii方法可以選擇性的設(shè)置圓角
11.自定義UITextView的彈出菜單
只需要自定義UITextView,重寫canPerformAction:withSender:方法即可
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (action == @selector(copy:)) {
return YES;
} else if (action == @selector(selectAll:)) {
return YES;
}
return NO;
}
根據(jù)action來(lái)判斷题篷,需要出現(xiàn)在菜單上的返回yes词身,不需要的返回no
cut:剪切
copy:復(fù)制
paste:粘貼
selectAll:全選
12.圖片壓縮
方式一
UIImagePNGRepresentation(image);
UIImageJPEGRepresentation(image, 1); //第二個(gè)參數(shù)為壓縮系數(shù),取值范圍為0-1
方式二:
//scale為縮放比例
CGSize size = CGSizeMake(image.size.width / scale, image.size.height / scale);
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
結(jié)束語(yǔ)
遇到過(guò)的問(wèn)題番枚,遠(yuǎn)遠(yuǎn)不止上面這些法严,不過(guò)有些不記得了,以后遇到了再補(bǔ)上吧葫笼!