iOS 知識點(diǎn)個人總結(jié)(不定期持續(xù)性更新)

1.單個控制器監(jiān)聽進(jìn)入后臺

在該控制器的-viewDidLoad方法中典奉,添加代碼監(jiān)聽notification最爬,也可以使用監(jiān)聽APP返回方法

[[NSNotificationCenter defaultCenter] addObserver:self

selector:@selector(someMethod:)

name:UIApplicationDidBecomeActiveNotification object:nil];

監(jiān)聽方法的具體實(shí)現(xiàn)

-(void)someMethod:(NSNotification *)noti

{

? ? ? ? //從該控制器進(jìn)入后臺時需要執(zhí)行的代碼

}

恢復(fù)到前臺

- (void)applicationDidBecomeActive:(UIApplication *)application{

????NSLog(@"---applicationDidBecomeActive----");

}

2.十六進(jìn)制字符串轉(zhuǎn)換成字節(jié)數(shù)組.

目標(biāo)字符串 NSString *str = @"0200107580FD7590FD750FD7590FD75A0FD";

調(diào)用方法:NSData *temp = [string hexToBytes]; ?轉(zhuǎn)換后

?byte數(shù)組?Byte byteArr[] = { 0x02, 0x00, 0x10, ... , ?0xFD };


3肚医、對于項目中的第三庫一定要進(jìn)行再次封裝匙奴,包括網(wǎng)絡(luò)叙赚、刷新怨咪、提示乏矾、模型轉(zhuǎn)換等所有能封裝的部分孟抗,一直用MJExtension來做字典轉(zhuǎn)模型,突然想用YYModel了钻心,項目中替換很麻煩凄硼,刷新也一樣,一直用第三方框架捷沸,突然想自己寫摊沉,改起來麻煩的不要不要的;

4、熟悉一下測試的幾種方案痒给,例如交叉測試(一個功能正在運(yùn)行说墨,另一個功能運(yùn)行對它的影響,例如 掃碼時打開燈光苍柏,突然退到后臺尼斧,再回來查看,可能燈光已經(jīng)熄滅试吁,按鈕還沒改變狀態(tài))等棺棵,這樣寫程序時才知道往哪些方面考慮

5、多寫點(diǎn)代碼塊,寫起代碼來會很快烛恤,我把自定義Cell都封裝了代碼塊母怜,用xib布局cell就沒有純手寫這么快了,改起來還麻煩,這就是代碼塊的好處棒动;

6糙申、主控制器因?yàn)榇a比較多,結(jié)構(gòu)一定要清晰船惨,才方便尋找柜裸,插入的類按 服務(wù)工具類+MVC 劃分,屬性按修飾符劃分粱锐,下面代碼按功能劃分疙挺,如下

#import "ViewController.h"

// 工具和服務(wù)類

#import "Header.h"

#import "Tool1.h"

#import "Tool2.h"


// Model

#import "Model1.h"

#import "Model2.h"

#import "Model3.h"


// View

#import "View1.h"

#import "View2.h"

#import "View3.h"


// Controller

#import "ViewController1.h"

#import "ViewController2.h"

#import "ViewController3.h"

@interface ViewController ()

// 按修飾符劃分

@property (nonatomic, assign) NSInteger num1;

@property (nonatomic, assign) NSInteger num2;


@property (nonatomic, strong, nonnull) NSMutableArray<NSString *> *object3;@property (nonatomic, strong, nonnull) NSMutableArray<NSNumber *> *object4;


@property (nonatomic, copy, nullable) NSString *object5;

@property (nonatomic, copy, nullable) NSString *object6;



@property (nonatomic, weak) UILabel *object1;

@property (nonatomic, weak) UILabel *object2;

@end


@implementation ViewController

- (void)viewDidLoad {? ?

????[super viewDidLoad]; ? ?

}


#pragma mark - 初始化View

- (void)initView{

?}

#pragma mark - 系統(tǒng)方法,界面顯示到銷毀

#pragma mark - 代理

#pragma mark - 按鈕點(diǎn)擊怜浅,通知铐然,定時器

#pragma mark - 輔助方法#pragma mark - 懶加載


@end


7、定時器不是馬上開始的恶座,多久觸發(fā)一次事件搀暑,多久才開始,記得在退出頁面的時候釋放定時器,否則控制器不會釋放跨琳;

8自点、如果錯誤提示中出現(xiàn)了duplicate這樣的字眼,很可能就是引入了.m文件

9脉让、UIView的tag不能為0桂敛;

10、字典轉(zhuǎn)JSON字符串溅潜;

NSData *data = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];

NSString *paramStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

11术唬、有時在動畫過程中,需要避免用戶重復(fù)操作滚澜,否則很容易崩潰粗仓。

