日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

那些著名或非著名的iOS面试题(中)

發布時間:2023/12/8 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 那些著名或非著名的iOS面试题(中) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

接上篇:那些著名或非著名的iOS面試題(上),本文繼續介紹一些著名或非著名的iOS面試題。

1. 反轉二叉樹,不用遞歸

/***?Definition?for?a?binary?tree?node.*?public?class?TreeNode?{*?????int?val;*?????TreeNode?left;*?????TreeNode?right;*?????TreeNode(int?x)?{?val?=?x;?}*?}*/

遞歸方式:

public?class?Solution?{public?TreeNode?invertTree(TreeNode?root)?{if?(root?==?null)?{return?null;}root.left?=?invertTree(root.left);root.right?=?invertTree(root.right);TreeNode?tmp?=?root.left;root.left?=?root.right;root.right?=?tmp;return?root;} }

Objective-C實現:

/**?*?翻轉二叉樹(又叫:二叉樹的鏡像)?**?@param?rootNode?根節點**?@return?翻轉后的樹根節點(其實就是原二叉樹的根節點)?*/+?(BinaryTreeNode?*)invertBinaryTree:(BinaryTreeNode?*)rootNode?{if?(!rootNode)?{??return?nil;?}?if?(!rootNode.leftNode?&&?!rootNode.rightNode)?{??return?rootNode;?}?[self?invertBinaryTree:rootNode.leftNode];[self?invertBinaryTree:rootNode.rightNode];?BinaryTreeNode?*tempNode?=?rootNode.leftNode;?rootNode.leftNode?=?rootNode.rightNode;rootNode.rightNode?=?tempNode;?return?rootNode;}

非遞歸方式:

