資料梳理-01

 

1.如果是隻讀,需要用線程鎖嗎 ?

    不需要。線程安全是由於多線程訪問修改共享資源而引起不可預測的結果。因此,如果都是訪問共享資源而不去修改共享資源也可以保證線程安全,比如:設置只讀屬性的全局變量

2.自動釋放池原理?

AutoreleasePool

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.按層遍歷二叉樹?

  1.  前序遍歷:ABCDEFGHK。1根 2左後根 3右後根
  2.  中序遍歷:BDCAEHGKF。1左後根 2根 3右後跟
  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?

如何設計並實現一個線程安全的 Map (上篇)

如何設計並實現一個線程安全的 Map (下篇)

13.面向對象六大原則?

  1. 單一職責原則【SRP】 -- 就一個類而言,應該僅有一個引起他變化的原因
  2. 開閉原則[【OCP】-- 對於擴展是開放的 對於本類修改是關閉的
  3. 里氏替換原則【LSP】 --子類可以實現父類的抽象方法,但是不能覆蓋,且返回值要比父類嚴謹。子類可以添加的獨立方法,也可以重載,但是重載的時候要比父類的方法參數寬鬆
  4. 依賴倒置原則【DIP】--高層次模塊不應該依賴低層次模塊,抽象不應該依賴細節,細節應該依賴抽象
  5. 接口隔離原則【ISP】--客戶端不應該依賴不需要的接口(避免接口設計的時候 有冗餘的方法)
  6. 迪米特原則【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並把它賦值給UIViewControllerview屬性。
    -[ViewController viewDidLoad]: 此時整個視圖層次(view hierarchy)已經放到內存中,可以移除一些視圖,修改約束,加載數據等。
  • [ViewController viewWillAppear:]: 視圖加載完成,並即將顯示在屏幕上。還沒設置動畫,可以改變當前屏幕方向或狀態欄的風格等。
  • [ViewController viewWillLayoutSubviews]即將開始子視圖位置佈局
  • [ViewController viewDidLayoutSubviews]用於通知視圖的位置佈局已經完成
  • [ViewController viewDidAppear:]:視圖已經展示在屏幕上,可以對視圖做一些關於展示效果方面的修改。
  • [ViewController viewWillDisappear:]:視圖即將消失
  • [ViewController viewDidDisappear:]:視圖已經消失
  • [ViewController dealloc:]:視圖銷燬的時候調用

視圖切換

  1. BBB_VC  initWithNibName:bundle:
  2. BBB_VC  loadView
  3. BBB_VC  viewDidLoad
  4. AAA_VC  viewWillDisappear:
  5. BBB_VC  viewWillApear:
  6. BBB_VC  viewWillLayoutSubviews
  7. BBB_VC  viewDidLayoutSubviews
  8. AAA_VC  viewDidDisappear:
  9. 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.循環引用的場景?

  1. 在dealloc中銷燬NSTimer,Timer不停止工作不會走到dealloc
  2. self.block中調用self,互相持有
  3. 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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章