建議動畫過程中設(shè)置[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

允許用戶操作[[UIApplication sharedApplication] endIgnoringInteractionEvents];

12博秫、如果延時執(zhí)行事件會被多次觸發(fā)潦牛,那是一件很危險的事情,需要取消前面的延時執(zhí)行事件

[selfperformSelector:<#(nonnull SEL)#>

withObject:<#(nullable id)#>afterDelay:<#(NSTimeInterval)#>];// 延時執(zhí)行


[NSObject cancelPreviousPerformRequestsWithTarget:<#(nonnull id)#>

selector:<#(nonnull SEL)#>object:<#(nullable id)#>]// 取消延時執(zhí)行


13挡育、測試某部分代碼的運(yùn)行時間

NSTimeInterval beginTime = CFAbsoluteTimeGetCurrent();

......// 執(zhí)行代碼

NSTimeInterval endTime = CFAbsoluteTimeGetCurrent();

time = endTime-beginTime;// 運(yùn)行時間


14、對某個控件截圖

UIGraphicsBeginImageContextWithOptions(view.bounds.size,NO,0);

[view.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();


15朴爬、添加毛玻璃效果

UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];

UIVisualEffectView *effectView = [[UIVisualEffectView alloc]initWithEffect:effect];

effectView.contentView = 控件;


16即寒、添加長按手勢,在手勢開始時才執(zhí)行方法,避免方法被調(diào)用兩次

- (void)longPress:(UILongPressGestureRecognizer *)longPressGesture{

????if (UIGestureRecognizerStateBegan != longPressGesture.state) {

????????return;

????}

????... // 執(zhí)行方法

}


17母赵、輸入框有值時才能點(diǎn)擊return key

textField.enablesReturnKeyAutomatically = YES;


18逸爵、isKindOfClass判斷對象是否是一個類的成員,或者是派生自該類的成員isMemberOfClass確定對象是否是當(dāng)前類的成員;

19凹嘲、tableView設(shè)置cell的分割線從屏幕左側(cè)邊緣開始

?cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0);


20师倔、tableView當(dāng)內(nèi)容不夠時,去掉底部的分割線

self.tableView.tableFooterView = [[UIView alloc]init];


21周蹭、UITableView設(shè)置為Plain的樣式時趋艘,你又有多組時,組頭就會默認(rèn)有懸浮效果凶朗,停留在上邊瓷胧,如果不想組頭懸浮在上邊,可以將樣式設(shè)為Grouped,把足部設(shè)置很小棚愤,解決這問題搓萧;

UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(x,y,w,h) style:UITableViewStyleGrouped];

tableView.sectionFooterHeight = 0.0001;


22、設(shè)置UITableViewCell之間的間距,在自定義cell中重寫setFrame方法

-(void)setFrame:(CGRect)frame{

????frame.origin.y += 5;

????frame.size.height -= 5;

????[super setFrame:frame];

}


23宛畦、修改UISearchController上searchBar的風(fēng)格瘸洛,遍歷子控件(很有用),找到合適的, 設(shè)置想要的子控件的顏色和分格次和;

UIImageView *barImageView = self.searchController.searchBar.subviews[0].subviews[0];

barImageView.layer.borderColor = [UIColor lightGrayColor];

barImageView.layer.borderWidth = 1;

UIView *textView = self.searchController.searchBar.subviews[0].subviews[1];

textView.backgroundColor = [UIColor whiteColor];


24反肋、監(jiān)測WKWebView的加載進(jìn)度

[wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];


25、一個控件獲取在某個控件上的坐標(biāo)點(diǎn)的四種方式

// 獲取View在window上的坐標(biāo)點(diǎn)的四種寫法

// 使用 convertRect:toRect 方法

CGRect rect = [view convertRect:view.bounds toRect:window];

CGRect rect = [view.superView convertRect:view.frame toRect:window];


// 使用 convertRect:from 方法

CGRect rect = [window convertRect:view.boundsfrom:view];

CGRect rect = [window convertRect:view.framefrom:view.superView];


26斯够、iOS11獲取最上面的window

// iOS 11 以前

UIView *windowView = [[UIApplication sharedApplication].windows lastObject];

// iOS 11 以后

UIView *windowView = [[UIApplication sharedApplication].windows firstObject];


27囚玫、某個控件有雙擊和單擊時,設(shè)置雙擊失敗時读规,才觸發(fā)單擊

[oneTap requireGestureRecognizerToFail:doubleTap];


28抓督、設(shè)置圖片捏合縮放,雙擊放大

// 首先把imageView添加到scrollview中

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{

????return self.imageView;

????// 在代理返回當(dāng)前imageView現(xiàn)

}


- (void)scrollViewDidZoom:(UIScrollView *)scrollView{

????// 保證繞著中心點(diǎn)縮放

????????CGSize boundsSize = self.scrollView.bounds.size;

????????CGRect frameToCenter = self.imageView.frame;

????????if (frameToCenter.size.width < boundsSize.width) {

????????????frameToCenter.origin.x = floorf((boundsSize.width - frameToCenter.size.width) * 0.5f);

????????} else {

????????????frameToCenter.origin.x = 0;

????????}

????????if (frameToCenter.size.height < boundsSize.height) {

????????????????frameToCenter.origin.y = floorf((boundsSize.height - frameToCenter.size.height) * 0.5f);

????????}else {

????????????????frameToCenter.origin.y = 0;

????????}

????????if (!CGRectEqualToRect(self.imageView.frame, frameToCenter)) {

????????????????self.imageView.frame = frameToCenter;

????????}

}


-(void)doubleTap:(UITapGestureRecognizer *)tapBgRecognizer{

????CGFloat scale = 4; // 最大縮放比例

????if (self.self.imageView.frame.frame.size.width < kScreenWidth * scale) {

????????CGPoint point = [tapBgRecognizer locationInView:self.imageView.frame];

????????CGFloat xSize = kScreenWidth / scale;

????????CGFloat ySize = kScreenHeight / scale;

????????CGRect zoomRect = CGRectMake(point.x - xSize * 0.5f, point.y - ySize * 0.5f, xSize, ySize);

????????self.scrollView.maximumZoomScale = scale;

????????// 以點(diǎn)擊點(diǎn)為中心縮放到最大

????????[self.scrollView zoomToRect:zoomRect animated:YES];

????} else {

????????[UIView animateWithDuration:0.25 animations:^{

????????self.scrollView.zoomScale = 1.0;

????????self.scrollView.contentSize = self.scrollView.bounds.size;

? ? ????self.self.imageView.frame.frame = self.originFrame; }];

????}

}


29束亏、尋找當(dāng)前控件的控制器

-(UIViewController*)ht_viewController{

????for(UIView *next = self; next; ?next = next.superview){

????????UIResponder *nextResponder = [next nextResponder];

????????if([nextResponder isKindOfClass:[UIViewController class]]{

????????????return (UIViewController *)nextResponder;

????????}

????}

????return nil;

}


30铃在、UITextField的inputView屬性是指第一響應(yīng)的不是鍵盤,而是賦值給inputView的那個view碍遍, inputAccessoryView 是指往鍵盤上添加另一個view;


31定铜、設(shè)置鍵盤在UIScrollView拖動動時消失

scrollview.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag


32、設(shè)置UITableViewCell之間的分割線顏色怕敬;

self.tableView.separatorColor = [UIColor redColor];


33揣炕、iOS9以后點(diǎn)擊狀態(tài)欄,UIScrollView可返回頂部;


34东跪、顯示狀態(tài)欄的網(wǎng)絡(luò)請求菊花畸陡;

// 顯示菊花-----NO為關(guān)閉菊花

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;


35鹰溜、讓UILabel的字體適應(yīng)指定的寬度,當(dāng)寬度大時丁恭,字體不變曹动, 寬度小時, 字體變小適應(yīng)寬度

label.adjustsFontSizeToFitWidth = YES;


36牲览、監(jiān)聽拖動進(jìn)度條時的狀態(tài)

監(jiān)聽拖動進(jìn)度條時的狀態(tài)

[slider addTarget:self action:@selector(sliderChange:event:) forControlEvents:UIControlEventValueChanged];


- (void)sliderChange:(UISlider *)slider event:(UIEvent *)event{

????UITouch *touch = [[event allTouches] anyObject];

????// 根據(jù)狀態(tài)來做相應(yīng)的事情墓陈,避免拖動時一直調(diào)用某些事件

????switch (touch.phase) {

????????case UITouchPhaseBegan: // 開始

????????case UITouchPhaseMoved: // 拖動

????????case UITouchPhaseEnded: // 結(jié)束

????????default:

????????????break;

????????}

}


37、讓UITableView的某一行滾到底部第献;

[self.tableView scrollToRowAtIndexPath:indexPath? ? atScrollPosition:UITableViewScrollPositionBottom animated:YES];


38贡必、以Modal的形式push出一個界面;

[UIView beginAnimations:nil context:NULL];

[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

[UIView setAnimationDuration:0.75];

[self.navigationController pushViewController:vc animated:NO];

[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];

[UIView commitAnimations];


39痊硕、阻止設(shè)備自動鎖屏[UIApplication sharedApplication].idleTimerDisabled = YES;在后臺不管用赊级,退出當(dāng)前頁面時,記得設(shè)為NO

40岔绸、為了避免循環(huán)引用理逊,在block中我們一般都用弱引用,但是block中的弱引用對象可能會提前釋放盒揉,造成崩潰晋被,我們需要在block中強(qiáng)引用一下這個弱對象;

__weak __typeof(self)weakSelf = self;

view.callback = ^(ViewStatus status) {

????// 強(qiáng)引用這個對象刚盈,避免執(zhí)行到一半 self釋放羡洛,造成崩潰;

????__strong __typeof(weakSelf)strongSelf = weakSelf;

????[strongSelf doSomething];

}


41藕漱、如果一個參數(shù)中需要包含多個枚舉值欲侮,用NS_OPTIONS,不要用NS_ENUM

// 位運(yùn)算保證任意組合的枚舉值進(jìn)行或運(yùn)算能得到唯一的值

typedefNS_OPTIONS(NSUInteger,TestName){

????????TestNameXiaoHua=1<<0,// 小花

????????TestNameXiaoBai=1<<1,// 小白

????????TestNameXiaoHei=1<<2// 小黑

};

[self eat:TestNameXiaoHua | TestNameXiaoBai];// 讓小花和小白有飯吃肋联;


-(void)eat:(TestName)name{

????if( (name & TestNameXiaoHua) || (name & TestNameXiaoBai) ){

????????NSLog(@"有飯吃");

????}

}


42威蕉、快速生成一個帶值的可變字典

NSMutableDictionary *mutDic = @{@"key":@"value"}.mutableCopy;


43、忽略編譯器警告

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Wgnu"????// 設(shè)置要忽略的類型 這里是GNU警告

// 代碼

#pragma clang diagnostic pop


44橄仍、為了避免多線程訪問數(shù)據(jù)庫韧涨,造成數(shù)據(jù)混亂,讓讀寫方法都在同一個隊列中進(jìn)行侮繁;

static const void * const IOKey = &IOKey;


// 開辟一個單例隊列

dispatch_queue_t NTESDispatchIOQueue(){

????static dispatch_queue_t queue;

????static dispatch_once_t onceToken;

????dispatch_once(&onceToken, ^{

????// dispatch_queue_create("", DISPATCH_QUEUE_SERIAL) queue = dispatch_queue_create("io.queue", 0);

????dispatch_queue_set_specific(queue, IOKey, (void *)IOKey, NULL); // 設(shè)置隊列的的標(biāo)記 });

????return queue;

}


typedef void(^dispatch_block)(void);

void io_sync_safe(dispatch_block block){

????// 如果是自己設(shè)置的隊列虑粥,執(zhí)行block

????if (dispatch_get_specific(IOKey)) {

????????block();

????} else// 如果不是自己設(shè)置的隊列,先創(chuàng)建隊列宪哩,再執(zhí)行block {

????????dispatch_sync(NTESDispatchIOQueue(), ^() {

????????block();

????});

}


45娩贷、監(jiān)聽UITextField值的改變,可以使用這個方法

[_textViewaddTarget:self.action:@selector(textFieldDidChangeValue:)forControlEvents:UIControlEventEditingChanged]

而不要使用這個代理锁孟,因?yàn)榭赡鼙O(jiān)聽不到

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { }育勺,


46但荤、把C++算法庫封裝在OC文件里形成靜態(tài)庫時罗岖,記得把OC的.m文件改成.mm文件


47涧至、如果視圖里面存在唯一一個UIScrollView或其子類View時,會主動設(shè)置相應(yīng)的內(nèi)邊距桑包,避免被導(dǎo)航欄遮住南蓬,如果我們的導(dǎo)航欄不透明,原點(diǎn)會從我們的導(dǎo)航欄下方算起哑了,導(dǎo)致上方留白赘方,解決這問題:

if (@available(iOS 11.0, *)) {

????????self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;????????//UIScrollView也適用

}else {

????????self.automaticallyAdjustsScrollViewInsets = NO;

?}


48、如果數(shù)組中的元素是唯一的弱左,或者要查詢某個數(shù)據(jù)是否在該數(shù)組中窄陡,不要使用NSArray, 而是使用集合NSSet,集合采用的是哈希表,查詢速度更快拆火;

49跳夭、動畫里的萬能神器CAShapeLayer,性能特別好,能實(shí)現(xiàn)很多神奇的效果们镜,做什么動畫前優(yōu)先考慮它币叹,尤其做股票財經(jīng)、健康A(chǔ)PP類的模狭,經(jīng)常需要畫圖颈抚,如果遇到性能問題,試試它嚼鹉;

50贩汉、swift中為了避免循環(huán)引用,我們使用weak或者unowned來解決锚赤,但它們是有區(qū)別的匹舞; unowned更像OC里的unsafe_unretained,當(dāng)引用對象釋放了以后宴树,它仍然會保持對引用對象的一個無效引用策菜,如果嘗試調(diào)用方法和成員屬性的話,程序就會崩潰酒贬;? weak則會在引用的內(nèi)容被釋放后又憨,它會自動地變成 nil;? 因此我們在使用它時锭吨,如果你引用對象不會釋放蠢莺, 使用unowned,寫起來方便點(diǎn)零如;? 如果你引用對象會被釋放躏将,請使用weak,例如網(wǎng)絡(luò)請求锄弱;

51、在swift中用強(qiáng)制解包!一定要非常小心祸憋,盡量少用会宪,一不小心程序就崩潰了;

52蚯窥、在swift中數(shù)組和字典都屬于值類型瓤鼻,相當(dāng)于int類型淋硝,跟oc不一樣墨林,當(dāng)你把數(shù)組賦值給另一個數(shù)組饥伊,修改數(shù)組的值不會影響另一個數(shù)組;

53荷鼠、__bridge 用于OC指針與c語言中的 void *互相轉(zhuǎn)換句携,雖然?id 和void *能夠相互轉(zhuǎn)換。但轉(zhuǎn)換為void *允乐,其安全性與賦值給__unsafe_unretained修飾符相近矮嫉,甚至?xí)汀H绻芾頃r不注意賦值對象的所有者喳篇,就會因懸垂指針而導(dǎo)致程序崩潰敞临。具體細(xì)節(jié),參考?__bridge 的那些事兒

54麸澜、void* 類型指針通用變體類型指針挺尿;可以不經(jīng)轉(zhuǎn)換,賦給其他指針炊邦,函數(shù)指針除外编矾;malloc返回的就是void*類型。

NULL指針:是一個標(biāo)準(zhǔn)規(guī)定的宏定義馁害;#define NULL ((void *) 0) ? ? ?用來表示空指針常量窄俏;

零指針:指針值為0,零值指針碘菜,沒有存儲任何內(nèi)存地址的指針凹蜈;可以使任意一種指針類型,eg:void * 忍啸;int * 仰坦;double *;

空指針:指針賦值為0计雌;0*7悄晃;3-3等之后,指針即變成空指針凿滤;即:空指針不指向任何實(shí)際的對象或者函數(shù)妈橄;NULL指針和零指針都是空指針庶近。

野指針指向垃圾內(nèi)存的指針;(1)指針變量沒有初始化(2)指針被delete或者free之后沒有置為空(3)指針操作超越了變量的范圍

懸垂指針:指向曾經(jīng)存放對象的內(nèi)存眷蚓,但是該對象已經(jīng)不存在了鼻种;delete操作完成后的指針就是懸垂指針,此時需要將指針置為0變?yōu)榱阒抵羔槪?/p>


55溪椎、WKWebView 與 JS 交互普舆,需要添加?[userController addScriptMessageHandler:self name:@"callFunction"]; ?callFunction 可自定義,與 JS 保持一致校读,才可交互。

于控制器中添加 evaluateJavaScript:方法

56.關(guān)于 -> 語法 與 .語法

self -> _topview 這個是把 self 當(dāng)成了個結(jié)構(gòu)體指針祖能;

self.topview 是把self 當(dāng)成了一個對象歉秫,或者說是結(jié)構(gòu)體變量;

另外养铸,self-> 不會觸發(fā) set方法雁芙,self. 會觸發(fā)。

. 左側(cè)可以是結(jié)構(gòu)體變量钞螟,也可以是對象兔甘;->?左側(cè)肯定是當(dāng)成 結(jié)構(gòu)體指針。

像這種用法鳞滨, k 就是個結(jié)構(gòu)體變量洞焙,p 是取了k 的地址,所以p 是個 astrct 類型指針拯啦,他就可以用->

成員變量 + 讀寫方法 = 類屬性

簡單直接的理解方式:.語法是去訪問類屬性澡匪,->是訪問成員變量。?. 語法用于尋址褒链,在c 語言中唁情,左側(cè)必須是個類型變量。而 - > 用于間接尋址甫匹。比如下圖

驗(yàn)證上面所說

第一行 &k 和 &(k.a)的地址完全一樣甸鸟,是因?yàn)樵谶@個結(jié)構(gòu)體中,于內(nèi)存存儲的時候兵迅,最開始的部分存放的就是a抢韭,然后緊接著就是b,當(dāng)拿到這個結(jié)構(gòu)題類型的變量K, 實(shí)際上就是拿到存儲的首地址喷兼。

而第二行的 p 篮绰,其實(shí)是 指針p 自身的地址,而指針指向的是 k季惯。


57.Implicit declaration of function XXX is invalid in C99

? ? ** 和CNCopySupportedInterfaces CNCopyCurrentNetworkInfo 等相關(guān)的錯?需要?#import <SystemConfiguration/CaptiveNetwork.h>


58.關(guān)于?armv7吠各、armv7s臀突、arm64、i386贾漏、x86_64 的區(qū)別

arm64:iPhone6s | iphone6s plus|iPhone6| iPhone6 plus|iPhone5S | iPad Air| iPad mini2(iPad mini with Retina Display)

armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)

armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4

i386 是針對intel通用微處理器32位處理器

x86_64是針對x86架構(gòu)的64位處理器

模擬器32位處理器測試需要i386架構(gòu)候学;

模擬器64位處理器測試需要x86_64架構(gòu);

真機(jī)32位處理器需要armv7,或者armv7s架構(gòu)纵散;

真機(jī)64位處理器需要arm64架構(gòu)梳码;


58.界面出來之前 xib 中的 frame 都不要去使用∥橄疲可以在viewDidAppear 方法里設(shè)置??♂?


59.使用CocoaPods創(chuàng)建自己的私有庫掰茶,首次使用?pod lib lint 可能遇到的問題

驗(yàn)證

這個問題是pod依賴的組件fourflusher與xcode版本不匹配造成的,可以使用如下命令:

1.sudo gem uninstall fourflusher?

2.sudo gem install fourflusher

必要情況下還需要更新pod

sudo gem update cocoapods

[!] TestLib did not pass validation, due to 3 warnings (but you can use `--allow-warnings` to ignore them).?

pod驗(yàn)證發(fā)現(xiàn)3個及以上的warning就會報這個錯蜜笤,如果只是驗(yàn)證一下工程濒蒋,能確保對外發(fā)布之前能修復(fù),可以使用 --allow-warnings

