YouKu iOS筆試題

fl_zxf 8年前發布 | 34K 次閱讀 設計模式 iOS開發 移動開發


序言

最近收到某某同學將去youku的iOS筆試題的郵件,希望筆者能整理一下,并提供參考答案。筆者決定整理出來,并分享給大家。當然,與此同時,也想看看youku的筆試題到底有多難,也考考自己有多少料吧!

如果所提供的參考答案有任何值得置疑的地方,請一定要在評論中指出!

題照

1、如何聲明私有變量和私有方法?

參考答案:

  • [email protected],這樣就是私有的成員變量了:
 
@interfaceHYBTestModel: NSObject {
  @private NSString *_userName;
}
@end
 
  • 沒有關鍵字聲明為私有方法,因為ObjC中也沒有真正意義上的私有方法。我們要讓方法成員私有,只能通過放在.m文件中定義而不暴露在外部。但是,如果有人知道內部此這么一個方法,那么也是可以訪問的。

先說明:ObjC中沒有絕對的私有變量和私有方法。

如何修改私有成員變量的值?

 
HYBTestModel *model = [[HYBTestModel alloc]init];
 
// 通過KVC可以輕松修改私有成員變量
// 自己加一個打印就可以看到有值了!
[modelsetValue:@"修改私有變量的值"forKey:@"_userName"];
 

那又如何訪問私有成員變量?

 
Ivar userNameIvar = class_getInstanceVariable([modelclass], "_userName");
NSString *userName = object_getIvar(model, userNameIvar);
 

我們可以通過runtime來獲取對象的成員變量Ivar,然后再通過object_getIvar來獲取某個對象的成員變量的值。

看到這里,還相信ObjC中所謂私有變量嗎?

2、assign、retain、copy分別起什么作用?重寫下面的屬性的getter/setter方法

 
@property (nonatomic, retain) NSNumber *num;
 

參考答案:

從題目可知這問的是MRC下的問題。在MRC下:

  • assign用于非對象類型,對于對象類型的只用于弱引用。
  • retain用于對象類型,強引用對象
  • copy用于對象類型,強引用對象。

重寫setter/getter(如何重寫getter和setter,是不會自動登錄_num成員變量的,需要自己手動聲明):

 
- (NSNumber *)num {
  return _num;
}
 
- (void)setNum:(NSNumber *)aNum {
  if (_num != aNum) {
    [_numrelease];
    _num = nil;
    
    _num = [aNumretain];
  }
}
 

3、如何聲明一個delegate屬性,為什么?

參考答案:

聲明屬性時要,在ARC下使用weak,在MRC下使用assign。比如:

 
@property (nonatomic, weak) id<HYBTestDelegate> delegate;
 

在MRC下,使用assign是因為沒有weak關鍵字,只能使用assign來防止循環引用。在ARC下,使用weak來防止循環引用。

4、autorelease的對象何時被釋放

參考答案:

如果了解一點點Run Loop的知道,應該了解到:Run Loop在每個事件循環結束后會去自動釋放池將所有自動釋放對象的引用計數減一,若引用計數變成了0,則會將對象真正銷毀掉,回收內存。

所以,autorelease的對象是在每個事件循環結束后,自動釋放池才會對所有自動釋放的對象的引用計數減一,若引用計數變成了0,則釋放對象,回收內存。因此,若想要早一點釋放掉auto release對象,那么我們可以在對象外加一個自動釋放池。比如,在循環處理數據時,臨時變量要快速釋放,就應該采用這種方式:

 
for (int i = 0; i < 10000000; ++i) {
  @autoreleasepool {
      HYBTestModel *tempModel = [[HYBTestModel alloc]init];
      // 臨時處理
      // ...
  } // 出了這里,就會去遍歷該自動釋放池了
}
 

5、這段代碼有問題嗎?如何修改?

 
for (int i = 0; i < 10000; ++i) {
  NSString *str = @"Abc";
  str = [strlowercaseString];
  str = [strstringByAppendingString:@"xyz"];
  
  NSLog(@"%@", str);
}
 

參考答案:

這道題從語法上看沒有任何問題的,當然,既然面試官出了這一道題,那肯定是有問題的。

問題出在哪里呢?語法沒有錯啊?內存最后也可以得到釋放啊!為什么會有問題呢?是的,問題是挺大的。這對于不了解iOS的自動釋放池的原理的人或者說內存管理的人來說,這根本看不出來這有什么問題。

問題就出在內存得不到及時地釋放。為什么得不到及時地釋放?因為Run Loop是在每個事件循環結束后才會自動釋放池去使對象的引用計數減一,對于引用計數為0的對象才會真正被銷毀、回收內存。

因此,對于這里的問題,一個for循環執行10000次,會產生10000個臨時自動番話對象,一直放到自動釋放池中管理,內存得不到回收。