+?(BinaryTreeNode?*)invertBinaryTree:(BinaryTreeNode?*)rootNode?{if?(!rootNode)?{??return?nil;?}if?(!rootNode.leftNode?&&?!rootNode.rightNode)?{??return?rootNode;?}NSMutableArray?*queueArray?=?[NSMutableArray?array];?//數組當成隊列[queueArray?addObject:rootNode];?//壓入根節點while?(queueArray.count?>?0)?{BinaryTreeNode?*node?=?[queueArray?firstObject];[queueArray?removeObjectAtIndex:0];?//彈出最前面的節點,仿照隊列先進先出原則BinaryTreeNode?*pLeft?=?node.leftNode;node.leftNode?=?node.rightNode;node.rightNode?=?pLeft;if?(node.leftNode)?{[queueArray?addObject:node.leftNode];}if?(node.rightNode)?{[queueArray?addObject:node.rightNode];}}return?rootNode; }

示例代碼參考:二叉樹

2. 寫一個單例模式

+?(AccountManager?*)sharedManager {static?AccountManager?*sharedAccountManagerInstance?=?nil;static?dispatch_once_t?predicate;dispatch_once(&predicate,?^{sharedAccountManagerInstance?=?[[self?alloc]?init];?});return?sharedAccountManagerInstance; }

3. iOS應用生命周期

應用程序的狀態:

  • Not running未運行:程序沒啟動。

  • Inactive未激活:程序在前臺運行,不過沒有接收到事件。在沒有事件處理情況下程序通常停留在這個狀態。

  • Active激活:程序在前臺運行而且接收到了事件。這也是前臺的一個正常的模式。

  • Backgroud后臺:程序在后臺而且能執行代碼,大多數程序進入這個狀態后會在在這個狀態上停留一會。時間到之后會進入掛起狀態(Suspended)。有的程序經過特殊的請求后可以長期處于Backgroud狀態。

  • Suspended掛起:程序在后臺不能執行代碼。系統會自動把程序變成這個狀態而且不會發出通知。當掛起時,程序還是停留在內存中的,當系統內存低時,系統就把掛起的程序清除掉,為前臺程序提供更多的內存。

iOS的入口在main.m文件:

int?main(int?argc,?char?*argv[]) {@autoreleasepool?{return?UIApplicationMain(argc,?argv,?nil,?NSStringFromClass([AppDelegate?class]));} }

main函數的兩個參數,iOS中沒有用到,包括這兩個參數是為了與標準ANSI C保持一致。 UIApplicationMain函數,前兩個和main函數一樣,重點是后兩個。

后兩個參數分別表示程序的主要類(principal class)和代理類(delegate class)。如果主要類(principal class)為nil,將從Info.plist中獲取,如果Info.plist中不存在對應的key,則默認為UIApplication;如果代理類(delegate class)將在新建工程時創建。

根據UIApplicationMain函數,程序將進入AppDelegate.m,這個文件是xcode新建工程時自動生成的。下面看一下AppDelegate.m文件,這個關乎著應用程序的生命周期。

1、application didFinishLaunchingWithOptions:當應用程序啟動時執行,應用程序啟動入口,只在應用程序啟動時執行一次。若用戶直接啟動,lauchOptions內無數據,若通過其他方式啟動應用,lauchOptions包含對應方式的內容。

2、applicationWillResignActive:在應用程序將要由活動狀態切換到非活動狀態時候,要執行的委托調用,如 按下 home 按鈕,返回主屏幕,或全屏之間切換應用程序等。

3、applicationDidEnterBackground:在應用程序已進入后臺程序時,要執行的委托調用。

4、applicationWillEnterForeground:在應用程序將要進入前臺時(被激活),要執行的委托調用,剛好與applicationWillResignActive 方法相對應。

5、applicationDidBecomeActive:在應用程序已被激活后,要執行的委托調用,剛好與applicationDidEnterBackground 方法相對應。

6、applicationWillTerminate:在應用程序要完全推出的時候,要執行的委托調用,這個需要要設置UIApplicationExitsOnSuspend的鍵值。

初次啟動:

iOS_didFinishLaunchingWithOptions iOS_applicationDidBecomeActive

按下home鍵:

iOS_applicationWillResignActive iOS_applicationDidEnterBackground

點擊程序圖標進入:

iOS_applicationWillEnterForeground iOS_applicationDidBecomeActive

當應用程序進入后臺時,應該保存用戶數據或狀態信息,所有沒寫到磁盤的文件或信息,在進入后臺時,最后都寫到磁盤去,因為程序可能在后臺被殺死。釋放盡可能釋放的內存。

-?(void)applicationDidEnterBackground:(UIApplication?*)application

方法有大概5秒的時間讓你完成這些任務。如果超過時間還有未完成的任務,你的程序就會被終止而且從內存中清除。

如果還需要長時間的運行任務,可以在該方法中調用:

[application?beginBackgroundTaskWithExpirationHandler:^{?NSLog(@"begin?Background?Task?With?Expiration?Handler");? }];

程序終止

程序只要符合以下情況之一,只要進入后臺或掛起狀態就會終止:

①iOS 4.0以前的系統

②app是基于iOS 4.0之前系統開發的。

③設備不支持多任務

④在Info.plist文件中,程序包含了 UIApplicationExitsOnSuspend 鍵。

系統常常是為其他app啟動時由于內存不足而回收內存最后需要終止應用程序,但有時也會是由于app很長時間才響應而終止。如果app當時運行在后臺并且沒有暫停,系統會在應用程序終止之前調用app的代理的方法 - (void)applicationWillTerminate:(UIApplication *)application,這樣可以讓你可以做一些清理工作。你可以保存一些數據或app的狀態。這個方法也有5秒鐘的限制。超時后方法會返回程序從內存中清除。

注意:用戶可以手工關閉應用程序。

4. 一工人給老板打7天工要求一塊金條 這金條只能切2次 工人每天要1/7金條 怎么分?

這道題解決的主要難點在于:不是給出去的就收不回來了,可以用交換的方法。  

把金條分成三段(就是分兩次,或者切兩刀),分別是整根金條的1/7、2/7、 4/7。  

第一天:給1/7的, 第二天:給2/7的,收回1/7的; 第三天,給1/7的; 第四天:給4/7的,收回1/7和2/7的 ;第五天:給1/7的 ;第六天:給2/7的,收回1/7的;第七天發1/7。

5. iOS中socket使用

Socket是對TCP/IP協議的封裝,Socket本身并不是協議,而是一個調用接口(API),通過Socket,我們才能使用TCP/IP協議。

  • http協議:對應于應用層

  • tcp協議:對應于傳輸層

  • ip協議:對應于網絡層

三者本質上沒有可比性。 何況HTTP協議是基于TCP連接的。

TCP/IP是傳輸層協議,主要解決數據如何在網絡中傳輸;而HTTP是應用層協議,主要解決如何包裝數據。

我 們在傳輸數據時,可以只使用傳輸層(TCP/IP),但是那樣的話,由于沒有應用層,便無法識別數據內容,如果想要使傳輸的數據有意義,則必須使用應用層 協議,應用層協議很多,有HTTP、FTP、TELNET等等,也可以自己定義應用層協議。WEB使用HTTP作傳輸層協議,以封裝HTTP文本信息,然 后使用TCP/IP做傳輸層協議將它發送到網絡上。

SOCKET原理

1、套接字(socket)概念

套接字(socket)是通信的基石,是支持TCP/IP協議的網絡通信的基本操作單元。它是網絡通信過程中端點的抽象表示,包含進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。

應 用層通過傳輸層進行數據通信時,TCP會遇到同時為多個應用程序進程提供并發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個 TCP協議端口傳輸數據。為了區別不同的應用程序進程和連接,許多計算機操作系統為應用程序與TCP/IP協議交互提供了套接字(Socket)接口。應 用層可以和傳輸層通過Socket接口,區分來自不同應用程序進程或網絡連接的通信,實現數據傳輸的并發服務。

2、建立socket連接

建立Socket連接至少需要一對套接字,其中一個運行于客戶端,稱為ClientSocket,另一個運行于服務器端,稱為ServerSocket。

套接字之間的連接過程分為三個步驟:服務器監聽,客戶端請求,連接確認。

服務器監聽:服務器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。

客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。

連 接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶 端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處于監聽狀態,繼續接收其他客戶端套接字的連接請求。

3、SOCKET連接與TCP連接

創建Socket連接時,可以指定使用的傳輸層協議,Socket可以支持不同的傳輸層協議(TCP或UDP),當使用TCP協議進行連接時,該Socket連接就是一個TCP連接。

4、Socket連接與HTTP連接

由 于通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發送數據內容,直到雙方連接斷開。但在實際網絡應用 中,客戶端到服務器之間的通信往往需要穿越多個中間節點,例如路由器、網關、防火墻等,大部分防火墻默認會關閉長時間處于非活躍狀態的連接而導致 Socket 連接斷連,因此需要通過輪詢告訴網絡,該連接處于活躍狀態。

而HTTP連接使用的是“請求—響應”的方式,不僅在請求時需要先建立連接,而且需要客戶端向服務器發出請求后,服務器端才能回復數據。

很 多情況下,需要服務器端主動向客戶端推送數據,保持客戶端與服務器數據的實時與同步。此時若雙方建立的是Socket連接,服務器就可以直接將數據傳送給 客戶端;若雙方建立的是HTTP連接,則服務器需要等到客戶端發送一次請求后才能將數據傳回給客戶端,因此,客戶端定時向服務器端發送連接請求,不僅可以 保持在線,同時也是在“詢問”服務器是否有新的數據,如果有就將數據傳給客戶端。

6. 網絡請求中post和get的區別

GET是用于獲取數據的,POST一般用于將數據發給服務器之用。

普遍答案

1.GET使用URL或Cookie傳參。而POST將數據放在BODY中。

2.GET的URL會有長度上的限制,則POST的數據則可以非常大。

3.POST比GET安全,因為數據在地址欄上不可見。

不過也有文章說其實上面的是錯誤的,具體參考這篇文章。

7. 時間復雜度和空間復雜度

由于打不出數字符號,只能貼圖了。

時間復雜度

求時間復雜度

【1】如果算法的執行時間不隨著問題規模n的增加而增長,即使算法中有上千條語句,其執行時間也不過是一個較大的常數。此類算法的時間復雜度是O(1)。

x=91;?y=100;while(y>0)?if(x>100)?{x=x-10;y--;}?else?x++;解答:?T(n)=O(1)

這段程序的運行是和n無關的,就算它再循環一萬年,我們也不管他,只是一個常數階的函數。

【2】當有若干個循環語句時,算法的時間復雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。

?x=1;? for(i=1;i<=n;i++)?for(j=1;j<=i;j++)for(k=1;k<=j;k++)x++;

該程序段中頻度最大的語句是(5),內循環的執行次數雖然與問題規模n沒有直接關系,但是卻與外層循環的變量取值有關,而最外層循環的次數直接與n有關,因此可以從內層循環向外層分析語句(5)的執行次數: 則該程序段的時間復雜度為

【3】算法的時間復雜度不僅僅依賴于問題的規模,還與輸入實例的初始狀態有關。

在數值A[0..n-1]中查找給定值K的算法大致如下:

i=n-1;???????????? while(i>=0&&(A[i]!=k))???????i--;???????? return?i;

此算法中的語句(3)的頻度不僅與問題規模n有關,還與輸入實例中A的各元素取值及K的取值有關: ①若A中沒有與K相等的元素,則語句(3)的頻度f(n)=n; ②若A的最后一個元素等于K,則語句(3)的頻度f(n)是常數0。

空間復雜度

一個程序的空間復雜度是指運行完一個程序所需內存的大小。利用程序的空間復雜度,可以對程序的運行所需要的內存多少有個預先估計。一個程序執行時除了需要存儲空間和存儲本身所使用的指令、常數、變量和輸入數據外,還需要一些對數據進行操作的工作單元和存儲一些為現實計算所需信息的輔助空間。程序執行時所需存儲空間包括以下兩部分。 

(1)固定部分。這部分空間的大小與輸入/輸出的數據的個數多少、數值無關。主要包括指令空間(即代碼空間)、數據空間(常量、簡單變量)等所占的空間。這部分屬于靜態空間。

(2)可變空間,這部分空間的主要包括動態分配的空間,以及遞歸棧所需的空間等。這部分的空間大小與算法有關。

一個算法所需的存儲空間用f(n)表示。S(n)=O(f(n))  其中n為問題的規模,S(n)表示空間復雜度。

8. 支付寶SDK使用

使用支付寶進行一個完整的支付功能,大致有以下步驟:向支付寶申請, 與支付寶簽約,獲得商戶ID(partner)和賬號ID(seller)和私鑰(privateKey)。下載支付寶SDK,生成訂單信息,簽名加密調用支付寶客戶端,由支付寶客戶端跟支付寶安全服務器打交道。支付完畢后,支付寶客戶端會自動跳回到原來的應用程序,在原來的應用程序中顯示支付結果給用戶看。

集成之后可能遇到的問題

1)集成SDK編譯時找不到 openssl/asn1.h 文件