pod lib lint --allow-warnings

如果驗(yàn)證通過把兔,會看到 TestLib passed validation 沪伙,到這一步既完成驗(yàn)證。


60.WKWebView 背景透明

[self.webView setOpaque:NO];

[self.webView setBackgroundColor:[UIColor clearColor]];

[self.webView.scrollView setBackgroundColor:[UIColor clearColor]];


61.ARC 情況下堆县好、棧注意點(diǎn)

Block0在堆围橡,Block1在棧

如圖第二個Block處不使用Copy發(fā)生崩潰,通過打印可以發(fā)現(xiàn)2個Block所處區(qū)域不同缕贡,前者?blk0 在堆區(qū)翁授,而后面的blk1在棧,容易被系統(tǒng)回收善绎,在ARC 的情況下一般就直接拷貝到堆上去黔漂。

驗(yàn)證


62.App 或 Mac 程序內(nèi)使用WebView播放網(wǎng)絡(luò)視頻,禁止自動全屏:

? ? 目前在做一個Mac程序的監(jiān)控設(shè)備播放禀酱,由JavaScript控制播放炬守,發(fā)現(xiàn)程序在加載頁面后會自動彈出播放器并進(jìn)行全屏播放,碰巧視頻是采用如?.m3u8 格式剂跟,結(jié)果在退出全屏后减途,除非重新加載頁面,否則視頻無法播放曹洽;

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];? ?

