1.如果是隻讀,需要用線程鎖嗎 ?
不需要。線程安全是由於多線程訪問和修改共享資源而引起不可預測的結果。因此,如果都是訪問共享資源而不去修改共享資源也可以保證線程安全,比如:設置只讀屬性的全局變量
2.自動釋放池原理?
3.SDWebImage如何處理gif圖?從緩存取出來還是gif嗎?
在SDWebImage的核心文件中有對UIImage的gif擴展,在這個擴展裏面,程序獲取到了gif每一幀圖像以及對應的顯示時間
for (size_t i = 0; i < count; i++) { //獲取gif每一幀圖像 CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); if (!image) { continue; } //sd_frameDurationAtIndex 獲取每一幀圖像對應的顯示時間 duration += [self sd_frameDurationAtIndex:i source:source]; [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; CGImageRelease(image); } if (!duration) { duration = (1.0f / 10.0f) * count; } //創建動圖 animatedImage = [UIImage animatedImageWithImages:images duration:duration]; }
獲取每一幀圖像的顯示時間的目的僅僅是爲了計算gif動畫的總時長,並沒有給每一幀圖像的顯示時間分配相應的權重,導致每一幀圖像顯示的時間爲平均時間,視覺上給人帶來了卡頓效果
4.手勢衝突如何處理?
a.修改手勢響應優先級
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
b.同時響應
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
5.按層遍歷二叉樹?
- 前序遍歷:ABCDEFGHK。1根 2左後根 3右後根
- 中序遍歷:BDCAEHGKF。1左後根 2根 3右後跟
- 後序遍歷:DCBHKGFEA。1左後根 2右後跟 3根
6.手寫多邊形view,不規則圖形怎麼判斷點擊事件?
UIBezierPath繪製多邊形,- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; [UIBezierPath containsPoint:]判斷點擊的點是否在圖形內
7.工廠,抽象工廠?
8.cell複用叫什麼設計模式?
工廠設計模式
9.單例如何讓其他類不用init?
10.使用的關鍵字,NSAvaliable,還有哪些關鍵字?
NS_UNAVAILABLE -- 指定 方法不可調用
- (instancetype)init NS_UNAVAILABLE;
DEPRECATED_ATTRIBUTE -- 方法過期
/** 方法h過期 */ - (void)method DEPRECATED_ATTRIBUTE; // 這裏可以提示給其他開發者 替換的方法 - (void)method1 __attribute__ ((deprecated("# 請使用 init")));
NS_DEPRECATED_IOS(5_0, 12_0) -- 可以指定該方法依附的版本有效
- (void)method4 NS_DEPRECATED_IOS(5_0, 12_0);
NS_DESIGNATED_INITIALIZER
/** 這個關鍵字 用來修飾init方法,被修飾的init方法 必須調用super的NS_DESIGNATED_INITIALIZER方法 */ - (instancetype)initMethod5 NS_DESIGNATED_INITIALIZER;
11.block裏weak-strong爲什麼用strong不會循環引用?
爲什麼使用weakSelf?
通過 clang -rewrite-objc 源代碼文件名 將代碼轉爲c++代碼(實質是c代碼),可以看到block是一個結構體,它會將全局變量保存爲一個屬性(是__strong的),而self強引用了block這會造成循環 引用。所以需要使用__weak修飾的weakSelf。
爲什麼在block裏面需要使用strongSelf?
是爲了保證block執行完畢之前self不會被釋放,執行完畢的時候再釋放。這時候會發現爲什麼在block外邊使用了__weak修飾self,裏面使用__strong修飾weakSelf的時候不會發生循環引用?!
PS:strongSelf只是爲了保證在block內部執行的時候不會釋放,但存在執行前self就已經被釋放的情況,導致strongSelf=nil。注意判空處理。
爲什麼不會引起循環引用?
因爲block截獲self之後self屬於block結構體中的一個由__strong修飾的屬性會強引用self, 所以需要使用__weak修飾的weakSelf防止循環引用。
block使用的__strong修飾的weakSelf是爲了在block(可以理解爲函數)生命週期中self不會提前釋放。strongSelf實質是一個局部變量(在block這個“函數”裏面的局部變量),當block執行完畢就會釋放自動變量strongSelf,不會對self進行一直進行強引用。總結
外部使用了weakSelf,裏面使用strongSelf卻不會造成循環,究其原因就是因爲weakSelf是block截獲的屬性,而strongSelf是一個局部變量會在“函數”執行完釋放。
12.自己如何實現一個安全的dict?
13.面向對象六大原則?
- 單一職責原則【SRP】 -- 就一個類而言,應該僅有一個引起他變化的原因
- 開閉原則[【OCP】-- 對於擴展是開放的 對於本類修改是關閉的
- 里氏替換原則【LSP】 --子類可以實現父類的抽象方法,但是不能覆蓋,且返回值要比父類嚴謹。子類可以添加的獨立方法,也可以重載,但是重載的時候要比父類的方法參數寬鬆
- 依賴倒置原則【DIP】--高層次模塊不應該依賴低層次模塊,抽象不應該依賴細節,細節應該依賴抽象
- 接口隔離原則【ISP】--客戶端不應該依賴不需要的接口(避免接口設計的時候 有冗餘的方法)
- 迪米特原則【LOD】--一個對象應該對其他對象保持最小的瞭解 (降低類與類之間的耦合)
14.異步繪製和離屏渲染,如何優化?如何異步?
15.gcd 中Serial(串行)和Concurrent(併發),Synchronous(同步)和Asynchronous(異步)?
- 串行隊列:線程只能依次有序的執行。dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL)
- 併發隊列:線程可以同時一起進行執行。實際上是CPU在多條線程之間快速的切換。(併發功能只有在異步(dispatch_async)函數下才有效)
dispatch_queue_t queue1 = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);- 同步(sync):一個接着一個,前一個沒有執行完,後面不能執行,不開線程。dispatch_sync(dispatch_get_global_queue(0, 0), ^{
});- 異步(async):開啓多個新線程,任務同一時間可以一起執行。異步是多線程的代名詞dispatch_async(dispatch_get_global_queue(0, 0), ^{
});
16.線程通信還有其他什麼方式?
NSThread
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
GCD
dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 1.下載圖片(耗時) dispatch_async(queue, ^{ // 1.創建URL NSURL *url = [NSURL URLWithString:@"http://stimgcn1.s-msn.com/msnportal/ent/2015/08/04/7a59dbe7-3c18-4fae-bb56-305dab5e6951.jpg"]; // 2.通過NSData下載圖片 NSData *data = [NSData dataWithContentsOfURL:url]; // 3.將NSData轉換爲圖片 UIImage *image = [UIImage imageWithData:data]; // 4.更新UI // 如果是通過異步函數調用, 那麼會先執行完所有的代碼, 再更新UI // 如果是同步函數調用, 那麼會先更新UI, 再執行其它代碼 dispatch_sync(dispatch_get_main_queue(), ^{ self.imageView.image = image; }); });
NSOperation
// 1.創建一個新的隊列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.添加任務(操作) [queue addOperationWithBlock:^{ // 2.1在子線程中下載圖片 NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img2/M04/8C/74/CgAPDk9dyjvS1AanAAJPpRypnFA573_700x0x1.JPG"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; // 2.2回到主線程更新UI [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }]; }];
17.繼承、分類、類擴展的優缺點,如何選擇?
- 繼承的好處:代碼重用,子類擁有父類所有的方法和屬性
- 繼承的缺點:父類的改變影響所有的子類。子類與父類耦合度很高。當子類中需要有自己獨特的行爲,不想使用父類的方法,可以把父類的方法覆蓋掉:直接在子類中用一樣的名字寫個方法。不用在.h中寫,因爲父類已經聲明過了,直接在.m中重寫。
- 分類的好處:擴展原有類的方法
- 分類的缺點:不能增加成員變量,多個分類有同名方法依據類編譯順序,執行最後編譯的方法
- 類擴展的好處:類擴展得到的屬性和方法,都是私有的!在外界中無法直接使用
- 類擴展的缺點:外界無法直接使用
18.代碼和nib加載的生命週期?
生命週期
[ViewController initWithCoder:]
或[ViewController initWithNibName:Bundle]
: 首先從歸檔文件中加載UIViewController
對象。即使是純代碼,也會把nil
作爲參數傳給後者。[UIView awakeFromNib]:
作爲第一個方法的助手,方法處理一些額外的設置。[ViewController loadView]
:創建或加載一個view
並把它賦值給UIViewController
的view
屬性。
-[ViewController viewDidLoad]
: 此時整個視圖層次(view hierarchy)
已經放到內存中,可以移除一些視圖,修改約束,加載數據等。[ViewController viewWillAppear:]
: 視圖加載完成,並即將顯示在屏幕上。還沒設置動畫,可以改變當前屏幕方向或狀態欄的風格等。[ViewController viewWillLayoutSubviews]
即將開始子視圖位置佈局[ViewController viewDidLayoutSubviews]
用於通知視圖的位置佈局已經完成[ViewController viewDidAppear:]
:視圖已經展示在屏幕上,可以對視圖做一些關於展示效果方面的修改。[ViewController viewWillDisappear:]
:視圖即將消失[ViewController viewDidDisappear:]
:視圖已經消失[ViewController dealloc:]
:視圖銷燬的時候調用視圖切換
- BBB_VC initWithNibName:bundle:
- BBB_VC loadView
- BBB_VC viewDidLoad
- AAA_VC viewWillDisappear:
- BBB_VC viewWillApear:
- BBB_VC viewWillLayoutSubviews
- BBB_VC viewDidLayoutSubviews
- AAA_VC viewDidDisappear:
- BBB_VC viewDidAppear:
19.GCD dispatch_sync同步引起死鎖的問題?
dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"hello"); });
執行這個dispatch_get_main_queue隊列的是主線程。執行了dispatch_sync函數後,將block添加到了main_queue中,同時調用dispatch_syn這個函數的線程(也就是主線程)被阻塞,等待block執行完成,而執行主線程隊列任務的線程正是主線程,此時他處於阻塞狀態,所以block永遠不會被執行,因此主線程一直處於阻塞狀態。因此這段代碼運行後,並非卡在block中無法返回,而是根本無法執行到這個block。
20.循環引用的場景?
- 在dealloc中銷燬NSTimer,Timer不停止工作不會走到dealloc
- self.block中調用self,互相持有
- delegate用strong、retain屬性,互相持有
21.算法題
1.給定排好序的數組a[n],找到m的位置,沒有則返回-1
2.給定金額m,找到5元、2元、1元的組合
22.HTTP和HTTPS攻擊和防攻擊策略
1
23.界面卡頓和主線程切換的關係
1
24.GCD實現線程控制
1
25.多線程修改和讀取屬性
1
26.CGImage屬性用什麼關鍵字,strong,weak,assign
1