解決方案:Build Settings --> Search Paths --> Header Search paths : $(SRCROOT)/支付寶集成/Classes/Alipay

2)鏈接時:找不到 SystemConfiguration.framework 這個庫

解決方案:

打開支付寶客戶端進行支付(用戶沒有安裝支付寶客戶端,直接在應用程序中添加一個WebView,通過網頁讓用戶進行支付)

//?注意:如果是通過網頁支付完成,那么會回調該block:callback [[AlipaySDK?defaultService]?payOrder:orderString?fromScheme:@"jingdong"?callback:^(NSDictionary?*resultDic)?{?}];

在AppDelegate.m

//?當通過別的應用程序,將該應用程序打開時,會調用該方法 -?(BOOL)application:(UIApplication?*)app?openURL:(NSURL?*)url?options:(NSDictionary?*)options{?//?當用戶通過支付寶客戶端進行支付時,會回調該block:standbyCallback? [[AlipaySDK?defaultService]?processOrderWithPaymentResult:url?standbyCallback:^(NSDictionary?*resultDic)?{?NSLog(@"result?=?%@",resultDic);?}];?return?YES;}

9. 遠程推送

當服務端遠程向APNS推送至一臺離線的設備時,蘋果服務器Qos組件會自動保留一份最新的通知,等設備上線后,Qos將把推送發送到目標設備上。

