2、如何獲取圖片的? 一、在內存緩存中找 二、若是內存中找不到, 會去默認磁盤目錄中尋找, 若是找不到,在去自定義磁盤目錄中尋找 三、若是磁盤也找不到就會下載圖片 四、獲取圖片數據以後, 將圖片數據從NSData轉化UIImage。其中轉化根據圖片的類型進行轉化 五、默認對圖片進行解壓縮,生成位圖圖片 六、將位圖圖片返回程序員
3、圖片是如何被解壓縮的? 一、判斷圖片是不是動態圖片,若是是,不能解壓縮 二、判斷圖片是否透明,若是是,不能解壓縮 三、判斷圖片的顏色空間是否是RGB若是不是、不能解壓縮 四、根據圖片的大小建立一個上下文 五、將圖片繪製在上下文中 六、從上下文中讀取一個不透明的位圖圖像,該圖像就是解壓縮後的圖像 七、將位圖圖像返回web
####接上說 NSCache面試
//名稱
@property (copy) NSString *name;
//NSCacheDelegate代理
@property (nullable, assign) id<NSCacheDelegate> delegate;
//經過key獲取value,相似於字典中經過key取value的操做
- (nullable ObjectType)objectForKey:(KeyType)key;
//設置key、value
- (void)setObject:(ObjectType)obj forKey:(KeyType)key; // 0 cost
/*
設置key、value
cost表示obj這個value對象的佔用的消耗?能夠自行設置每一個須要添加進緩存的對象的cost值
這個值與後面的totalCostLimit對應,若是添加進緩存的cost總值大於totalCostLimit就會自動進行刪除
感受在實際開發中直接使用setObject:forKey:方法就能夠解決問題了
*/
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;
//根據key刪除value對象
- (void)removeObjectForKey:(KeyType)key;
//刪除保存的全部的key-value
- (void)removeAllObjects;
/*
當NSCache緩存的對象的總cost值大於這個值則會自動釋放一部分對象直到佔用小於該值
非嚴格限制意味着若是保存的對象超出這個大小也不必定會被刪除
這個值就是與前面setObject:forKey:cost:方法對應
*/
@property NSUInteger totalCostLimit; // limits are imprecise/not strict
/*
緩存可以保存的key-value個數的最大數量
當保存的數量大於該值就會被自動釋放
非嚴格限制意味着若是超出了這個數量也不必定會被刪除
*/
@property NSUInteger countLimit; // limits are imprecise/not strict
/*
這個值與NSDiscardableContent協議有關,默認爲YES
當一個類實現了該協議,而且這個類的對象再也不被使用時意味着能夠被釋放
*/
@property BOOL evictsObjectsWithDiscardedContent;
@end
//NSCacheDelegate協議
@protocol NSCacheDelegate <NSObject>
@optional
//上述協議只有這一個方法,緩存中的一個對象即將被刪除時被回調
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;
@end**
複製代碼
countLimit注意一下這個屬性, 這個屬性就是設置最大緩存數量,啥意思呢? 這玩意就和棧差很少, 先進先出(叫什麼FIFO?)原則。好比你countLimit設置爲5 那麼當你緩存第6個對象的時候, 本來第一個就被移除了。 因此這便就有有一個風險,也可能會是面試點,爲何,經過key去取值的時候,必定要判斷一個獲取的對象是否爲nil?答:就由於頗有可能某些對象被釋放(頂)掉了。算法
又又又可能出現的面試題!NSCache裏面緩存的對象,在什麼場景下會被釋放?數據庫
###29. 爲何刷新UI要在主線程操做數組
UIKit並非一個線程安全的類,因此涉及多個線程同時對UI進行操做會形成影響。緩存
爲何不把UIKit框架設置爲線程安全呢?安全
由於線程安全須要加鎖,咱們都知道加鎖就會消耗性能,影響處理速度,影響渲染速度,咱們一般本身在寫@property時都會寫nonatomic來追求高性能高效率。bash
假設可以異步設置view的屬性,那咱們到底是但願這些改動可以同時生效,仍是按照各自runloop的進度去改變這個view的屬性呢?服務器
假設UITableView在其餘線程去移除了一個cell,而在另外一個線程卻對這個cell所在的index進行一些操做,這時候可能就會引起crash。
若是在後臺線程移除了一個view,這個時候runloop週期尚未完結,用戶在主線程點擊了這個「將要」消失的view,那麼究竟該不應響應事件?在哪條線程進行響應?
在Cocoa Touch框架中,UIApplication初始化工做是在主線程進行的。而界面上全部的視圖都是在UIApplication 實例的葉子節點(內存管理角度),因此全部的手勢交互操做都是在主線程上才能響應
//Class也表示一個結構體指針的類型
typedef struct objc_class *Class;
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
複製代碼
struct category_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods; // 對象方法
struct method_list_t *classMethods; // 類方法
struct protocol_list_t *protocols; // 協議
struct property_list_t *instanceProperties; // 屬性
// Fields below this point are not always present on disk.
struct property_list_t *_classProperties;
method_list_t *methodsForMeta(bool isMeta) {
if (isMeta) return classMethods;
else return instanceMethods;
}
property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};
複製代碼
// 好比
dispatch_async(dispatch_get_main_queue(), ^{
// 刷新UI
});
複製代碼
一、imageName與imageWithContentsOfFile區別?
imageWithContentsOfFile: 加載本地目錄圖片,並不會緩存,佔用內存小, 不能加載image.xcassets裏面的圖片資源。 相同的圖片會被重複加載到內存中
imageName:加載到內存中, 會緩存起來, 佔用內存較大,相同的圖片不會被重複加載到內存當中,會讀取image.xcassets的圖片圖片資源。
若是不斷重複讀取同一個圖片,則使用imageName
若是不須要重複讀取同一個圖片,而且須要低內存,則使用imageWithContentsOfFile
2.IBOutlet連出來的視圖屬性爲何能夠被設置成weak?
由於連接之Xcode 內部把連接的控件 放進了一個_topLevelObjectsToKeepAliveFromStoryboard的私有數組中,這個數組強引用這全部top level的對象 因此用weak也無傷大雅。
點語法就是setter和getter方法, 然而id類 沒法肯定所指的類是什麼類型, 尋不到setter個getter方法,id類型的對象 只能用【】方法調用方法
4.id和NSObject的區別?
另外OC的基類不止有NSObject一個,還有個NSProxy虛類。因此說id類型和NSObject並非等價的。
5 . OC中 Null 與 nil的區別
6 . 自旋鎖和互斥鎖
相同點:都能保證同一時間只有一個線程訪問共享資源,都能保證系統安全
不一樣點:
互斥鎖:若是共享數據已經有了其餘線程加鎖了,線程會進行休眠狀態等待鎖,一旦被訪問的資源被解鎖,則等待資源的線程會被喚醒。信號量dispatch_semaphore 爲互斥鎖 @synchronized是NSLock的封裝 屬於互斥鎖 互斥鎖通常用於等待時間較長的狀況
**適用於**:線程等待鎖的時間較長
自旋鎖:若是共享數據已經有其餘線程加鎖了,線程會以死循環的方式等待鎖,一旦被訪問的資源被解鎖,則等待資源的線程會當即執行。OSSpinLock 屬於自旋鎖 自旋鎖通常用於時間較短的狀況,OSSpinLock
**適用於**:線程等待鎖的時間較端
複製代碼
7 . 進程和線程的區別
進程是指在系統中正在運行的一個應用程序
線程是進程中的一個實體,一個進程想要執行任務, 必須至少有一條線程,應程序啓動的時候會默認開啓一條線程,也就是主線程
一個進程擁有多個線程
8 LayoutSubviews和drawRect調用時機 LayoutSubviews調用時機
drawRect調用時機
drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 兩方法以後掉用的.因此不用擔憂在 控制器中,這些View的drawRect就開始畫了.、
9 cocoaPods裏面pod install和update的區別? **pod install **
- 通常是第一次想要爲項目添加pod的時候使用的,固然也能夠在添加和移除庫使用
- 每次pod install的時候,pod install 回爲每個安裝的pod庫在Podfile.lock文件中寫入其版本號,而且鎖定當前版本號。
- 若是pod install的時候,不會更新其版本庫,而是去下載新的或者移除當前版本 pod update
- 當執行了pod update的時候,cocoaPods不會考慮Podfile.lock中的版本。直接去更新當前全部的庫到最新,而後Podfile.lock會更新這一次的版本號。
- 有的相對佈局最終都會轉換成Frame絕對佈局 中間多了一層轉換的操做
iOS9
從HTTP升級到HTTPS App瘦身 下面有講 這裏不贅述( App瘦身 ) 新增UIStackView
iOS10
新增通知推送相關的操做。自定義通知彈窗,自定義通知類型(地理位置,時間間隔,日曆等)
iOS11
無線 調試 齊劉海兒,導航條,安全距離等
iOS12
啓動速度優化 應用啓動速度提高40% 鍵盤響應速度提高50% 相機啓動速度提高70%
iOS13
黑暗模式 詳情請查閱 www.jianshu.com/p/0da3b107f…
一、App如何瘦身?
Slicing: 這個過程是iOS9出來以後 不須要程序員干預的一個瘦身的過程,簡單來講就是咱們再上傳IPA包到iTunes Connect,而後AppStore會對app進行切片,切成特定的機型想要的數據,好比@3x給max用,@2x就自動剔除了。 是一個自動的過程、 Bitcode:是一種中間碼,若是配置了Bitcode(Xcode7之後默認開啓)的程序會在App Store Connect上被從新編譯等一系列操做,進而蘋果內部會對可執行文件進行優化,也就是說不須要咱們干預什麼東西,也操做不了, 若是後面蘋果有更牛逼的優化操做,也是蘋果的事情, 跟咱們我的開發者一毛錢關係沒有。 On Demand Resources 按需加載, 是程序員本身手動操做,說白了就是在用的時候去下載某些資源, 可是咱們本身在配置的時候都須要配置,要額外寫一些代碼啥的,等咱們提交到市場的時候, 蘋果內部會把咱們按需加載的資源從包裏面作了一些抽離操做啥的, 讓咱們的包在下載的時候更小,舉個例子,就是吃雞裏面沙漠地圖若是玩家不本身下載, 就玩不了沙漠。
**on-demond resource(ODR)**具體請查看原理版本:www.jianshu.com/p/bacedd8a3…
或者詳細使用版本:www.cocoachina.com/articles/12…
關於 **slicing, bitcode, on-demond resource(ODR)**的參考資源https://blog.csdn.net/zhuod/article/details/70051514?utm_source=blogxgwz6
二、app啓動時候都經歷了什麼?
啓動分爲兩種。 一種是以前啓動過,按了一下home鍵,而後再點啓動,這個啓動叫熱啓動,另外就是第一次啓動app,或者啓動殺死以後的app 叫作冷啓動
根據info.plist裏面的設置加載,創建沙箱,權限檢查等 加載可執行文件 加載動態庫 objc運行時的初始化處理(類的註冊,category註冊,selector惟一性檢查等等) 初始化,包括+load方法 執行main函數 Application 初始化,到 applicationDidFinishLaunchingWithOptions 執行完 渲染屏幕,到viewDidAppear 執行完畢,展示給用戶
根據info.plist裏面的設置加載,創建沙箱,權限檢查等 加載可執行文件 加載動態庫 objc運行時的初始化處理(類的註冊,category註冊,selector惟一性檢查等等) 初始化,包括+load方法
三、優化啓動時間
注意:啓動時間在小於400ms是最佳的,由於從點擊圖標到顯示Launch Screen,到Launch Screen消失這段時間是400ms。啓動時間不能夠大於20s,不然會被系統殺掉。
mian函數以前的啓動優化
mian函數以後的啓動優化 首先分析一下從main函數開始執行,到第一個頁面顯示, 這段時間作了哪些事情
- 執行didFinishLaunchingWithOptions方法
- 初始化Window,初始化基礎ViewContreoller(通常是UINavigationController+UITabViewController)
- 獲取數據(本地和遠程)
- 最後展現給用戶
- 減小建立線程(高性能iOS開發一書中提到,線程不只僅有建立時的時間開銷,還會消耗內核的內存,即應用的內存空間。 每一個線程大約消耗 1KB 的內核內存空間。線程建立的耗時(不包含啓動時間),其區間範圍在 4000~5000 微秒,即 4~5 毫秒。建立線程後啓動線程的耗時區間爲 5~100 毫秒,平均大約在 29 毫秒。這是很大的時間開銷,若在應用啓動時開啓多個線程,則尤其明顯。線程的啓動時間之因此如此之長,是由於屢次的上下文切換所帶來的開銷。因此線程在開發過程當中也避免濫用)
- 合併或者刪減沒必要要的類(或者分類)和函數objc的類越多,函數越多啓動越慢
- 在設計師可接受的範文儘可能使用小的圖片
didFinishLaunchingWithOptions
applicationDidBecomeActive
複製代碼
優化的核心思想就是,能延時的延時, 不能延時的儘可能放到後臺去優化。
- 日誌、統計等必須在 APP 一啓動就最早配置的事件。仍然把它留在 didFinishLaunchingWithOptions 裏啓動。
- 項目配置、環境配置、用戶信息的初始化 、推送、IM等事件,這些功能在用戶進入 APP 主體的以前是必需要加載完的,把他放到廣告頁面的viewDidAppear啓動。
- 其餘 SDK 和配置事件,因爲啓動時間不是必須的,因此咱們能夠放在第一個界面的 viewDidAppear 方法裏,這裏徹底不會影響到啓動時間。
- 每次用NSLog方式打印會隱式的建立一個Calendar,所以須要刪減啓動時各業務方打的log,或者僅僅針對內測版輸出log
- 儘可能不要在didFinishLaunchingWithOptions 裏面建立和開啓多線程
複製代碼
參考文獻https://www.jianshu.com/p/f40fdd8799b8 其文章內部做者談到了美團關於啓動優化的相關分析,看似似曾類似,沒記錯的畫《高性能iOS應用開發》這本書就是美團這幾個哥們兒翻譯的吧,實現方式和書中頗爲類似。
三、App電量消耗
定位優化
1.儘可能不要實時更新 2.定位精度儘可能不要過高
網絡優化
1.減小、壓縮網絡數據 2.能使用緩存就使用緩存,減小網絡請求 3.斷點續傳 4.批量傳輸 5.設置適合的超時時間,用戶能夠取消耗時的網絡請求 6.網絡不可用時就不要再執行網絡請求了
CPU/GPU優化
相關離屏渲染操做盡可能避免 內存管理處理好 使用懶加載 使用繪製 圖片與imageView相同大小避免多餘運算 Timer的時間間隔不宜過短,知足需求便可 線程適量,不宜過多,不要阻塞主線程 適當使用多線程 減小視圖刷新:確保必要的時候才刷新,能刷新1行cell最好只刷新一行;
爲了優化耗電咱們還能夠作: 1.儘可能不要使用定時器 2.優化I/O操做(文件的讀寫操做) 2.1最好不要頻繁讀寫小數據,最好批量讀寫 2.2數據量比較大的時候能夠考慮使用數據庫 2.3讀寫大量重要數據時,考慮用dispatch_io,其提供了基於GCD的異步操做文件I/O的API。用dispatch_io系統會優化磁盤訪問
高性能iOS應用開發中提到一下幾點
- 數據處理(例如文本格式優化)
- 待處理的數據大小----更大的顯示屏容許軟件在單個視圖中展現更多的信息,但這也意味着要處理更多的數據
- 處理數據的算法和數據結構
- 執行更新的次數,尤爲是在數據更新以後,觸發應用的狀態或者UI進行更新(好比刷新單行cell)
- 服務器中的數據儘可能不要在客戶端上處理(例如服務器字符串,在客戶端進行拆分操做)
- 按需加載(例如tableViewcell 不須要一會兒所有渲染,快速滑動的時候 過程當中的留白處理。)
- 在進行網絡請求以前,先檢查是否有網絡鏈接。(沒網絡的時候,不要請求網絡)
- 避免沒有鏈接WiFi的狀況下進行高帶寬的消耗操做(由於3G、4G等手機網絡耗電量遠大於WIFi信號),例如視頻流在4G或者非Wifi狀況下應該給出響應的提示。
- 儘可能不要實時更新
- 定位精度儘可能不要過高
##3、算法
數組在內存中是逐個存放的,鏈表每隔節點沒有相對固定的位置關係 數組被聲明後,大小就固定了,不能進行動態擴充。 鏈表能夠動態生成節點,而且添加到已有的鏈表後面 數組存在越界問題,鏈表則不存在 數組的插入刪除的時間複雜度是O(n),鏈表O(1) 數組的查詢下標時間複雜度爲O(1), 鏈表爲O(n) 根據值查詢的時間複雜度,鏈表和數組都是O(n)
思路 假設有兩個學生A和B在跑道上跑步,兩人從相同起點出發,假設A的速度爲2m/s,B的速度爲1m/s,結果會發生什麼? 答案很簡單,A繞了跑道一圈以後會追上B! 將這個問題延伸到鏈表中,跑道就是鏈表,咱們能夠設置兩個指針,a跑的快,b跑的慢,若是鏈表有環,那麼當程序執行到某一狀態時,a==b。若是鏈表沒有環,程序會執行到a==NULL,結束。
###一、 調換A和B
// int a = 10;
// int b = 20;
//
// a = a + b;
// b = a - b;
// a = a - b;
//
// NSLog(@"a = %d , b = %d", a, b);
//
//
// a = a*b;
// b = a/b;
// a = a/b;
//
// NSLog(@"1 ===== : a = %d , b = %d", a, b);
複製代碼
###二、最大公約數
// int n = 20,v = 30,temp = 0,max,min;
//
// if (n>v) {
// max = n;
// min = v;
// } else {
// max = v;
// min = n;
// }
//
//
// while (min != 0) {
// temp = max - min;
// max = min;
// min = temp;
// }
//
// NSLog(@"%d", max);
複製代碼
###三、打印2 - 100 的素數(質數) 除了1和自身被整除的.
// NSMutableArray *primeNumberArray =[NSMutableArray array];
// for(int i=2; i<=100; i++) {
//
// NSInteger n = 0;
//
// for(int j = 1; j <= i; j++) {
//
// if(i % j == 0) {
// n = n + 1;
// }
// }
//
// if(n == 2) {
// [primeNumberArray addObject:@(i)];
// }
// }
//
// NSLog(@"primeNumber = %@",primeNumberArray);
//
複製代碼
###四、 字符串倒敘
// NSString *string = @"hei Son 我是你father";
// NSMutableString *string1 = [NSMutableString string];
// for (NSInteger i = string.length; i>0; i--) {
// [string1 appendString:[string substringWithRange:NSMakeRange(i -1,1)]];
// }
//
// NSLog(@"%@", string1);
//
複製代碼
###五、 尋找出字符串中有那些中文
// for (int i = 0; i < string.length; i++) {
// NSString *str1 = [string substringWithRange:NSMakeRange(i, 1)];
// const char *cStr = [str1 UTF8String];
// if (strlen(cStr) == 3 ) { // oc中 中文三個字節
// NSLog(@"%@", str1);
// }
// }
複製代碼
####6. 排序
比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。 對每一對相鄰元素作一樣的工做,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。 針對全部的元素重複以上的步驟,除了最後一個。 持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較
for (int i = 0; i<result.count-1; i++) {
for (int j = 0; j<result.count-1-i; j++) {
NSInteger left = [result[j] integerValue];
NSInteger right = [result[j+1] integerValue];
if (left>right) {
[result exchangeObjectAtIndex:j withObjectAtIndex:j+1];
}
}
}
NSLog(@"%@",result);
時間複雜度O(n^2)
複製代碼
選擇排序就是經過遍歷數組找出每次遍歷數組的最小元素的下標,而後將其按順序從第一位依次排列
//self.array = @[@2,@4,@3,@1];
NSMutableArray *mutableArray = [self.array mutableCopy];//oc數組中不能存儲基本數據類型,因此快速賦值完成後,系統默認數組元素爲NSNumber類型
if (mutableArray == nil || [mutableArray count] == 0)
{
return;
}
for (int i = 0; i < [mutableArray count]; i++)
{
NSInteger minIdx = i;//默認最小值的索引爲i
for (int j = i+1; j < [mutableArray count]; j++)//經過循環尋找當前數組中最小值的索引值
{
if (NSOrderedAscending == [mutableArray[j] compare:mutableArray[minIdx]])//NSNumber類判斷大小方法,這句話的意思是當mutableArray[j] <mutableArray[minIdx]時
{
minIdx = j;//更新數組中最小值的索引值
}
}
[mutableArray exchangeObjectAtIndex:i withObjectAtIndex:minIdx];//將每次循環結束後找到的最小值交換到數組的第i位
NSLog(@"%@",mutableArray);
}
}
時間複雜度爲O(n)。最壞狀況下仍爲O(n^2)
複製代碼
NSMutableArray *priceArray = [NSMutableArray arrayWithObjects:@"0.2",@"5",@"44",@"67",@"98.5",@"1.55", nil];
[priceArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
if ([obj1 integerValue] < [obj2 integerValue]){
return NSOrderedAscending;
} else {
return NSOrderedDescending;
}
}];
這裏再次獲得的priceArray即爲升序排列的數組;
若果想要獲得降序的調換一下return的位置便可
複製代碼
####7 尋找最近的公共View
// 全部View的父View
+ (NSArray *)superViews:(UIView *)view{
if (view==nil) {
return @[];
}
NSMutableArray *result = [NSMutableArray array];
while (view!=nil) {
[result addObject:view];
view = view.superview;
}
return [result copy];
}
// 相互對比兩個節點中的view,出現同樣就返回
+ (UIView *)commonView_1:(UIView *)viewA andView:(UIView *)viewB{
NSArray *arr1 = [self superViews:viewA];
NSArray *arr2 = [self superViews:viewB];
for (NSUInteger i =0; i<arr1.count; ++i) {
UIView *targetView = arr1[i];
for (NSUInteger j=0; j<arr2.count; ++j) {
if (targetView == arr2[j]) {
return targetView;
}
}
}
return nil;
}
// 利用NSSet中的hash表,能夠將上面代碼進行進一步優化
+ (UIView *)commomView_2:(UIView *)viewA andView:(UIView *)viewB{
NSArray *arr1 = [self superViews:viewA];
NSArray *arr2 = [self superViews:viewB];
NSSet *set = [NSSet setWithArray:arr2];
for (NSUInteger i =0; i<arr1.count; ++i) {
UIView *targetView = arr1[i];
if ([set containsObject:targetView]) {
return targetView;
}
}
return nil;
}
複製代碼
####8.數組題:如何在有序數組中找出和等於給定值的兩個元素?
NSArray *arr = @[@"1", @"12", @"13", @"23", @"31", @"43", @"52", @"66", @"88", @"111", @"127", @"199"];
[self confirmNumbers:arr total:199];
----
- (void)confirmNumbers:(NSArray *)array total:(NSInteger)totalNmuber {
if (array.count <= 1) { return; }
NSInteger tempAddCount = 0;
NSInteger tempDeleltCount = 0;
for (int i = 0; i <= array.count; i++) {
NSInteger tNamber = [array[tempAddCount] integerValue] + [array[array.count-1-tempDeleltCount] integerValue];
if (tNamber == totalNmuber) {
NSLog(@"%ld, %ld, 第一個元素%@ - 後面的元素%@", (long)tempAddCount, (long)tempDeleltCount, array[tempAddCount] ,array[array.count-tempDeleltCount-1]);
break;
} else if (tNamber < totalNmuber) {
tempAddCount ++;
} else {
tempDeleltCount ++;
}
if (i == array.count - 1) {
NSLog(@"啥都沒匹配着");
break;
}
}
}
複製代碼
NSLog(@"%ld", [self getSumResult:100]);
- (NSInteger)getSumResult:(NSInteger)number {
if (number <=0 ) {
return number;
}
return number + [self getSumResult:number - 1];
}
// 遞歸效率差的緣由是 每一次調用函數(本身)都是要有內存開銷的,影響CUP的效率
複製代碼
NSArray* arr = @[@"1",@"2",@"3"];
arr = [arr sortedArrayUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
int seed = arc4random_uniform(2);
if (seed) {
return [str1 compare:str2];
} else {
return [str2 compare:str1];
}
}];
複製代碼
##3、軟技術篇 ###1.開發過程當中, 你碰到那些技術難點?是怎麼解決的?
- SD4.X的解決辦法
[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
- SD5.0 及以上的解決辦法
SDWebImageAvoidDecodeImage添加了這個枚舉,意思是在子線程程解壓縮圖片
[self.imageView sd_setImageWithURL:self.url placeholderImage:[UIImage imageNamed:@"logo"] options:SDWebImageAvoidDecodeImage];
複製代碼
更多詳情請查看 也必須看!
在舉個例子「因爲在開發過程當中,用到的全部圖片必須是原圖, 問題就出現了, 若是幾張圖片是超清的超大圖片,把這些圖片所有渲染到一個畫布中而且進行隨機形狀的超高清拼圖, 這個過程會出現一個奇怪的問題,就是繪製的結果是大機率會變成 一張純白色的沒有任何圖案的圖片,出現的緣由是由於在App內部若是正在運行的內存達到必定的值得時候繪製圖像的上下文就會獲取一個空白的圖片,解決辦法由於是機率事件因此內部作了一個循環渲染的機制,在特定次數範圍內,若是出現繪製成功的話返回正常的圖片,若是沒有正確繪製,則作一個內部的提示語App內部沒有任何反應, 因此若是製做跟圖片相關的項目,特別涉及到自定義系統相冊的功能,最好優化好內存問題,由於內存優化很差,致使的問題有不少系統層級的BUG。並且很難找到問題的緣由。
** 這就把面試官引向了一個優化內存的事情。好比優化內存的工具, 檢測內存泄漏,循環引用的工具等等。 下面會一一介紹。**
###2.過程當中, 你用過什麼調試工具?
Leaks(泄漏):通常的查看內存使用狀況,檢查泄漏的內存,並提供了全部活動的分配和泄漏模塊的類對象分配統計信息以及內存地址歷史記錄;
- locations(內存分配):跟蹤過程的匿名虛擬內存和堆的對象提供類名和可選保留/釋放歷史;
複製代碼
這是陸陸續續面試中總結出來的, 總之,有的問題回答的比較撿漏, 有的問題模棱兩可,有些面試官的反饋比較紮實,有些面試官說回答的泰國籠統不夠細緻,反正這東西見仁見智吧。
最後附上一個寫的很詳細的基礎知識博主寫的一些列,我的以爲幫助很大!juejin.im/user/5e09e4…
此文章基本上不會添加新的問題了,若是有錯誤我會及時改正,避免耽誤有須要幫助的小夥伴! 最後一次更新時間:2020年07月20日