1、使用NSTimer,需要注意什么?
這里按我的理解就是,主要是涉及runloop了。 一是拖動scrollView的時(shí)候,runloop處于EventTracking模式,創(chuàng)建的計(jì)時(shí)器默認(rèn)是添加在defalut下,而runloop 有一個(gè)特點(diǎn)只會處理當(dāng)前mode下的輸入源事件和計(jì)時(shí)器事件, 所以當(dāng)scrollView滾動的時(shí)候,計(jì)時(shí)器的事件會導(dǎo)致無法觸發(fā),這種情況下,只需需將計(jì)時(shí)器添加到當(dāng)前runloop下的common mode下即可;二是,子線程的計(jì)時(shí)器事件,需要主動添加這句[[NSRunLoop currentRunLoop] run]才能觸發(fā), 子線程的運(yùn)行循環(huán)默認(rèn)是沒有開啟的
2、self.name = nil 和[_name release]的區(qū)別
前者使用property的點(diǎn)操作符,也就相當(dāng)于調(diào)用了name對應(yīng)的set method,和這句是一樣的:[self setName:nil];
而后者沒有通過property,直接訪問了成員變量,調(diào)用了它的release方法。
對于set method來說,用synthesize來讓系統(tǒng)幫我們生成的set方法和如下的類似:
- (void)setAbc:(id)newAbc
{
if(_abc != newAbc){
[_abc release];
_abc = [newAbc retain]; //是retain還是copy取決于你property聲明時(shí)的attributes
}
}
如果新值和成員相等,就不需要進(jìn)行重復(fù)的賦值了,不等的話,需要把新值賦給成員,同時(shí),成員_abc原來的內(nèi)容就不需要了,這里要先調(diào)用release進(jìn)行釋放。(這個(gè)具體的原因在那本講Objective-C的書中寫的很清楚,請查看)。
因此在這里,調(diào)用self.abc = nil;
就等于掉了[_abc release];? 和_abc = nil;
self.abc = nil;和[_abc release]; 都不一定釋放對象,因?yàn)樵搶ο筮€可能被別的引用,這里的操作的意圖就是:別的地方用沒用_abc我不知道,在這里的_abc我不用了。
在用retain或者copy的property attributes的時(shí)候,self.abc = nil;等于如下語句:
if(_abc!= nil)
{
[_abc release];
_abc = nil; //message sent to nil returns nil.
}
所以用起來更簡單一點(diǎn)。
3、@property中一些屬性關(guān)鍵字的作用, 默認(rèn)下分別是哪些關(guān)鍵字?
strong? ? ? ? ? ? ? 釋放舊對象將舊對象的值賦予輸入對象,再提高輸入對象的索引計(jì)數(shù)為1,此關(guān)鍵字經(jīng)常使用。
weak? ? ? ? ? ? ? ? 不增加引用計(jì)數(shù),不持有對象,因此也不能決定對象釋放? 對比assign 的一個(gè)好處是,當(dāng)對象消失時(shí)指針自動歸為nil
assign? ? ? ? ? ? ? 適用于基礎(chǔ)數(shù)據(jù)類型(NSInteger CGFloat...)不增加引用計(jì)數(shù)
copy? ? ? ? ? ? ? ? 建立一個(gè)索引計(jì)數(shù)為1 的對象然后釋放舊對象 此屬性只對那些實(shí)行了NSCopying協(xié)議的對象類型有效(NSString , Block)
atomic? ? ? ? ? ? 和 nonatomic用來決定編譯器生成的getter和setter是否為原子操作,atomic 設(shè)置成員變量的@property屬性時(shí)? 默認(rèn)為是atomic 提供線程安全。
nonatomic? ? ? 非原子性訪問對于屬性賦值的時(shí)候不加鎖,多線程并發(fā)訪問會提高性能,如果不加此屬性則默認(rèn)是兩個(gè)訪問方法都為原子型事務(wù)訪問。
readonly? ? ? ? ? 此標(biāo)記說明屬性是只讀的
readwrite? ? ? ? ? 此標(biāo)記說明屬性會被當(dāng)成讀寫的? 這也是默認(rèn)的屬性
unsafe_unretained? ? ? ? ? 跟weak類似,聲明一個(gè)弱引用,但是當(dāng)引用計(jì)數(shù)為0時(shí),變量不會自動設(shè)置為nil(ios5加入的 我基本沒用過)
3.1、屬性關(guān)鍵字對比
copy : strong? ? ??
1.copy建立一個(gè)同樣的對象 比如一個(gè)NSString 地址為0x1212 內(nèi)容 @“121”? copy到另一個(gè)NSString上? 地址改變 而內(nèi)容不變 新對象retain +1 就對象不變? 也就是說copy時(shí)內(nèi)容拷貝? 而 strong不是他只是單純的生命一個(gè)變量 retain為1? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?2.strong的set方法時(shí)淺拷貝? copy的set為深拷貝
assign : weak? ??
?在MRC環(huán)境下使用使用assign實(shí)現(xiàn)基本類型.? ? ? ? ? 在ARC環(huán)境下,weak相當(dāng)于assign? 個(gè)人感覺weak比assign要強(qiáng)大的地方在 weak可以避免循環(huán)引用 , 同時(shí)當(dāng)對象不存在時(shí)候可以將其置為nil
4、sql語句常用的增刪改查
5、KVO的內(nèi)部實(shí)現(xiàn)
KVO是基于runtime機(jī)制實(shí)現(xiàn)的
當(dāng)某個(gè)類的屬性對象第一次被觀察時(shí),系統(tǒng)就會在運(yùn)行期動態(tài)地創(chuàng)建該類的一個(gè)派生類,在這個(gè)派生類中重寫基類中任何被觀察屬性的setter 方法。派生類在被重寫的setter方法內(nèi)實(shí)現(xiàn)真正的通知機(jī)制
如果原類為Person,那么生成的派生類名為NSKVONotifying_Person
每個(gè)類對象中都有一個(gè)isa指針指向當(dāng)前類,當(dāng)一個(gè)類對象的第一次被觀察,那么系統(tǒng)會偷偷將isa指針指向動態(tài)生成的派生類,從而在給被監(jiān)控屬性賦值時(shí)執(zhí)行的是派生類的setter方法
鍵值觀察通知依賴于NSObject 的兩個(gè)方法: willChangeValueForKey: 和 didChangevlueForKey:;在一個(gè)被觀察屬性發(fā)生改變之前, willChangeValueForKey:一定會被調(diào)用,這就 會記錄舊的值。而當(dāng)改變發(fā)生后,didChangeValueForKey:會被調(diào)用,繼而 observeValueForKey:ofObject:change:context: 也會被調(diào)用。
補(bǔ)充:KVO的這套實(shí)現(xiàn)機(jī)制中蘋果還偷偷重寫了class方法,讓我們誤認(rèn)為還是使用的當(dāng)前類,從而達(dá)到隱藏生成的派生類
KVC是OC特有的,本質(zhì)是在運(yùn)行時(shí)動態(tài)的給對象發(fā)送setValue:forKey 消息,設(shè)置數(shù)值 -調(diào)用super.init 保證對象已經(jīng)被創(chuàng)建完成 .當(dāng)給對象發(fā)送setValue:forKey 消息時(shí)要判斷對象是否存在key所對應(yīng)的屬性,直接賦值 如果沒有就調(diào)用undefinedKey(默認(rèn)崩潰,需要重寫)? ? setValue:forKey的調(diào)用順序首先會尋找set方法,如果沒有就去找__isis順序?qū)ふ?如何還沒找到就調(diào)用undefinedKey(默認(rèn)崩潰,需要重寫). ValueForKey的調(diào)用順序? 按照get,is順序?qū)ふ?如果沒有找到按照__isis順序?qū)ふ?如何還沒找到就調(diào)用undefinedKey(默認(rèn)崩潰,需要重寫).
6、category 和 extension 的區(qū)別
分類有名字,類擴(kuò)展沒有分類名字,是一種特殊的分類
分類只能擴(kuò)展方法(屬性僅僅是聲明,并沒真正實(shí)現(xiàn)),類擴(kuò)展可以擴(kuò)展屬性、成員變量和方法
7、define 和 const常量有什么區(qū)別?
define在預(yù)處理階段進(jìn)行替換,const常量在編譯階段使用
宏不做類型檢查,僅僅進(jìn)行替換,const常量有數(shù)據(jù)類型,會執(zhí)行類型檢查
define不能調(diào)試,const常量可以調(diào)試
define定義的常量在替換后運(yùn)行過程中會不斷地占用內(nèi)存,而const定義的常量存儲在數(shù)據(jù)段只有一份copy,效率更高
define可以定義一些簡單的函數(shù),const不可以
8、block和weak修飾符的區(qū)別?
__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,也可以修飾基本數(shù)據(jù)類型
__weak只能在ARC模式下使用,只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型
block修飾的對象可以在block中被重新賦值,weak修飾的對象不可以
9、static關(guān)鍵字的作用
函數(shù)(方法)體內(nèi) static 變量的作用范圍為該函數(shù)體,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值;
在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問;
在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個(gè)函數(shù)的使用范圍被限制在聲明 它的模塊內(nèi);
在類中的 static 成員變量屬于整個(gè)類所擁有,對類的所有對象只有一份拷貝;
在類中的 static 成員函數(shù)屬于整個(gè)類所擁有,這個(gè)函數(shù)不接收 this 指針,因而只能訪問類的static 成員變量
10、堆和棧的區(qū)別
從管理方式來講
對于棧來講,是由編譯器自動管理,無需我們手工控制;
對于堆來說,釋放工作由程序員控制,容易產(chǎn)生內(nèi)存泄露(memory leak)
從申請大小大小方面講
??臻g比較小
堆控件比較大
從數(shù)據(jù)存儲方面來講
??臻g中一般存儲基本類型,對象的地址
堆空間一般存放對象本身,block的copy等
11、進(jìn)程和線程的區(qū)別和聯(lián)系
進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合上的一次運(yùn)行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位. 線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.
一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程;同一個(gè)進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行.
12、談?wù)刬nstancetype和id的異同
1、相同點(diǎn)
都可以作為方法的返回類型
2、不同點(diǎn)
①instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象;②instancetype只能作為返回值,不能像id那樣作為參數(shù)
13、isKindOfClass和isMemberOfClass的區(qū)別
isKindOfClass來確定一個(gè)對象是否是一個(gè)類的成員,或者是派生自該類的成員
14、Core Data是數(shù)據(jù)庫么?有哪些重要的類?
Core Data確實(shí)不是一個(gè)數(shù)據(jù)庫,只是把表和OC對象進(jìn)行的映射,當(dāng)時(shí)并不是進(jìn)進(jìn)映射那么簡單,底層還是用的Sqlite3進(jìn)行存儲的,所以Core Data不是數(shù)據(jù)庫。
有以下6個(gè)重要的類:
(1)NSManagedObjectContext(被管理的數(shù)據(jù)上下文)
操作實(shí)際內(nèi)容(操作持久層)
作用:插入數(shù)據(jù),查詢數(shù)據(jù),刪除數(shù)據(jù)
(2)NSManagedObjectModel(被管理的數(shù)據(jù)模型)
數(shù)據(jù)庫所有表格或數(shù)據(jù)結(jié)構(gòu),包含各實(shí)體的定義信息
作用:添加實(shí)體的屬性,建立屬性之間的關(guān)系
操作方法:視圖編輯器,或代碼
(3)NSPersistentStoreCoordinator(持久化存儲助理)
相當(dāng)于數(shù)據(jù)庫的連接器
作用:設(shè)置數(shù)據(jù)存儲的名字,位置,存儲方式,和存儲時(shí)機(jī)
(4)NSManagedObject(被管理的數(shù)據(jù)記錄)
相當(dāng)于數(shù)據(jù)庫中的表格記錄
(5)NSFetchRequest(獲取數(shù)據(jù)的請求)
相當(dāng)于查詢語句
(6)NSEntityDescription(實(shí)體結(jié)構(gòu))
相當(dāng)于表格結(jié)構(gòu)
15、算法題
二分查找 θ(logn)
遞歸方法
int binarySearch1(int a[] , int low , int high , int findNum)
{
int mid = ( low + high ) / 2;
if (low > high)
return -1;
else
{
if (a[mid] > findNum)
return binarySearch1(a, low, mid - 1, findNum);
else if (a[mid] < findNum)
return binarySearch1(a, mid + 1, high, findNum);
else
return mid;
}
}
非遞歸方法
int binarySearch2(int a[] , int low , int high , int findNum)
{
while (low <= high)
{
int mid = ( low + high) / 2;? //此處一定要放在while里面
if (a[mid] < findNum)
low = mid + 1;
else if (a[mid] > findNum)
high = mid - 1;
else
return mid;
}
return? -1;
}
冒泡排序? θ(n^2)
void bubble_sort(int a[], int n)
{
int i, j, temp;
for (j = 0; j < n - 1; j++)
for (i = 0; i < n - 1 - j; i++) //外層循環(huán)每循環(huán)一次就能確定出一個(gè)泡泡(最大或者最?。?,所以內(nèi)層循環(huán)不用再計(jì)算已經(jīng)排好的部分
{
if(a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
}
}
}
快速排序? 調(diào)用方法? quickSort(a,0,n);? θ(nlogn)
void quickSort (int a[] , int low , int high)
{
if (high < low + 2)
return;
int start = low;
int end = high;
int temp;
while (start < end)
{
while ( ++start < high && a[start] <= a[low]);//找到第一個(gè)比a[low]數(shù)值大的位子start
while ( --end? > low? && a[end]? >= a[low]);//找到第一個(gè)比a[low]數(shù)值小的位子end
//進(jìn)行到此,a[end] < a[low] < a[start],但是物理位置上還是low < start < end,因此接下來交換a[start]和a[end],于是[low,start]這個(gè)區(qū)間里面全部比a[low]小的,[end,hight]這個(gè)區(qū)間里面全部都是比a[low]大的
if (start < end)
{
temp = a[start];
a[start]=a[end];
a[end]=temp;
}
//在GCC編譯器下,該寫法無法達(dá)到交換的目的,a[start] ^= a[end] ^= a[start] ^= a[end];編譯器的問題
}
//進(jìn)行到此,[low,end]區(qū)間里面的數(shù)都比a[low]小的,[end,higt]區(qū)間里面都是比a[low]大的,把a(bǔ)[low]放到中間即可
//在GCC編譯器下,該寫法無法達(dá)到交換的目的,a[low] ^= a[end] ^= a[low] ^= a[end];編譯器的問題
temp = a[low];
a[low]=a[end];
a[end]=temp;
//現(xiàn)在就分成了3段了,由最初的a[low]樞紐分開的
quickSort(a, low, end);
quickSort(a, start, high);
}