遠程推送的基本過程:

1.客戶端的app需要將用戶的UDID和app的bundleID發送給apns服務器,進行注冊,apns將加密后的device Token返回給app

2.app獲得device Token后,上傳到公司服務器

3.當需要推送通知時,公司服務器會將推送內容和device Token一起發給apns服務器

4.apns再將推送內容送到客戶端上

創建證書的流程:

1.打開鑰匙串,生成CertificateSigningRequest.certSigningRequest文件

2.將CertificateSigningRequest.certSigningRequest上傳進developer,導出.cer文件

3.利用CSR導出P12文件

4.需要準備下設備token值(無空格)

5.使用OpenSSL合成服務器所使用的推送證書

本地app代碼參考

1.注冊遠程通知

-?(BOOL)application:(UIApplication?*)application?didFinishLaunchingWithOptions:(NSDictionary?*)launchOptions//中注冊遠程通知 {[[UIApplication?sharedApplication]?registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert?|?UIRemoteNotificationTypeBadge?|?UIRemoteNotificationTypeSound)]; }

2,實現幾個代理方法:

//獲取deviceToken令牌?? -(void)application:(UIApplication?*)application?didRegisterForRemoteNotificationsWithDeviceToken:(NSData?*)deviceToken?? {??//獲取設備的deviceToken唯一編號??NSLog(@"deviceToken=%@",deviceToken);??NSString?*realDeviceToken=[NSString?stringWithFormat:@"%@",deviceToken];??//去除<>??realDeviceToken?=?[realDeviceToken?stringByReplacingOccurrencesOfString:@"<"?withString:@""];??realDeviceToken?=?[realDeviceToken?stringByReplacingOccurrencesOfString:@">"?withString:@""];??NSLog(@"realDeviceToken=%@",realDeviceToken);??[[NSUserDefaults?standardUserDefaults]?setValue:realDeviceToken?forKey:@"DeviceToken"];??//要發送給服務器 }??//獲取令牌出錯?? -(void)application:(UIApplication?*)application?didFailToRegisterForRemoteNotificationsWithError:(NSError?*)error?? {??//注冊遠程通知設備出錯??NSLog(@"RegisterForRemoteNotification?error=%@",error);?? }?? //在應用在前臺時受到消息調用?? -(void)application:(UIApplication?*)application?didReceiveRemoteNotification:(NSDictionary?*)userInfo?? {??//打印推送的消息??NSLog(@"%@",[[userInfo?objectForKey:@"aps"]?objectForKey:@"alert"]):?? }

配置后臺模式

一般我們是使用開發版本的Provisioning做推送測試,如果沒有問題,再使用發布版本證書的時候一般也應該是沒有問題的。為了以防萬一,我們可以在越獄的手機上安裝我們的使用發布版證書的ipa文件(最好使用debug版本,并打印出獲取到的deviceToken),安裝成功后在;XCode->Window->Organizer-找到對應的設備查看console找到打印的deviceToken。

在后臺的推送程序中使用發布版制作的證書并使用該deviceToken做推送服務.

使用開發和發布證書獲取到的deviceToken是不一樣的。

10. @protocol 和 category 中如何使用 @property

1)在protocol中使用property只會生成setter和getter方法聲明,我們使用屬性的目的,是希望遵守我協議的對象能實現該屬性

2)category 使用 @property 也是只會生成setter和getter方法的聲明,如果我們真的需要給category增加屬性的實現,需要借助于運行時的兩個函數:

①objc_setAssociatedObject ②objc_getAssociatedObject

總結

以上是生活随笔為你收集整理的那些著名或非著名的iOS面试题(中)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。