然后,現象是 內存暴漲 。正確的寫法:

 
for (int i = 0; i < 10000; ++i) {
  @autoreleasepool {
    NSString *str = @"Abc";
    str = [strlowercaseString];
    str = [strstringByAppendingString:@"xyz"];
      
    NSLog(@"%@", str);
  }
}
 

6、UIViewController的viewDidUnload、viewDidLoad和loadView分別什么時候調用?UIView的drawRect和layoutSubviews分別起什么作用?

參考答案:

第一個問題:

  • 在控制器被銷毀前會調用viewDidUnload(MRC下才會調用)
  • 在控制器沒有任何view時,會調用loadView
  • 在view加載完成時,會調用viewDidLoad

第二個問題:

  • 在調用setNeedsDisplay后,會調用drawRect方法,我們通過在此方法中可以獲取到context(設置上下文),就可以實現繪圖
  • 在調用setNeedsLayout后,會調用layoutSubviews方法,我們可以通過在此方法去調整UI。當然能引起layoutSubviews調用的方式有很多種的,比如添加子視圖、滾動scrollview、修改視圖的frame等。

7、自定義NSOperation,需要實現哪些方法?

參考答案:

  • 對于自定義并發NSOperation,只需要實現main方法就可以了。
  • 對于自定義非并發NSOperation,需要重寫main、start、isFinished、isExecuting,還要注意在相關地方加上kvo的代碼,通知其它線程。

更多內容看這里:iOS NSOperation

8、如何擴展ObjC里面類的方法?

參考答案:

不太清楚題目的語義,好像是說擴展類方法?通過category很容易做到,這里就不說了!

9、用代碼實現一個單例

參考答案:

隨手寫一個吧:

 
+ (instancetype)sharedInstance {
  static id s_manager = nil;
  
  static dispatch_once_tonceToken;
  dispatch_once(&onceToken, ^{
    s_manager = [[HYBTestSingleton alloc]init];
  });
  
  return s_manager;
}
 

10、用代碼實現一個冒泡算法

參考答案:

冒泡算法的核心算法思想是每趟兩兩比較,將小的往上浮,大的往下沉,就像氣泡一樣從水底往水面浮。

 
void bubbleSort(int a[], int len) {
  for (int i = 0; i < len - 1; ++i) {
    // 從水底往水面浮,所以從最后一個開始
    for (int j = len - 1; j > i; j--) {
      // 后者比前者還小,將需要交換
      if (a[j] < a[j - 1]) {
          int temp = a[j];
          a[j] = a[j - 1];
          a[j - 1] = temp;
      }
    }
  }
}
 

更詳細地可閱讀:冒泡排序

11、UITableView是如何重用cell的?

參考答案:

UITableView提供了一個屬性:visibleCells,它是記錄當前在屏幕可見的cell,要想重用cell,我們需要明確指定重用標識(identifier)。

當cell滾動到屏幕之外時,就會被放到可重用數組中。當有一個cell滾動出屏幕之外,同樣也會有新的cell要顯示到屏幕上,因此這個新顯示出來的cell就會先從可重用數組中通過所指定的identifier來獲取,如果能夠獲取到,則直接使用之,否則創建一個新的cell。

12、如果更高效地顯示列表

參考答案:

要更高效地顯示列表(不考慮種種優化),可以通過以下方法處理(只是部分):

  • 提前根據數據計算好高度并緩存起來
  • 提前將數據處理、I/O計算異步處理好,并保存結果,在需要時直接拿來使用

13、Cocoa中MVC是怎么實現的?

參考答案:

這個問題三言兩語講不明白。簡單來說,M對應于Model(數據層)、V對應于View(視圖層)、C對應于Controller(控制器層)。

如下圖:

用戶在V上操作,需要通過C更新M,然后將新的M交到C,C讓M更新。

更詳細可以閱讀: iOS中的MVC設計模式

14、描述KVC、KVO機制

參考答案:

KVC即是指NSKeyValueCoding,是一個非正式的Protocol,提供一種機制來間接訪問對象的屬性。KVO 就是基于KVC實現的關鍵技術之一。

KVO即Key-Value Observing,是建立在KVC之上,它能夠觀察一個對象的KVC key path值的變化。 當keypath對應的值發生變化時,會回調observeValueForKeyPath:ofObject:change:context:方法,我們可以在這里處理。

更詳細的內容,請自行百度吧,現在筆者沒有寫相關文章!

15、使用或了解哪些設計模式

參考答案:

筆者只說說我們在開發中真正常用到的設計模式(包括架構設計模式):

  • 單例設計模式
  • MVC構架設計模式
  • 工廠設計模式
  • 觀察者設計模式(比如KVC/KVO/NSNotification,也有人說不是設計模式)
  • 代理設計模式

更詳細可以看這里:23種設計模式目錄

最后

真心挺累的,整理一篇真不容易,光打字都快累死了~喜歡就打賞支持一下,雖不多,至少給點力氣~

來自: http://www.henishuo.com/youku-interview-one/

</div>

 本文由用戶 fl_zxf 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!