那些著名或非著名的iOS面试题(中)
接上篇:那些著名或非著名的iOS面試題(上),本文繼續(xù)介紹一些著名或非著名的iOS面試題。
1. 反轉(zhuǎn)二叉樹,不用遞歸
/***?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實(shí)現(xiàn):
/**?*?翻轉(zhuǎn)二叉樹(又叫:二叉樹的鏡像)?**?@param?rootNode?根節(jié)點(diǎn)**?@return?翻轉(zhuǎn)后的樹根節(jié)點(diǎn)(其實(shí)就是原二叉樹的根節(jié)點(diǎn))?*/+?(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];?//數(shù)組當(dāng)成隊(duì)列[queueArray?addObject:rootNode];?//壓入根節(jié)點(diǎn)while?(queueArray.count?>?0)?{BinaryTreeNode?*node?=?[queueArray?firstObject];[queueArray?removeObjectAtIndex:0];?//彈出最前面的節(jié)點(diǎn),仿照隊(duì)列先進(jìn)先出原則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. 寫一個(gè)單例模式
+?(AccountManager?*)sharedManager {static?AccountManager?*sharedAccountManagerInstance?=?nil;static?dispatch_once_t?predicate;dispatch_once(&predicate,?^{sharedAccountManagerInstance?=?[[self?alloc]?init];?});return?sharedAccountManagerInstance; }3. iOS應(yīng)用生命周期
應(yīng)用程序的狀態(tài):
-
Not running未運(yùn)行:程序沒啟動(dòng)。
-
Inactive未激活:程序在前臺(tái)運(yùn)行,不過沒有接收到事件。在沒有事件處理情況下程序通常停留在這個(gè)狀態(tài)。
-
Active激活:程序在前臺(tái)運(yùn)行而且接收到了事件。這也是前臺(tái)的一個(gè)正常的模式。
-
Backgroud后臺(tái):程序在后臺(tái)而且能執(zhí)行代碼,大多數(shù)程序進(jìn)入這個(gè)狀態(tài)后會(huì)在在這個(gè)狀態(tài)上停留一會(huì)。時(shí)間到之后會(huì)進(jìn)入掛起狀態(tài)(Suspended)。有的程序經(jīng)過特殊的請求后可以長期處于Backgroud狀態(tài)。
-
Suspended掛起:程序在后臺(tái)不能執(zhí)行代碼。系統(tǒng)會(huì)自動(dòng)把程序變成這個(gè)狀態(tài)而且不會(huì)發(fā)出通知。當(dāng)掛起時(shí),程序還是停留在內(nèi)存中的,當(dāng)系統(tǒng)內(nèi)存低時(shí),系統(tǒng)就把掛起的程序清除掉,為前臺(tái)程序提供更多的內(nèi)存。
iOS的入口在main.m文件:
int?main(int?argc,?char?*argv[]) {@autoreleasepool?{return?UIApplicationMain(argc,?argv,?nil,?NSStringFromClass([AppDelegate?class]));} }main函數(shù)的兩個(gè)參數(shù),iOS中沒有用到,包括這兩個(gè)參數(shù)是為了與標(biāo)準(zhǔn)ANSI C保持一致。 UIApplicationMain函數(shù),前兩個(gè)和main函數(shù)一樣,重點(diǎn)是后兩個(gè)。
后兩個(gè)參數(shù)分別表示程序的主要類(principal class)和代理類(delegate class)。如果主要類(principal class)為nil,將從Info.plist中獲取,如果Info.plist中不存在對應(yīng)的key,則默認(rèn)為UIApplication;如果代理類(delegate class)將在新建工程時(shí)創(chuàng)建。
根據(jù)UIApplicationMain函數(shù),程序?qū)⑦M(jìn)入AppDelegate.m,這個(gè)文件是xcode新建工程時(shí)自動(dòng)生成的。下面看一下AppDelegate.m文件,這個(gè)關(guān)乎著應(yīng)用程序的生命周期。
1、application didFinishLaunchingWithOptions:當(dāng)應(yīng)用程序啟動(dòng)時(shí)執(zhí)行,應(yīng)用程序啟動(dòng)入口,只在應(yīng)用程序啟動(dòng)時(shí)執(zhí)行一次。若用戶直接啟動(dòng),lauchOptions內(nèi)無數(shù)據(jù),若通過其他方式啟動(dòng)應(yīng)用,lauchOptions包含對應(yīng)方式的內(nèi)容。
2、applicationWillResignActive:在應(yīng)用程序?qū)⒁苫顒?dòng)狀態(tài)切換到非活動(dòng)狀態(tài)時(shí)候,要執(zhí)行的委托調(diào)用,如 按下 home 按鈕,返回主屏幕,或全屏之間切換應(yīng)用程序等。
3、applicationDidEnterBackground:在應(yīng)用程序已進(jìn)入后臺(tái)程序時(shí),要執(zhí)行的委托調(diào)用。
4、applicationWillEnterForeground:在應(yīng)用程序?qū)⒁M(jìn)入前臺(tái)時(shí)(被激活),要執(zhí)行的委托調(diào)用,剛好與applicationWillResignActive 方法相對應(yīng)。
5、applicationDidBecomeActive:在應(yīng)用程序已被激活后,要執(zhí)行的委托調(diào)用,剛好與applicationDidEnterBackground 方法相對應(yīng)。
6、applicationWillTerminate:在應(yīng)用程序要完全推出的時(shí)候,要執(zhí)行的委托調(diào)用,這個(gè)需要要設(shè)置UIApplicationExitsOnSuspend的鍵值。
初次啟動(dòng):
iOS_didFinishLaunchingWithOptions iOS_applicationDidBecomeActive按下home鍵:
iOS_applicationWillResignActive iOS_applicationDidEnterBackground點(diǎn)擊程序圖標(biāo)進(jìn)入:
iOS_applicationWillEnterForeground iOS_applicationDidBecomeActive當(dāng)應(yīng)用程序進(jìn)入后臺(tái)時(shí),應(yīng)該保存用戶數(shù)據(jù)或狀態(tài)信息,所有沒寫到磁盤的文件或信息,在進(jìn)入后臺(tái)時(shí),最后都寫到磁盤去,因?yàn)槌绦蚩赡茉诤笈_(tái)被殺死。釋放盡可能釋放的內(nèi)存。
-?(void)applicationDidEnterBackground:(UIApplication?*)application方法有大概5秒的時(shí)間讓你完成這些任務(wù)。如果超過時(shí)間還有未完成的任務(wù),你的程序就會(huì)被終止而且從內(nèi)存中清除。
如果還需要長時(shí)間的運(yùn)行任務(wù),可以在該方法中調(diào)用:
[application?beginBackgroundTaskWithExpirationHandler:^{?NSLog(@"begin?Background?Task?With?Expiration?Handler");? }];程序終止
程序只要符合以下情況之一,只要進(jìn)入后臺(tái)或掛起狀態(tài)就會(huì)終止:
①iOS 4.0以前的系統(tǒng)
②app是基于iOS 4.0之前系統(tǒng)開發(fā)的。
③設(shè)備不支持多任務(wù)
④在Info.plist文件中,程序包含了 UIApplicationExitsOnSuspend 鍵。
系統(tǒng)常常是為其他app啟動(dòng)時(shí)由于內(nèi)存不足而回收內(nèi)存最后需要終止應(yīng)用程序,但有時(shí)也會(huì)是由于app很長時(shí)間才響應(yīng)而終止。如果app當(dāng)時(shí)運(yùn)行在后臺(tái)并且沒有暫停,系統(tǒng)會(huì)在應(yīng)用程序終止之前調(diào)用app的代理的方法 - (void)applicationWillTerminate:(UIApplication *)application,這樣可以讓你可以做一些清理工作。你可以保存一些數(shù)據(jù)或app的狀態(tài)。這個(gè)方法也有5秒鐘的限制。超時(shí)后方法會(huì)返回程序從內(nèi)存中清除。
注意:用戶可以手工關(guān)閉應(yīng)用程序。
4. 一工人給老板打7天工要求一塊金條 這金條只能切2次 工人每天要1/7金條 怎么分?
這道題解決的主要難點(diǎn)在于:不是給出去的就收不回來了,可以用交換的方法?! ?/p>
把金條分成三段(就是分兩次,或者切兩刀),分別是整根金條的1/7、2/7、 4/7?! ?/p>
第一天:給1/7的, 第二天:給2/7的,收回1/7的; 第三天,給1/7的; 第四天:給4/7的,收回1/7和2/7的 ;第五天:給1/7的 ;第六天:給2/7的,收回1/7的;第七天發(fā)1/7。
5. iOS中socket使用
Socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個(gè)調(diào)用接口(API),通過Socket,我們才能使用TCP/IP協(xié)議。
-
http協(xié)議:對應(yīng)于應(yīng)用層
-
tcp協(xié)議:對應(yīng)于傳輸層
-
ip協(xié)議:對應(yīng)于網(wǎng)絡(luò)層
三者本質(zhì)上沒有可比性。 何況HTTP協(xié)議是基于TCP連接的。
TCP/IP是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸;而HTTP是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。
我 們在傳輸數(shù)據(jù)時(shí),可以只使用傳輸層(TCP/IP),但是那樣的話,由于沒有應(yīng)用層,便無法識(shí)別數(shù)據(jù)內(nèi)容,如果想要使傳輸?shù)臄?shù)據(jù)有意義,則必須使用應(yīng)用層 協(xié)議,應(yīng)用層協(xié)議很多,有HTTP、FTP、TELNET等等,也可以自己定義應(yīng)用層協(xié)議。WEB使用HTTP作傳輸層協(xié)議,以封裝HTTP文本信息,然 后使用TCP/IP做傳輸層協(xié)議將它發(fā)送到網(wǎng)絡(luò)上。
SOCKET原理
1、套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口。
應(yīng) 用層通過傳輸層進(jìn)行數(shù)據(jù)通信時(shí),TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問題。多個(gè)TCP連接或多個(gè)應(yīng)用程序進(jìn)程可能需要通過同一個(gè) TCP協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口。應(yīng) 用層可以和傳輸層通過Socket接口,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
2、建立socket連接
建立Socket連接至少需要一對套接字,其中一個(gè)運(yùn)行于客戶端,稱為ClientSocket,另一個(gè)運(yùn)行于服務(wù)器端,稱為ServerSocket。
套接字之間的連接過程分為三個(gè)步驟:服務(wù)器監(jiān)聽,客戶端請求,連接確認(rèn)。
服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請求。
客戶端請求:指客戶端的套接字提出連接請求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號(hào),然后就向服務(wù)器端套接字提出連接請求。
連 接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時(shí),就響應(yīng)客戶端套接字的請求,建立一個(gè)新的線程,把服務(wù)器端套接字的描述發(fā)給客戶 端,一旦客戶端確認(rèn)了此描述,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求。
3、SOCKET連接與TCP連接
創(chuàng)建Socket連接時(shí),可以指定使用的傳輸層協(xié)議,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP),當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí),該Socket連接就是一個(gè)TCP連接。
4、Socket連接與HTTP連接
由 于通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發(fā)送數(shù)據(jù)內(nèi)容,直到雙方連接斷開。但在實(shí)際網(wǎng)絡(luò)應(yīng)用 中,客戶端到服務(wù)器之間的通信往往需要穿越多個(gè)中間節(jié)點(diǎn),例如路由器、網(wǎng)關(guān)、防火墻等,大部分防火墻默認(rèn)會(huì)關(guān)閉長時(shí)間處于非活躍狀態(tài)的連接而導(dǎo)致 Socket 連接斷連,因此需要通過輪詢告訴網(wǎng)絡(luò),該連接處于活躍狀態(tài)。
而HTTP連接使用的是“請求—響應(yīng)”的方式,不僅在請求時(shí)需要先建立連接,而且需要客戶端向服務(wù)器發(fā)出請求后,服務(wù)器端才能回復(fù)數(shù)據(jù)。
很 多情況下,需要服務(wù)器端主動(dòng)向客戶端推送數(shù)據(jù),保持客戶端與服務(wù)器數(shù)據(jù)的實(shí)時(shí)與同步。此時(shí)若雙方建立的是Socket連接,服務(wù)器就可以直接將數(shù)據(jù)傳送給 客戶端;若雙方建立的是HTTP連接,則服務(wù)器需要等到客戶端發(fā)送一次請求后才能將數(shù)據(jù)傳回給客戶端,因此,客戶端定時(shí)向服務(wù)器端發(fā)送連接請求,不僅可以 保持在線,同時(shí)也是在“詢問”服務(wù)器是否有新的數(shù)據(jù),如果有就將數(shù)據(jù)傳給客戶端。
6. 網(wǎng)絡(luò)請求中post和get的區(qū)別
GET是用于獲取數(shù)據(jù)的,POST一般用于將數(shù)據(jù)發(fā)給服務(wù)器之用。
普遍答案
1.GET使用URL或Cookie傳參。而POST將數(shù)據(jù)放在BODY中。
2.GET的URL會(huì)有長度上的限制,則POST的數(shù)據(jù)則可以非常大。
3.POST比GET安全,因?yàn)閿?shù)據(jù)在地址欄上不可見。
不過也有文章說其實(shí)上面的是錯(cuò)誤的,具體參考這篇文章。
7. 時(shí)間復(fù)雜度和空間復(fù)雜度
由于打不出數(shù)字符號(hào),只能貼圖了。
時(shí)間復(fù)雜度
求時(shí)間復(fù)雜度
【1】如果算法的執(zhí)行時(shí)間不隨著問題規(guī)模n的增加而增長,即使算法中有上千條語句,其執(zhí)行時(shí)間也不過是一個(gè)較大的常數(shù)。此類算法的時(shí)間復(fù)雜度是O(1)。
x=91;?y=100;while(y>0)?if(x>100)?{x=x-10;y--;}?else?x++;解答:?T(n)=O(1)這段程序的運(yùn)行是和n無關(guān)的,就算它再循環(huán)一萬年,我們也不管他,只是一個(gè)常數(shù)階的函數(shù)。
【2】當(dāng)有若干個(gè)循環(huán)語句時(shí),算法的時(shí)間復(fù)雜度是由嵌套層數(shù)最多的循環(huán)語句中最內(nèi)層語句的頻度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èi)循環(huán)的執(zhí)行次數(shù)雖然與問題規(guī)模n沒有直接關(guān)系,但是卻與外層循環(huán)的變量取值有關(guān),而最外層循環(huán)的次數(shù)直接與n有關(guān),因此可以從內(nèi)層循環(huán)向外層分析語句(5)的執(zhí)行次數(shù): 則該程序段的時(shí)間復(fù)雜度為
【3】算法的時(shí)間復(fù)雜度不僅僅依賴于問題的規(guī)模,還與輸入實(shí)例的初始狀態(tài)有關(guān)。
在數(shù)值A(chǔ)[0..n-1]中查找給定值K的算法大致如下:
i=n-1;???????????? while(i>=0&&(A[i]!=k))???????i--;???????? return?i;此算法中的語句(3)的頻度不僅與問題規(guī)模n有關(guān),還與輸入實(shí)例中A的各元素取值及K的取值有關(guān): ①若A中沒有與K相等的元素,則語句(3)的頻度f(n)=n; ②若A的最后一個(gè)元素等于K,則語句(3)的頻度f(n)是常數(shù)0。
空間復(fù)雜度
一個(gè)程序的空間復(fù)雜度是指運(yùn)行完一個(gè)程序所需內(nèi)存的大小。利用程序的空間復(fù)雜度,可以對程序的運(yùn)行所需要的內(nèi)存多少有個(gè)預(yù)先估計(jì)。一個(gè)程序執(zhí)行時(shí)除了需要存儲(chǔ)空間和存儲(chǔ)本身所使用的指令、常數(shù)、變量和輸入數(shù)據(jù)外,還需要一些對數(shù)據(jù)進(jìn)行操作的工作單元和存儲(chǔ)一些為現(xiàn)實(shí)計(jì)算所需信息的輔助空間。程序執(zhí)行時(shí)所需存儲(chǔ)空間包括以下兩部分?!?/p>
(1)固定部分。這部分空間的大小與輸入/輸出的數(shù)據(jù)的個(gè)數(shù)多少、數(shù)值無關(guān)。主要包括指令空間(即代碼空間)、數(shù)據(jù)空間(常量、簡單變量)等所占的空間。這部分屬于靜態(tài)空間。
(2)可變空間,這部分空間的主要包括動(dòng)態(tài)分配的空間,以及遞歸棧所需的空間等。這部分的空間大小與算法有關(guān)。
一個(gè)算法所需的存儲(chǔ)空間用f(n)表示。S(n)=O(f(n)) 其中n為問題的規(guī)模,S(n)表示空間復(fù)雜度。
8. 支付寶SDK使用
使用支付寶進(jìn)行一個(gè)完整的支付功能,大致有以下步驟:向支付寶申請, 與支付寶簽約,獲得商戶ID(partner)和賬號(hào)ID(seller)和私鑰(privateKey)。下載支付寶SDK,生成訂單信息,簽名加密調(diào)用支付寶客戶端,由支付寶客戶端跟支付寶安全服務(wù)器打交道。支付完畢后,支付寶客戶端會(huì)自動(dòng)跳回到原來的應(yīng)用程序,在原來的應(yīng)用程序中顯示支付結(jié)果給用戶看。
集成之后可能遇到的問題
1)集成SDK編譯時(shí)找不到 openssl/asn1.h 文件
解決方案:Build Settings --> Search Paths --> Header Search paths : $(SRCROOT)/支付寶集成/Classes/Alipay
2)鏈接時(shí):找不到 SystemConfiguration.framework 這個(gè)庫
解決方案:
打開支付寶客戶端進(jìn)行支付(用戶沒有安裝支付寶客戶端,直接在應(yīng)用程序中添加一個(gè)WebView,通過網(wǎng)頁讓用戶進(jìn)行支付)
//?注意:如果是通過網(wǎng)頁支付完成,那么會(huì)回調(diào)該block:callback [[AlipaySDK?defaultService]?payOrder:orderString?fromScheme:@"jingdong"?callback:^(NSDictionary?*resultDic)?{?}];在AppDelegate.m
//?當(dāng)通過別的應(yīng)用程序,將該應(yīng)用程序打開時(shí),會(huì)調(diào)用該方法 -?(BOOL)application:(UIApplication?*)app?openURL:(NSURL?*)url?options:(NSDictionary?*)options{?//?當(dāng)用戶通過支付寶客戶端進(jìn)行支付時(shí),會(huì)回調(diào)該block:standbyCallback? [[AlipaySDK?defaultService]?processOrderWithPaymentResult:url?standbyCallback:^(NSDictionary?*resultDic)?{?NSLog(@"result?=?%@",resultDic);?}];?return?YES;}9. 遠(yuǎn)程推送
當(dāng)服務(wù)端遠(yuǎn)程向APNS推送至一臺(tái)離線的設(shè)備時(shí),蘋果服務(wù)器Qos組件會(huì)自動(dòng)保留一份最新的通知,等設(shè)備上線后,Qos將把推送發(fā)送到目標(biāo)設(shè)備上。
遠(yuǎn)程推送的基本過程:
1.客戶端的app需要將用戶的UDID和app的bundleID發(fā)送給apns服務(wù)器,進(jìn)行注冊,apns將加密后的device Token返回給app
2.app獲得device Token后,上傳到公司服務(wù)器
3.當(dāng)需要推送通知時(shí),公司服務(wù)器會(huì)將推送內(nèi)容和device Token一起發(fā)給apns服務(wù)器
4.apns再將推送內(nèi)容送到客戶端上
創(chuàng)建證書的流程:
1.打開鑰匙串,生成CertificateSigningRequest.certSigningRequest文件
2.將CertificateSigningRequest.certSigningRequest上傳進(jìn)developer,導(dǎo)出.cer文件
3.利用CSR導(dǎo)出P12文件
4.需要準(zhǔn)備下設(shè)備token值(無空格)
5.使用OpenSSL合成服務(wù)器所使用的推送證書
本地app代碼參考
1.注冊遠(yuǎn)程通知
-?(BOOL)application:(UIApplication?*)application?didFinishLaunchingWithOptions:(NSDictionary?*)launchOptions//中注冊遠(yuǎn)程通知 {[[UIApplication?sharedApplication]?registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert?|?UIRemoteNotificationTypeBadge?|?UIRemoteNotificationTypeSound)]; }2,實(shí)現(xiàn)幾個(gè)代理方法:
//獲取deviceToken令牌?? -(void)application:(UIApplication?*)application?didRegisterForRemoteNotificationsWithDeviceToken:(NSData?*)deviceToken?? {??//獲取設(shè)備的deviceToken唯一編號(hào)??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"];??//要發(fā)送給服務(wù)器 }??//獲取令牌出錯(cuò)?? -(void)application:(UIApplication?*)application?didFailToRegisterForRemoteNotificationsWithError:(NSError?*)error?? {??//注冊遠(yuǎn)程通知設(shè)備出錯(cuò)??NSLog(@"RegisterForRemoteNotification?error=%@",error);?? }?? //在應(yīng)用在前臺(tái)時(shí)受到消息調(diào)用?? -(void)application:(UIApplication?*)application?didReceiveRemoteNotification:(NSDictionary?*)userInfo?? {??//打印推送的消息??NSLog(@"%@",[[userInfo?objectForKey:@"aps"]?objectForKey:@"alert"]):?? }配置后臺(tái)模式
一般我們是使用開發(fā)版本的Provisioning做推送測試,如果沒有問題,再使用發(fā)布版本證書的時(shí)候一般也應(yīng)該是沒有問題的。為了以防萬一,我們可以在越獄的手機(jī)上安裝我們的使用發(fā)布版證書的ipa文件(最好使用debug版本,并打印出獲取到的deviceToken),安裝成功后在;XCode->Window->Organizer-找到對應(yīng)的設(shè)備查看console找到打印的deviceToken。
在后臺(tái)的推送程序中使用發(fā)布版制作的證書并使用該deviceToken做推送服務(wù).
使用開發(fā)和發(fā)布證書獲取到的deviceToken是不一樣的。
10. @protocol 和 category 中如何使用 @property
1)在protocol中使用property只會(huì)生成setter和getter方法聲明,我們使用屬性的目的,是希望遵守我協(xié)議的對象能實(shí)現(xiàn)該屬性
2)category 使用 @property 也是只會(huì)生成setter和getter方法的聲明,如果我們真的需要給category增加屬性的實(shí)現(xiàn),需要借助于運(yùn)行時(shí)的兩個(gè)函數(shù):
①objc_setAssociatedObject ②objc_getAssociatedObject總結(jié)
以上是生活随笔為你收集整理的那些著名或非著名的iOS面试题(中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小学英语教学c语言,小学英语老师常用的课
- 下一篇: 收藏的JAVA面试题大全