configuration.allowsInlineMediaPlayback = true;? ?

self.webView =[[WKWebView alloc] initWithFrame:CGRectMake(0,20,W,H-20)configuration: configuration];

如果使用的是UIWebView:

self.webView.allowsInlineMediaPlayback = YES;

如果是在Xib中創(chuàng)建鳍置,需要勾選Inline Playback選項:

63.手機(jī)連接打印機(jī)

let printVC = UIPrintInteractionController.init()? ? ? ?

let printInfo = UIPrintInfo.printInfo()? ? ? ?

printInfo.outputType = .general? ? ? ?

printInfo.duplex = .longEdge? ? ? ?

printVC.showsPaperSelectionForLoadedPapers = true? ? ? ?

printVC.printInfo = printInfo? ? ? ?

printVC.printFormatter = webView.viewPrintFormatter()? ? ? ?

printVC.present(animated: true, completionHandler: nil)

64.關(guān)于可變數(shù)組添加對象

? ? 假設(shè)有臨時變量可變數(shù)組A,可變數(shù)組B送淆,可變數(shù)組B中有若干元素税产,當(dāng)可變數(shù)組A執(zhí)行 AddObject 添加數(shù)組B后,僅是添加可變數(shù)組B的指針,即數(shù)組B的首地址辟拷,當(dāng)操作數(shù)組B后撞羽,如移除數(shù)組元素,數(shù)組A中的數(shù)據(jù)也會隨之改變衫冻。

