關鍵詞/關鍵類
1.#import跟#include有什么區別,@class呢,#import<>跟#import<>有什么區別?
#include c語言中引入一個頭文件,但是可能出現交叉編譯
#import在OC中引入自己創建的頭文件#import””或者系統框架#import<>。
#import不會出現交叉編譯,@class對一個類進行聲明,告訴編譯器有這個類,但是類的定義什么的都不知道
2描述一下KVO和KVC?
Key-Value Observing (簡寫為KVO):當指定的對象的屬性被修改了,允許對象接受到通知的機制。每次指定的被觀察對象的屬性被修改的時候,KVO都會自動的去通知相應的觀察者。
KVC是KeyValue Coding的簡稱,它是一種可以直接通過字符串的名字(key)來訪問類屬性的機制。而不是通過調用Setter、Getter方法訪問。
3.類目和繼承地區別
1.類別是對方法的擴展,不能添加成員變量。繼承可以在原來父類的成員變量的基礎上,添加新的成員變量
2.類別只能添加新的方法,不能修改和刪除原來的方法。繼承可以增加、修改和刪除方法。
3.類別不提倡對原有的方法進行重載。繼承可以通過使用super對原來方法進行重載。
4.類別可以被繼承,如果一個父類中定義了類別,那么其子類中也會繼承此類別。
5.什么是懶加載?在使用懶加載時的注意事項是什么?
答:所謂的懶加載指的是延遲創建對象,只有當需要的時候才創建對象。在真正開發的過程中其實懶加載就是重寫getter方法。在getter方法的內部,實現對象的創建,如果對象為nil才創建,如果不為nil,直接返回對象。在真正使用懶加載時需要注意的是當第一次使用對象時,需要調用self.因為只有這樣才能調用對應的getter方法,對象才會被創建。
6.簡述你對UIView、UIWindow、CALayer的理解。
答:CALayer是圖層類,本身可以顯示的,但是不能響應事件。
UIView是iOS系統中界面元素的基礎,所有的界面元素都繼承自它。事件的處理由它來執行,但是顯示其實是由其對應的layer層來操作的,UIView內嵌了一個layer,layer顯示內容,UIView本身增加了事件處理的功能。
UIWindow繼承自UIView,主要的作用是作為窗口呈現其他的視圖。而且一個應用程序一般情況下只有一個窗口。
7. id聲明的對象有什么特性?
答:id是任意對象類型的,不能表示基本類型。id類型是通用指針類型,因為通過指針,也就是內存地址來引用對象,所以可以將任意對象賦值給id類型的對象。返回id類型值的方法是返回指向內存中某對象的指針。然后可以將該值賦給任何對象變量(強制類型轉換即可)。因為無論在哪里,對象總是攜帶它的isa成員。所以即使將它存儲在id類型的通用對象變量中,也總是可以確定它的真實類型,id是多態的一種體現
7.@synthesize和@dynamic有什么區別?
(1)@property有兩個對應的詞,一個是@synthesize,一個是@dynamic。如果@synthesize和@dynamic都沒寫,那么默認的就是@syntheszie var = _var;
(2)@synthesize的語義是如果你沒有手動實現setter方法和getter方法,那么編譯器會自動為你加上這兩個方法。
(3)@dynamic告訴編譯器:屬性的setter與getter方法由用戶自己實現,不自動生成。(當然對于readonly的屬性只需提供getter即可)。假如一個屬性被聲明為@dynamic var,然后你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當程序運行到instance.var = someVar,由于缺setter方法會導致程序崩潰;或者當運行到someVar = instance.var時,由于缺getter方法同樣會導致崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。@dynamic可用于在分類中添加屬性(需要用到objc_getAssociatedObject和objc_setAssociatedObject函數)。
3.在Category中本身不允許為已有的類添加新的屬性或者成員變量,你有沒有其他的方法可以在category中添加屬性或者是成員變量?
答:一種方法就是使用runtime.h中的objc_getAssociatedObject和objc_setAssociatedObject來訪問和生成關聯對象。例如為NSObject添加一個類目,分類中添加一個屬性。代碼如下所示:
NSObject+Test.h文件
#import
@interface NSObject (Test)
@property (nonatomic, strong) NSString *test;
@end
NSObject+Test.m文件
#import “NSObject+Test.h"
#import
static const void *instanceNameKey = &instanceNameKey;
@implementation NSObject (Test)
@dynamic test;
- (NSString *)test
{
return objc_getAssociatedObject(self, instanceNameKey);
}
- (void)setTest:(NSString *)test
{
objc_setAssociatedObject(self, instanceNameKey, test, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
15.在oc中引入頭文件使用的關鍵字是哪一個?能在c語言文件中使用嗎?
答:#import關鍵字可以在OC中使用,不能在C文件中使用,#include可以在C和OC中使用。
16.#import與#include相比,好處是什么?
答:#import確定一個文件只能被導入一次,避免的重復導入的問題,使用#include一定要注意重復導入的問題。所以在OC中都使用#import來引用頭文件。
17.#import<>和#import””的區別是什么?
答:#import<>用于對系統文件的引用,編譯器會在系統文件目錄中去查找文件
#import””用于對自定義的文件的引用,編譯器首先回去用戶目錄下查找,然后去安裝目錄,最后去系統目錄中查找文件。
18.@class的作用是什么?
答:@class的作用是告訴編譯器有@class后面的內容是一個類名。只是告訴編譯器存在這么一個類,類具體包含哪些方法,屬性和變量的并沒有告訴編譯器。一般在類的頭文件中使用@class來引入其他類。
55.簡述你對UIView、UIWindow、CALayer的理解。
答:CALayer是圖層類,本身可以顯示的,但是不能響應事件。
UIView是iOS系統中界面元素的基礎,所有的界面元素都繼承自它。事件的處理由它來執行,但是顯示其實是由其對應的layer層來操作的,UIView內嵌了一個layer,layer顯示內容,UIView本身增加了事件處理的功能。
UIWindow繼承自UIView,主要的作用是作為窗口呈現其他的視圖。而且一個應用程序一般情況下只有一個窗口。
2.Sizeof和strlen的區別和聯系?
sizeof(...)是運算符,在頭文件中typedef為unsigned int,其值在編譯時即計算好了,參數可以是數組、指針、類型、對象、函數等。
它的功能是:獲得保證能容納實現所建立的最大對象的字節大小。
由于在編譯時計算,因此sizeof不能用來返回動態分配的內存空間的大小。實際上,用sizeof來返回類型以及靜態分配的對象、結構或數組所占的空間,返回值跟對象、結構、數組所存儲的內容沒有關系。
strlen(...)是函數,要在運行時才能計算。參數必須是字符型指針(char*)。當數組名作為參數傳入時,實際上數組就退化成指針了。
它的功能是:返回字符串的長度。該字符串可能是自己定義的,也可能是內存中隨機的,該函數實際完成的功能是從代表該字符串的第一個地址開始遍歷,直到遇到結束符NULL。返回的長度大小不包括NULL。
區別和聯系:
1.sizeof操作符的結果類型是size_t,它在頭文件中typedef為unsigned int類型。
該類型保證能容納實現所建立的最大對象的字節大小。
2.sizeof是運算符,strlen是函數。
3.sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以''\0''結尾的。
sizeof還可以用函數做參數,比如:
short f();
printf("%d\n", sizeof(f()));
輸出的結果是sizeof(short),即2。
4.數組做sizeof的參數不退化,傳遞給strlen就退化為指針了。
5.大部分編譯程序 在編譯的時候就把sizeof計算過了 是類型或是變量的長度這就是sizeof(x)可以用來定義數組維數的原因
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
6.strlen的結果要在運行的時候才能計算出來,時用來計算字符串的長度,不是類型占內存的大小。
7.sizeof后如果是類型必須加括弧,如果是變量名可以不加括弧。這是因為sizeof是個操作符不是個函數。
8.當適用了于一個結構類型時或變量,sizeof返回實際的大小,
當適用一靜態地空間數組,sizeof歸還全部數組的尺寸。
sizeof操作符不能返回動態地被分派了的數組或外部的數組的尺寸
3.do while和while do的區別?
while語句是先測試條件再執行語句,條件不符后終止
do while語句是先執行語句再測試條件,條件不符后終止,所以do while循環至少執行一次
15、const意味著”只讀”,關鍵字const什么含義?下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作?用是?一樣,a是?一個常整型數。第三個意味著a是?一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是?一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最后?一個意味著a是?一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時
指針也是不可修改的)。
欲阻?止?一個變量被改變,可以使?用const關鍵字。在定義該const變量時,通常需要對它進?行初
始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本?身為const,也可以指定指針所指的數據為const,或?二者同時指
定為const;
(3)在?一個函數聲明中,const可以修飾形參,表明它是?一個輸?入參數,在函數內部不
能改變其值;
(4)對于類的成員函數,若指定其為const類型,則表明其是?一個常函數,不能修改類的成員變量;
(5)對于類的成員函數,有時候必須指定其返回值為const類型,以使得其返回值不 為“左值”。
4.關鍵字volatile有什么含義?
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到
這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
? 并行設備的硬件寄存器(如:狀態寄存器)
? 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
? 多線程應用中被幾個任務共享的變量
? 一個參數既可以是const還可以是volatile嗎?解釋為什么。
? 一個指針可以是volatile嗎?解釋為什么。
下面是答案:
? 是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。
? 是的。盡管這并不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。
6、nil,NSNULL,NULL區別
nil定義一個實例為空,指向oc中對象的空指針.是對objective c id對象賦空值,對于objective c集合類對象 比如數組對象,字典對象,當我們不需要再使用他們的時候,對他們release的同時最好也把他們賦值為nil,這樣確保安全性,如果不賦值nil,可能導致程序崩潰
NSNull類定義了一個單例對象用于表示集合對象的空值
集合對象無法包含nil作為其具體值,如NSArray、NSSet和NSDictionary。相應地,nil值用一個特定的對象NSNull來表示。NSNull提供了一個單一實例用于表示對象屬性中的的nil值。默認的實現方法中,dictionaryWithValuesForKeys:和setValuesForKeysWithDictionary:自動地將NSNull和nil相互轉換,因此您的對象不需要進行NSNull的測試操作。
NULL可以用在C語言的各種指針上,在Objective-C里,nil對象被設計來跟NULL空指針關聯的。他們的區別就是nil是一個對象,而NULL只是一個值。而且我們對于nil調用方法,不會產生crash或者拋出異常。
8、NSDictionary和NSMutableDictionary的區別,是有序還是無序(追問:可以排序嗎?如何排序,最好代碼實現)
NSDictionary是不可變的對象,NSMutableDictionary是可變對象,可以進行添加和刪除操作。
是無序的
排序的話可以這樣做:
1.獲取所有的key
NSArray *myKeys = [myDictionary allKeys];
2.對key進行排序
NSArray *sortedKeys = [myKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
3.按照key獲取對象
id firstObject = [myDictionary objectForKey: [sortedKeys objectAtIndex:0]];
keysSortedByValueUsingSelector/keysSortedByValueUsingComparator通過使用指定SEL或NSComarator來對allKeys進行排序,然后通過objectsForKeys取出排序后的鍵-值對。
5、內存中的棧和堆的區別是什么?哪些數據在棧上哪些數據在堆上?
(1)管理方式:對于棧來講,是由編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產生memory leak。
(2)申請大小:能從棧獲得的空間較小,堆是向高地址擴展的數據結構,是不連續的內存區域。堆的大小受限于計算機系統中 有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
(3)碎片問題:對于堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。 對于棧來講,則不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應,以至于永遠都不可能有一個內存塊 從棧中間彈出
(4)分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成 的,比如局部變量的分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器 進行釋放,無需我們手工實現。
(5)分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧 都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很復雜的。
在函數體中定義的變量通常是在棧上,用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上。
8)淺復制和深復制的區別
淺層復制:只復制指向對象的指針,而不復制引用對象本身。
深層復制:復制引用對象本身。
意思就是說我有個A對象,復制一份后得到A_copy對象后,對于淺復制來說,A和A_copy指向的是同一 個內存資源,復制的只不過是是一個指針,對象本身資源 還是只有一份,那如果我們對A_copy執行了修改操作,那么發現A引用的對象同樣被修改,這其實違背 了我們復制拷貝的一個思想。深復制就好理解了,內存中存在了
兩份獨立對象本身。
用網上一哥們通俗的話將就是:
淺復制好比你和你的影子,你完蛋,你的影子也完蛋
深復制好比你和你的克隆人,你完蛋,你的克隆人還活著。
深淺拷貝前提是:是實現NSCopying或者NSMutableCopying協議。
淺拷貝只是復制對象本身,對象的屬性和包含的對象不做復制。
深拷貝則對對象本身復制,同時對對象的屬性也進行復制。
深淺拷貝的本質區別是對象或者對象屬性的內存地址是否一樣,一樣則為淺拷貝,不一樣則為深拷貝。
Foundation框架支持復制的類,默認是淺拷貝。其中對Foundation中不可變的對象進行copy時作用相當于retain。
而如果是mutablecopy時,無論對象是否可變,副本是可變的,并且實現了真正意義上的copy。如果對可變對象進行copy,
副本對象是不可變的,同樣是真正意義上的copy。
12readwrite,readonly,assign,retain,copy,nonatomic屬性的作?
@property是?一個屬性訪問聲明,擴號內?支持以下?幾個屬性: 1,getter=getterName,setter=setterName,設置setter與getter的?方法名2,readwrite,readonly,設置可供訪問級別2,assign,setter?方法直接賦值,不進?行任何retain操作,為了解決原類型與環循引?用問題3,retain,setter?方法對參數進?行release舊值再retain新值,所有實現都是這個順序(CC上有相關資料) 4,copy,setter?方法進?行Copy操作,與retain處理流程?一樣,先舊值release,再Copy出新的對象, retainCount為1。這是為了減少對上下?文的依賴?而引?入的機制。copy是在你不希望a和b共享?一塊內存時會使?用到。a和b各?自有?自?己的內存。5,nonatomic,?非原?子性訪問,不加同步,多線程并發訪問會提?高性能。注意,如果不加此屬性,則 默認是兩個訪問?方法都為原?子型事務訪問。鎖被加到所屬對象實例級(我是這么理解的...)。atomic和nonatomic?用來決定編譯器?生成的getter和setter是否為原?子操作。在多線程環境下,原?子操作 是必要的,否則有可能引起錯 誤的結果。
property中屬性retain,copy,assgin的含義分別是什么?有什么區別?將其轉換成get/set方法怎么做?有什么注意事項?
assign: 簡單賦值,不更改索引計數(Reference Counting)。
copy: 建立一個索引計數為1的對象,然后釋放舊對象
retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1
使用assign:對基礎數據類型 (NSInteger,CGFloat)和C數據類型(int, float, double, char,等等)
使用copy: 對NSString
使用retain: 對其他NSObject和其子類
retain表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
- (void)setInstance:(id)instance{
if (_instance != instance) {
[_instance release];
_instance = [instance retain];
}
}
copy表示賦值特性,setter方法將傳入對象復制一份;需要完全一份新的變量時。
- (void)setInstance:(id)instance{
if (_instance != instance) {
[_instance release];
_instance = [instance copy];
}
}
assign是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
- (void)setInstance:(id)instance{
if (_instance != instance) {
_instance = instance;
}
}
7、setValue和setObject區別
在使用NSMutableDictionary的時候經常會使用setValue forKey與setObject forKey,他們經常是可以交互使用的,代碼中經常每一種的使用都有。
他們2者的區別就是:
1、setObject:forkey:中value是不能夠為nil的,不然會報錯。
setValue:forKey:中value能夠為nil,但是當value為nil的時候,會自動調用removeObject:forKey方法
2、setValue:forKey:中key的參數只能夠是NSString類型,而setObject:forKey:的可以是任何類型
3、setObject:forKey:方法NSMutabledictionary特有的,而
setValue:forKey:方法是KVC(鍵-值編碼)的主要方法。
、類別和擴展
8、聲明并實現一個cotegory為UIView添加addNewView方法
.h
@interface UIView (AddNewView)
- (void)addNewView:(UIView *)view;
@end
.m
#import "UIView+AddNewView.h"
@implementation UIView (AddNewView)
- (void)addNewView:(UIView *)view
{
[self addSubview:view];
}
@end
9)類別和類擴展的區別
category和extensions的不同在于后者可以添加屬性。另外后者添加的?方法是必須要實現的。extensions可以認為是?一個私有的Category。
9.原子(atomic)跟非原子(non-atomic)屬性有什么區別?
①. atomic提供多線程安全。是防止在寫未完成的時候被另外一個線程讀取,造成數據錯誤
②. non-atomic:在自己管理內存的環境中,解析的訪問器保留并自動釋放返回的值,如果指定了nonatomic,那么訪問器只是簡單地返回這個值。
12.類別的作用?繼承和類別在實現中有何區別?
category可以在不獲悉,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。
并且如果類別和原來類中的方法產生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優先級。
類別主要有3個作用:
(1)將類的實現分散到多個不同文件或多個不同框架中。
(2)創建對私有方法的前向引用。
(3)向對象添加非正式協議。
繼承可以增加,修改或者刪除方法,并且可以增加屬性。
14.什么是KVO和KVC?
kvc:鍵 – 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是通過調用存取方法,直接或通過實例變量訪問的機制。
很多情況下可以簡化程序代碼。apple文檔其實給了一個很好的例子。
kvo:鍵值觀察機制,他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對于按鈕點擊變化狀態的的監控。
比如我自定義的一個button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對于系統是根據keypath去取的到相應的值發生改變,理論上來說是和kvc機制的道理是一樣的。
對于kvc機制如何通過key尋找到value:
“當通過KVC調用對象時,比如:[self valueForKey:@”someKey”]時,程序會自動試圖通過幾種不同的方式解析這個調用。首先查找對象是否帶有someKey這個方法,如果沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),如果還沒有找到,程序會繼續試圖調用-(id) valueForUndefinedKey:這個方法。如果這個方法還是沒有被實現的話,程序會拋出一個NSUndefinedKeyException異常錯誤。(cocoachina.com注:Key-Value Coding查找方法的時候,不僅僅會查找someKey這個方法,還會查找getsomeKey這個方法,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時,查找實例變量的時候也會不僅僅查找someKey這個變量,也會查找_someKey這個變量是否存在。)設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象能夠在錯誤發生前,有最后的機會響應這個請求。這樣做有很多好處,下面的兩個例子說明了這樣做的好處?!皝碇羉ocoa,這個說法應該挺有道理。因為我們知道button卻是存在一個highlighted實例變量.因此為何上面我們只是add一個相關的keypath就行了,可以按照kvc查找的邏輯理解,就說的過去了。
15.我們說的OC是動態運行時語言是什么意思?
多態。 主要是將數據類型的確定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來說,運行時機制使我們直到運行時才去決定一個對象的類別,以及調用該類別對象指定方法。
多態:不同對象以自己的方式響應相同的消息的能力叫做多態。意思就是假設生物類(life)都用有一個相同的方法-eat;
那人類屬于生物,豬也屬于生物,都繼承了life后,實現各自的eat,但是調用是我們只需調用各自的eat方法。
也就是不同的對象以自己的方式響應了相同的消息(響應了eat這個選擇器)。因此也可以說,運行時機制是多態的基礎。
18.類變量的@protected ,@private,@public,@package,聲明各有什么含義?(OC第二講 ?實例變量可見度與方法)
上面的幾個聲明表明的時類成員的作用域,@private作用范圍只能在自身類(外界既不可訪問,又不能繼承);@protected作用范圍在自身類和子類,如果什么都不加修飾,默認是@protected(外界不可訪問,但是可以繼承);@public作用范圍最大,可以在任何地方被訪問(外界即可訪問,又可以繼承);@package作用范圍在某個框架內
線程是什么?進程是什么?二者有什么區別和聯系? (UI第二十二講 多線程編程)
線程是CPU獨立運行和獨立調度的基本單位(可以理解為一個進程中執行的代碼片段),進程是資源分配的基本單位(進程是一塊包含了某些資源的內存區域)。進程是線程的容器,真正完成代碼執行的是線程,而進程則作為線程的執行環境。一個程序至少包含一個進程,一個進程至少包含一個線程,一個進程中的多個線程共享當前進程所擁有的資源。
32. What is lazy loading?
在使用的時候才去初始化,比如UITableViewCell的imageView屬性,懶加載對象的創建是在getter方法里面進行創建的。
34. isKindOfClass、isMemberOfClass作用分別是什么?
-(BOOL) isKindOfClass: classObj判斷是否是這個類或者是這個類子類的實例
-(BOOL) isMemberOfClass: classObj判斷是否是這個類的實例
OC里怎么實現多繼承
OC沒有多繼承。用協議實現多繼承,把協議中的方法在實現的類 中重寫C++有多繼承,多繼承其實用好了很方便。C++多繼承很容易出現 二一性比如:
類A { int a;}
類B:類A,類C:類A
類D : B, C那么int a到底是繼承自誰的單繼承
60.使用圓角效果時為什么會出現卡頓效果,如何解決這個問題?
不要在滾動視圖使用cornerRadius或者mask,添加self.layer.shouldRasterize = YES; ?self.layer.rasterizationScale = [UIScreen mainScreen].scale;
采取預先生成圓角圖片,并緩存起來這個方法才是比較好的手段。預處理圓角圖片可以在后臺處理,處理完畢后緩存起來,再在主線程顯示,這就避免了不必要的離屏渲染了。
在網絡請求中如何提高性能
在網絡請求中如何保證安全性
iOS在數據傳輸過程中有數據泄露的可能,客戶端在進行網絡請求時一般都采用加密的方式來保證數據的安全性,在iOS9以后,蘋果為了保護數據的安全性,使用了Https協議。
86.#define和const定義的變量,有什么區別什么情況下會出現內存的循環引用block中的weak self,是任何時候都需要加的么?
答案:
1.宏:只是在預處理器里進行文本替換,沒有類型,不做任何類型檢查,編譯器可以對相同的字符串進行優化。只保存一份到.rodata段。甚至有相同后綴的字符串也可以優化,你可以用GCC編譯測試,"Hello world"與"world"兩個字符串,只存儲前面一個。取的時候只需要給前面和中間的地址,如果是整形、浮點型會有多份拷貝,但這些數寫在指令中。占的只是代碼段而已,大量用宏會導致二進制文件變大.常量:共享一塊內存空間,就算項目中N處用到,也不會分配N塊內存空間,可以根據const修飾的位置設定能否修改,在編譯階段會執行類型檢查
2.(1)計時器NSTimer
一方面,NSTimer經常會被作為某個類的成員變量,而NSTimer初始化時要指定self為target,容易造成循環引用。 另一方面,若timer一直處于validate的狀態,則其引用計數將始終大于0.
(2)block
block在copy時都會對block內部用到的對象進行強引用(ARC)或者retainCount增1(非ARC)。在ARC與非ARC環境下對block使用不當都會引起循環引用問題,一般表現為,某個類將block作為自己的屬性變量,然后該類在block的方法體里面又使用了該類本身,簡單說就是self.someBlock = ^(Type var){[self dosomething];或者self.otherVar = XXX;或者_otherVar = ...};block的這種循環引用會被編譯器捕捉到并及時提醒。
(3)委托delegate
在委托問題上出現循環引用問題已經是老生常談了,本文也不再細講,規避該問題的殺手锏也是簡單到哭,一字訣:聲明delegate時請用assign(MRC)或者weak(ARC),千萬別手賤玩一下retain或者strong,畢竟這基本逃不掉循環引用了!
3.使用方將self或成員變量加入block之前要先將self變為__weak
Configuration中,debug和release的區別是什么?
Release是發行版本,比Debug版本有一些優化,文件比Debug文件小Debug是調試版本,Debug和Release調用兩個不同的底層庫。
一、"Debug是調試版本,包括的程序信息更多"
二、只有DEBUG版的程序才能設置斷點、單步執行、使用TRACE/ASSERT等調試輸出語句。
三、REALEASE不包含任何調試信息,所以體積小、運行速度快。
、Initilize和load的區別
http://www.cnblogs.com/ider/archive/2012/09/29/objective_c_load_vs_initialize.html
1.怎么修改只讀(readonly)屬性的變量
使用KVC可以修改,kvc就是鍵值編碼(key-value),可以通過指定的key獲得想要的值value。而不是通過調用Setter、Getter方法訪問。
什么情況使?用weak關鍵字,相?比assign有什么不同?在ARC中,防?止在有可能出現循環引?用的時候使?用weak關鍵字,?比如:block。assign可以修飾基本數據類型和C數據類型,也就是簡單的賦值,?而weak只能修飾OC對象類型。
1)在ARC中,在有可能出現循環引?用的時候,往往要通過讓其中?一端使?用weak來解決,?比如:delegate代理屬性
2)自身已經對它進?行?一次強引?用,沒有必要再強引?用?一次,此時也會使?用weak,?自定義IBOutlet控件屬性?一般也使?用weak;當然,也可以使?用strong。在下文也有論述:《IBOutlet連出來的視圖屬性為什么可以被設置成weak?》不同點:
1)weak此特質表明該屬性定義了?一種“?非擁有關系”(nonowning relationship)。為這種屬性設置新值時,設置?方法既不保留新值,也不釋放舊值。此特質同assign類似,然?而在屬性所指的對象遭到摧毀時,屬性值也會清空(nil out)。?而assign的“設置?方法”只會執?行針對“純量類型”(scalar type,例如CGFloat或NSlnteger等)的簡單賦值操作。
2) assign可以用非OC對象,而weak必須用于OC對象
3、copy和mutablecopy的區別copy返回?一個不可變對象,mutableCopy是創建?一個新的可變對象,并初始化源
對象的值,引?用計數為1。
1. mutableCopy創建?一個新的可變對象,并初始化為原對象的值,新對象的引用計數為1;
2. copy返回?一個不可變對象。分兩種情況:(1)若原對象是不可變對象,那么返回原對象,并將其引用計數加1 ;(2)若原對象是可變對象,那么創建?一個新的不可變對象,并初始化為原對象的值,新對象的引用計數為1。
@synthesize和@dynamic的區別?
@synthesize就是?自動?生成屬性的setter和getter?方法。
@dynamic就是要告訴編譯器,?自?己實現?方法。
object-c為了讓java的開發者習慣使?用.的操作,所以可以將接??口類中的變量使?用@property來聲明屬性。但是在.h中聲明的屬性,必須在.m中使?用@synthesize或者@dynamic來實現(傳?言,在最近出的ios6中這步已經省了),否則屬性不可?用。熟悉object-c語法的都知道@synthesize實際的意義就是?自動?生成屬性的setter和getter?方法。
@dynamic就是要告訴編譯器,代碼中?用@dynamic修飾的屬性,其getter和setter?方法會在程序運?行的時候或者?用其他?方式動態綁定,以便讓編譯器通過編譯。其主要的作?用就是?用在NSManagerObject對象的屬性聲明上,由于此類對象的屬性?一般是從Core Data的屬性中?生成的,core data框架會在程序運?行的時候為此類屬性?生成getter和setter?方法,但是如果不是NSManagerObject的?子類,就必須?手動實現setter和getter?方法,否則將出現野指針;
5、__block和__weak修飾符的區別
1.__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型。
2.__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數據類型(int)。
3.__block對象可以在block中被重新賦值,__weak不可以。
PS:__unsafe_unretained修飾符可以被視為iOS SDK 4.3以前版本的__weak的替代品,不過不會被自動置空為nil。所以盡可能不要使用這個修飾符。
6.在什么情況下會用到weak這個關鍵字,作用是什么?
適用于OC對象,作用和非ARC中的assign作用相同,修飾的成員變量為弱指針類型
IBOutlet的屬性一般可以設為weak是因為它已經被view引用了,除非view被釋放,否則IBOutlet的屬性也不會被釋放,另外IBOutlet屬性的生命周期和view應該是一致的,所以IBOutlet屬性一般設為weak。
4、隊列和棧的區別是什么?
1.隊列先進先出,棧先進后出。
2.對插入和刪除操作的"限定"。 棧是限定只能在表的一端進行插入和刪除操作的線性表。 隊列是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。 從"數據結構"的角度看,它們都是線性結構,即數據元素之間的關系相同。但它們是完全不同的數據類型。除了它們各自的基本操作集不同外,主要區別是對插入和刪除操作的"限定"。 棧和隊列是在程序設計中被廣泛使用的兩種線性數據結構,它們的特點在于基本操作的特殊性,棧必須按"后進先出"的規則進行操作,而隊列必須按"先進先出"的規則進行操作。和線性表相比,它們的插入和刪除操作受更多的約束和限定,故又稱為限定性的線性表結構。
3.遍歷數據速度不同。棧只能從頭部取數據 也就最先放入的需要遍歷整個棧最后才能取出來,而且在遍歷數據的時候還得為數據開辟臨時空間,保持數據在遍歷前的一致性隊列怎不同,他基于地址指針進行遍歷,而且可以從頭或尾部開始遍歷,但不能同時遍歷,無需開辟臨時空間,因為在遍歷的過程中不影像數據結構,速度要快的多。
8、NSDictionary和NSMutableDictionary的區別,是有序還是無序(追問:可以排序嗎?如何排序,最好代碼實現)
NSDictionary是不可變的對象,NSMutableDictionary是可變對象,可以進行添加和刪除操作。
是無序的
排序的話可以這樣做:
1.獲取所有的key
NSArray *myKeys = [myDictionary allKeys];
2.對key進行排序
NSArray *sortedKeys = [myKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
3.按照key獲取對象
id firstObject = [myDictionary objectForKey: [sortedKeys objectAtIndex:0]];
keysSortedByValueUsingSelector/keysSortedByValueUsingComparator通過使用指定SEL或NSComarator來對allKeys進行排序,然后通過objectsForKeys取出排序后的鍵-值對。
9、推送通知和本地通知的區別
本地推送和遠程推送的區別是本地推送一般是用來實現鬧鐘或者生日提醒的功能.遠程推送是為了實現服務器想要把及時的消息在某個特定的時間發送給用戶的手段.
本地推送不需要申請推送證書,遠程推送需要先申請證書然后再去實現證書.
13.AVPlayer ?AVAudioPlayer ?MediaPlayer的不同
AVAudioPlayer:使用簡單方便,但只能播放本地音頻,不支持流媒體播放
AVPlayer: iOS4.0以后,可以使用AVPlayer播放本地音頻和支持流媒體播放,但是提供接口較少,處理音頻不夠靈活
MediaPlayer :是用來處理網絡上的視頻文件的播放的系統類.
24XML、JSON解析;
(1)區別:
(1)可讀性方面:基本相同,xml的可讀性比較好
(2)可擴展性方面:都具有很好的擴展性
(3)編碼難度方面:相對而言:JSON的編碼比較容易
(4)解碼難度:json的解碼難度基本為零,xml需要考慮子節點和父節點
(5)數據體積方面:json相對于xml來講,數據體積小,傳遞的速度跟快些
(6)數據交互方面:json與JavaScript的交互更加方面,更容易解析處理,更好的數據交互
(7)數據描述方面:xml對數據描述性比較好
(8)傳輸速度方面:json的速度遠遠快于xml
(2)
1)JSON底層原理:
遍歷字符串中的字符,最終根據格式規定的特殊字符,比如{}號,[]號, :號等進行區分,{}號是一個字典的開始,[]號是一個數組的開始, :號是字典的鍵和值的分水嶺,最終乃是將json數據轉化為字典,字典中值可能是字典,數
組,或字符串而已。
2)XML底層原理:XML解析常用的解析方法有兩種:DOM解析和SAX解析。DOM采用建立樹形結構的方式訪問XML文檔,而
SAX采用的事件模型。
DOM解析把XML文檔轉化為一個包含其內容的樹,并可以對樹進行遍歷。使用DOM解析器的時候需要處理整個XML文檔,所以對性能和內存的要求比較高。SAX在解析XML文檔的時候可以觸發一系列的事件,當發現給定的tag的時候,它可以激活一個回調方法,告訴該方法制定的標簽已經找到。SAX對內存的要求通常會比較低,因為它讓開發人員自己來決定所要處理的tag。特別是當開發人員只需要處理文檔中所包含的部分數據時,SAX這種擴展能力得到了更好的體現。
3)SAX與DOM的區別:
1、SAX處理的優點非常類似于流媒體的優點。分析能夠立即開始,而不是等待所有的數據被處理。而且由于應用程序只是在讀取數據時檢查數據,因此不需要將數據存儲在內存中。這對于大型文檔來說是個巨大的優點。事實上,應用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。一般來說,SAX還比它的替代者DOM快許多。另一方面,由于應用程序沒有以任何方式存儲數據,使用SAX來更改數據或在數據流中往后移是不可能的。
2、DOM以及廣義的基于樹的處理具有幾個優點。首先,由于樹在內存中是持久的,因此可以修改它以便應用程序能對數據和結構作出更改。它還可以在任何時候在樹中上下導航,而不是像SAX那樣是一次性的處理。DOM使用起來也要簡單得多。另一方面,在內存中構造這樣的樹涉及大量的開銷。大型文件完全占用系統內存容量的情況并不鮮見。此外,創建一棵DOM樹可能是一個緩慢的過程。
11.方法(method)和選擇器有何不同?
NSDictionary是不可變的對象,NSMutableDictionary是可變對象,可以進行添加和刪除操作。
是無序的
排序的話可以這樣做:
1.獲取所有的key
NSArray *myKeys = [myDictionary allKeys];
2.對key進行排序
NSArray *sortedKeys = [myKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
3.按照key獲取對象
id firstObject = [myDictionary objectForKey: [sortedKeys objectAtIndex:0]];
keysSortedByValueUsingSelector/keysSortedByValueUsingComparator通過使用指定SEL或NSComarator來對allKeys進行排序,然后通過objectsForKeys取出排序后的鍵-值對。
1.bounds和frame的區別?bound的大小改變frame改變嗎?
bounds相當于是一個視圖的坐標,一個視圖的frame是相對于父視圖的bounds,改變bounds并不會影響本視圖的frame,但是會對子視圖的布局造成影響
24.說說響應鏈
當事件發生的時候,響應鏈首先被發送給第一個響應者(往往是事件發生的視圖,也就是用戶觸摸屏幕的地方)。事件將沿著響應者鏈一直向下傳遞,直到被接受并作出處理。一般來說,第一響應這是個視圖對象或者其子類,當其被觸摸后事件就交由它處理,如果他不處理,時間就會被傳遞給視圖控制器對象UIViewController(如果存在),然后是它的父視圖對象(superview),以此類推直到頂層視圖。接下來會沿著頂層視圖(topview)到窗口(UIwindow對象)再到程序的(UIApplication對象),如果整個過程都沒有響應這個事件,則該事件被丟棄,一般情況下,在響應鏈中只要有對象處理事件,事件就會被傳遞典型的響應路線圖如:First Responser -> The Window ->The Applicationn -> App Delegate
4、drawInRect
在運行到drawInRect:withFont: lineBreakMode:alignment:,出現提示iOS7棄用這個方法,使用drawInRect:withAttributes:的方法的提示。但是這個方法在說明的時候,寫的很簡單,第二個參數是一個字典,根本就搞不明白是什么東西。我在查了不少資料后,才翻到字典里面能存放的東西:NSAttributedString,里面竟然可以使用21組鍵值對,功能強大了不少。NSParagraphStyleAttributeName這個key就能代替iOS6上的那個棄用方法,不過值必須得是NSMutableParagraphStyle,不然不能自定義
5、NSAttributedString屬性字符串
NSAttributedString管理一個字符串,以及與該字符串中的單個字符或某些范圍的字符串相關的屬性。比如這個字符串“我愛北京天安門”,“我”跟其他字符的顏色不一樣,而“北京”與其他的字體和大小不一樣,等等。NSAttributedString就是用來存儲這些信息的,具體實現時,NSAttributedString維護了一個NSString,用來保存最原始的字符串,另有一個NSDictionary用來保存各個子串/字符的屬性。
學習鏈接:http://blog.csdn.net/zhangao0086/article/details/7616385
UIScrollview重用機制
事件處理看過了,就要考慮scrollView如何重用內存的,下面寫了一個例子模仿UITableView的重用的思想,這里只是模仿,至于蘋果公司怎么實現這種重用的,他們應該有更好的方法。
這里的例子是在scrollView上放置4個2排2列的視圖,但是內存中只占用6個視圖的內存空間。當scrollView滾動的時候,通過不停的重用之前視圖的內存空間,從而達到節省內存的效果。重用的方法如下:
1.如果scrollView向下面滾動,一旦一排視圖滾出了可視范圍,就改變滾動出去的那個view在scrollView中的frame,也就是改變位置到達末尾,達到重用的效果。
2.如果scrollView向上面滾動,一旦最末排的視圖view滾出了可視范圍,就改變滾動出去的那個view在scrollView中的frame,移動到最前面。
8、描述什么是面向對象?
面向對象:
把數據及對數據的操作方法放在一起,作為一個相互依存的整體——對象。對同類對象抽象出其共性,形成類。類中的大多數數據,只能用本類的方法進行處理。類通過一個簡單的外部接口與外界發生關系,對象與對象之間通過消息進行通信。程序流程由用戶在使用中決定。
1、UITableView的執行流程是怎么樣的?
第一輪:
1、numberOfSectionsInTableView:假如section=2,此函數只執行一次,假如section=0,下面函數不執行,默認為1
2、heightForHeaderInSection,執行兩次,此函數執行次數為section數目
3、heightForFooterInSection,函數屬性同上,執行兩次
4、numberOfRowsInSection,此方法執行一次
5、heightForHeaderInSection,此方法執行了兩次,我其實有點困惑為什么這里還要調用這個方法
6、heightForFooterInSection,此方法執行兩次,
7、numberOfRowsInSection,執行一次
8、heightForRowAtIndexPath,行高,先執行section=0,對應的row次數
第二輪:
1、numberOfSectionsInTableView,一次
2、heightForHeaderInSection,section次數
3、heightForFooterInSection,section次數
4、numberOfRowsInSection,一次
5、heightForHeaderInSection,執行section次數
6、heightForFooterInSection,執行section次數
7、numberOfRowsInSection,執行一次
8、heightForRowAtIndexPath,行高,先執行一次
9、cellForRowAtIndexPath
10、willDisplayCell
然后8、9、10依次執行直到所有的cell被描畫完畢