? ? 同理诀紊。數(shù)組A在添加字符串C后,改變字符串C的值隅俘,數(shù)組A中的元素也會改變邻奠。

65.dealloc 方法被調(diào)用后,不代表對象的內(nèi)存立刻被回收为居。詳情可以了解一下runloop內(nèi)部autoRelase的釋放機(jī)制.


66.ARC情況下碌宴,關(guān)于控制器dealloc未執(zhí)行,導(dǎo)致沒有移除通知的預(yù)防措施

????假設(shè) A颜骤、B唧喉、C三個類,都繼承自 D 類忍抽,即D類為基類,層級關(guān)系為A push B董朝,B push C鸠项,由此可以知道,程序會當(dāng)C出棧時子姜,會執(zhí)行dealloc方法祟绊,然后D類執(zhí)行dealloc,接著B執(zhí)行dealloc哥捕,D又執(zhí)行dealloc牧抽,最后是A執(zhí)行dealloc,D再執(zhí)行dealloc遥赚。故而我們可以根據(jù)這一特性來設(shè)計扬舒。

? ? 首先定義一個全局的NSCache 來存儲 某個類class,其內(nèi)部監(jiān)聽所有KVO的Key凫佛,即?class 作為NSCache 的key, 所監(jiān)聽 key的數(shù)組作為Value讲坎,也就是一個類有多個通知的情況,然后在基類的delloc中愧薛,檢查是否存在這樣的key-value晨炕,如存在,for循環(huán)Remove毫炉。

? ? 解釋:假設(shè)因?yàn)镃類中的block強(qiáng)弱引用問題瓮栗,或NSTime未釋放等原因?qū)е耫eallo未執(zhí)行,通知未移除。而當(dāng)B類出棧時若正常執(zhí)行dealloc费奸,程序會自動調(diào)用基類的dealloc弥激,其方法內(nèi)檢查到NSCache中有通知未移除,就移除通知货邓。以達(dá)到防止內(nèi)存泄漏的目的秆撮。

67. arrarWithArray 等效于 alloc init 的方式創(chuàng)建數(shù)組

深拷貝
輸出結(jié)果

68. 關(guān)于copy與mutableCopy

69. 不可變字符串相當(dāng)于常量,初始化后换况,只有當(dāng)程序結(jié)束運(yùn)行才會被釋放职辨,并不會因?yàn)槌隽撕瘮?shù)作用域或者控制器被銷毀而釋放

驗(yàn)證:開始執(zhí)行for循環(huán),循環(huán)創(chuàng)建1億個String對象戈二,CPU與內(nèi)存開始上漲

循環(huán)執(zhí)行中

循環(huán)結(jié)束舒裤,CPU使用率下降,內(nèi)存占有率不變

循環(huán)結(jié)束


70.?WWDC 2020 觉吭,蘋果宣布當(dāng)用戶退款成功時腾供,無論哪種內(nèi)購類型,開發(fā)者都能收到退款通知!

當(dāng)Apple受理了用戶(玩家)的退款申請后鲜滩,即允許退款后伴鳖,蘋果服務(wù)器會發(fā)送通知,(商家)通過處理退款信息以響應(yīng)退款通知徙硅,達(dá)到因用戶(退款)而采取的相應(yīng)行動榜聂,如扣除相關(guān)訂閱服務(wù)或游戲道具等。

流程

詳細(xì)說明:https://developer.apple.com/documentation/storekit/in-app_purchase/handling_refund_notifications

在蘋果后臺可以配置一個退款通知的回調(diào)地址(一個App配置一條鏈接):

退款回調(diào)鏈接

配置的回調(diào)鏈接必須滿足條件:

滿足應(yīng)用傳輸安全要求(使用https)

URL 最長 255 字符

注意:這里的?https?是指蘋果的 App Transport Security (ATS)嗓蘑,其中有協(xié)議的要求须肆,比如使用 Transport Layer Security (TLS) protocol 1.2 版本,具體見蘋果文檔:Preventing Insecure Network Connections | Apple Developer Documentation桩皿。


蘋果把回調(diào)的通知分為2種類型:

退款通知類型

取消通知類型

其中新增加的退款通知類型是針對:

消耗型

非消耗型

非續(xù)期訂閱

取消通知類型是針對:

自動續(xù)期訂閱


退款通知流程

流程


退款通知的內(nèi)容:

蘋果返回的通知內(nèi)容為 JSON 對象數(shù)據(jù)豌汇,所有的退款訂單的通知是在?unified_receipt?里的?latest_receipt_info?數(shù)組中:

退款數(shù)據(jù)格式
數(shù)據(jù)說明

在?unified_receipt?里的?latest_receipt_info?是一個數(shù)組,其中包含的最近的100次應(yīng)用內(nèi)購買交易:

數(shù)據(jù)中每個退款訂單的主要字段:

詳細(xì)的返回字段見官方文檔:

responseBody | Apple Developer Documentation

unified_receipt | Apple Developer Documentation

responseBody.Latest_receipt_info | Apple Developer Documentation


退款通知的響應(yīng)

您的服務(wù)器應(yīng)發(fā)送HTTP狀態(tài)代碼泄隔,以指示服務(wù)器到服務(wù)器的通知接收是否成功:

如果回調(diào)接收成功拒贱,則發(fā)送 HTTP?200。您的服務(wù)器不需要返回數(shù)據(jù)梅尤。

如果回調(diào)接收不成功柜思,請發(fā)送 HTTP?50x?或?40x?讓 App Store 重試該通知。App Store在一段時間內(nèi)嘗試重試該通知巷燥,但在連續(xù)失敗嘗試后最終停止(3次)赡盘。


注意事項:

當(dāng)您使用包含退款交易的收據(jù)?transaction_data?向蘋果服務(wù)器校驗(yàn)?verifyReceipt?時,JSON響應(yīng)中不存在退款交易缰揪,自動續(xù)訂訂閱除外陨享。

收到?REFUND?通知時葱淳,您有責(zé)任為每筆退款交易存儲,監(jiān)控并采取適當(dāng)?shù)拇胧┡坠谩#ㄒ驗(yàn)樘O果只通知一次赞厕,暫時無法在蘋果后臺查詢退款的訂單。也不能由開發(fā)者主動去蘋果服務(wù)器查詢定硝。)


自動續(xù)訂訂閱通知

這個取消通知之前就一直有皿桑,所以這里不重復(fù)了,需要的自行搜索蔬啡。

自動續(xù)訂訂閱的相關(guān)文檔:

Handling Subscriptions Billing | Apple Developer Documentation

In-App Purchases and Using Server-to-Server Notifications - WWDC 2019 - Videos - Apple Developer

Subscription Offers Best Practices - WWDC 2019 - Videos - Apple Developer

最后有2點(diǎn)诲侮,1.退款通知目前并不能在沙盒中測試;2.蘋果后臺也無法看到退款的訂單詳情箱蟆;


71.?命令行修改App版本號

? ? cd 進(jìn)入工程所在目錄后

修改 Version 版本號 - 如改成?3.0.0

/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString 3.0.0" Info.plist

修改 Build 版本號 - 如改成?3.0.202103051700

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion 3.0.202103051700" Info.plist


72. 真機(jī)調(diào)試下查看沙盒文件

連接真機(jī)設(shè)備沟绪,打開Xcode ,選擇Window -->Device and Simulator?,快捷鍵 Command + Shift + 2;

Device and?Simulator

找到對應(yīng)的APP空猜,選擇設(shè)置圖標(biāo)绽慈,點(diǎn)擊Download?Container 下載到桌面

Download?Container

完成后就會在桌面上看見如下文件,右擊 ——> 選擇“顯示包內(nèi)容”

沙盒文件
沙盒目錄

如果要想替換真機(jī)中的沙盒文件也是如上操作辈毯,在已下載好的文件中修改完成后坝疼。打開Xcode,Command + Shift + 2谆沃。選擇Replace Container裙士,選擇修改后的沙盒文件,點(diǎn)擊Open管毙。

Replace Container


73. 獲取不到內(nèi)購套餐產(chǎn)品信息的情況

1.檢查App的Bundle ID是否與蘋果商店中配置的信息統(tǒng)一;

2.檢查產(chǎn)品ID是否填寫錯誤桌硫;

3.檢查是否同意App付費(fèi)協(xié)議夭咬,及填寫銀行卡等稅務(wù)信息;

????????當(dāng)在蘋果商店配置好內(nèi)購套餐后铆隘,即便不提交審核(二進(jìn)制文件缺失)卓舵,或者審核失敗,App在沙盒環(huán)境下膀钠,仍然能獲取掏湾、購買App內(nèi)購套餐;


74. 簡單的線程死鎖

線程死鎖


75.并行與串行的區(qū)別

并行與串行的區(qū)別

在子線程中啟動定時器肿嘲,需要使用Runloop


76.OC的動態(tài)消息機(jī)制

調(diào)用某個對象的私有方法

私有方法
NSInvocation調(diào)用方法


77.字符轉(zhuǎn)換

將普通話轉(zhuǎn)換為拉丁符號融击,且?guī)б魳?biāo),包括希伯來語雳窟、阿拉伯語尊浪、泰語等多種語言。對處理除英語以外的語言和非拉丁文字時非常有用

示例
支持的類型


78.將時間戳轉(zhuǎn)換為NSDate 或 NSString (如今日0點(diǎn)時間戳1639929600 -> 2021-12-20 00:00:00)

將時間戳轉(zhuǎn)換為NSDate 或 NSString


79.在字典A中SetValue一個從字典B轉(zhuǎn)換成的字符串B‘,然后將字典A轉(zhuǎn)成字符串A’導(dǎo)致Web端解析失敗的問題

示例

? ? 因?yàn)橥值渲蠸et 字符串pkgStr拇涤,會自動為Value添加引號捣作,導(dǎo)致最后將字典infoData轉(zhuǎn)成字符串時,會出現(xiàn) "webInfo":"{xxxx 的情況鹅士,導(dǎo)致Web解析失敗券躁。

? ? 解決方法,直接在 infoData 中Set另一個字典 pkgInfo掉盅,不需要轉(zhuǎn)成字符串后再寫入

解決方案
例子

這樣就不會出現(xiàn) Web 解析失敗的問題也拜;


80.關(guān)于App后臺推送標(biāo)題、副標(biāo)題怔接、正文及圖片音頻視頻等內(nèi)容正常應(yīng)由服務(wù)器確定搪泳,但App配置文件與代碼優(yōu)先級更高。優(yōu)先級為:App配置文件(TARGETS——NotificationService——Build Settings——Info.plist Value內(nèi)修改Display Name)扼脐、NotificationService.m內(nèi)UNMutableNotificationContent對象的title屬性岸军、服務(wù)器推送內(nèi)容中的title字段,以上內(nèi)容都為空時瓦侮,系統(tǒng)默認(rèn)以App名作為推送標(biāo)題艰赞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肚吏,隨后出現(xiàn)的幾起案子方妖,更是在濱河造成了極大的恐慌,老刑警劉巖罚攀,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件党觅,死亡現(xiàn)場離奇詭異,居然都是意外死亡斋泄,警方通過查閱死者的電腦和手機(jī)杯瞻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炫掐,“玉大人魁莉,你說我怎么就攤上這事∧嘉福” “怎么了旗唁?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長痹束。 經(jīng)常有香客問我检疫,道長,這世上最難降的妖魔是什么参袱? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任电谣,我火速辦了婚禮秽梅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剿牺。我一直安慰自己企垦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布晒来。 她就那樣靜靜地躺著钞诡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪湃崩。 梳的紋絲不亂的頭發(fā)上荧降,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機(jī)與錄音攒读,去河邊找鬼朵诫。 笑死,一個胖子當(dāng)著我的面吹牛薄扁,可吹牛的內(nèi)容都是我干的剪返。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼邓梅,長吁一口氣:“原來是場噩夢啊……” “哼脱盲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起日缨,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤钱反,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匣距,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體面哥,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年毅待,在試婚紗的時候發(fā)現(xiàn)自己被綠了幢竹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡恩静,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹲坷,到底是詐尸還是另有隱情驶乾,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布循签,位于F島的核電站级乐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏县匠。R本人自食惡果不足惜风科,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一撒轮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贼穆,春花似錦题山、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至愕秫,卻和暖如春慨菱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戴甩。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工符喝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甜孤。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓协饲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親课蔬。 傳聞我的和親對象是個殘疾皇子囱稽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容