307、setValue:forKey和setObject:forKey的區別是什么?
答:
1, setObject:forkey:中value是不能夠為nil的,不然會報錯。
setValue:forKey:中value能夠為nil,但是當value為nil的時候,會自動調用removeObject:forKey方法。
2, setValue:forKey:中key的參數只能夠是NSString類型,而setObject:forKey:的可以是任何類型
238.用變量a給出下面的定義
a)一個整型數(An integer)
b)一個指向整型數的指針(A pointer to an integer)
c)一個指向指針的的指針,它指向的指針是指向一個整型數(A pointer to a pointer to an integer)
d)一個有10個整型數的數組(An array of 10 integers)
e)一個有10個指針的數組,該指針是指向一個整型數的(An array of 10 pointers to integers)
f)一個指向有10個整型數數組的指針(A pointer to an array of 10 integers)
g)一個指向函數的指針,該函數有一個整型參數并返回一個整型數(A pointer to a function that takes an integer as an argument and returns an integer)
h)一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數并返回一個整型數(An array of ten pointers to functions that take an integer argument and return an integer)
答案:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int a[10]; // An array of 10 pointers to integers
f) int (a)[10]; // A pointer to an array of 10 integers
g) int (a)(int);// A pointer to a function a that takes an integer argument and returns an integer
h) int (a[10])(int);// An array of 10 pointers to functions that take an integer argument and return an integer
301、在一個數組中存在一萬條以上的字符串,現在要對數組中所有字符串進行拼接操作,請寫出拼接方法(要考慮到性能及內存占用情況,ARC模式)。
NSString *string = [array componentsJoinedByString:@","];
236.Static全局變量與普通的全局變量有什么區別?static局部變量和普通局部變量有什么區別?static函數與普通函數有什么區別?
答:
static全局變量與普通的全局變量有什么區別:static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量有什么區別:static局部變量只被初始化一次,下一次依據上一次結果值;
static函數與普通函數有什么區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝。
222.簡述淺拷貝和深拷貝
//淺拷貝就比如像引用類型,而深拷貝就比如值類型。
淺拷貝是指源對象與拷貝對象共用一份實體,僅僅是引用的變量不同(名稱不同)。對其中任何一個對象的改動都會影響另外一個對象。舉個例子,一個人一開始叫張三,后來改名叫李四了,可是還是同一個人,不管是張三缺胳膊少腿還是李四缺胳膊少腿,都是這個人倒霉。
深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。舉個例子,一個人名叫張三,后來用他克隆(假設法律允許)了另外一個人,叫李四,不管是張三缺胳膊少腿還是李四缺胳膊少腿都不會影響另外一個人。比較典型的就是Value(值)對象,如預定義類型Int32,Double,以及結構(struct),枚舉(Enum)等。
C#中有兩種類型變量,一種是值類型變量,一種是引用類型變量。對于前者,copy是屬于全盤復制;而對于后者,一般的copy只是淺copy,相當于只傳遞一個引用指針一樣。因此對于后者進行真正copy的時候,也是最費事的,具體的說,必須為其實現ICloneable接口中提供的Clone方法。
淺拷貝(影子克隆):只復制對象的基本類型,對象類型,仍屬于原來的引用.
深拷貝(深度克隆):不緊復制對象的基本類,同時也復制原對象中的對象.就是說完全是新對象產生的.
189.淺復制和深復制的區別?
答:簡單的來說就是,在有指針的情況下,淺拷貝只是增加了一個指針指向已經存在的內存,而深拷貝就是增加一個指針并且申請一個新的內存,使這個增加的指針指向這個新的內存,采用深拷貝的情況下,釋放內存的時候就不會出現在淺拷貝時重復釋放同一內存的錯誤!
214.簡述淺拷貝和深拷貝
答案:
淺層復制:只復制指向對象的指針,而不復制引用對象本身。
深層復制:復制引用對象本身。
意思就是說我有個A對象,復制一份后得到A_copy對象后,對于淺復制來說,A和A_copy指向的是同一個內存資源,復制的只不過是是一個指針,對象本身資源
還是只有一份,那如果我們對A_copy執行了修改操作,那么發現A引用的對象同樣被修改,這其實違背了我們復制拷貝的一個思想。深復制就好理解了,內存中存在了
兩份獨立對象本身。
用網上一哥們通俗的話將就是:
淺復制好比你和你的影子,你完蛋,你的影子也完蛋深復制好比你和你的克隆人,你完蛋,你的克隆人還活著。
168.淺復制和深復制的區別
簡單的來說就是,在有指針的情況下,淺拷貝只是增加了一個指針指向已經存在的內存,而深拷貝就是增加一個指針并且申請一個新的內存,使這個增加的指針指向這個新的內存,采用深拷貝的情況下,釋放內存的時候就不會出現在淺拷貝時重復釋放同一內存的錯誤!
我列舉一個例子來說吧:
你正在編寫C++程序中有時用到,操作符的重載。最能體現深層拷貝與淺層拷貝的,就是‘=’的重載。
- Write something about the differencesbetween Objective-C and C++.
寫一些關于Objective-C和C++之間的差異
答案:
1、Objective C基本上是在C +
Smalltalk基礎上衍生出來的,C++就是C++。除了都是從C語言分化出來的以外,完全沒有任何共性。
2、最大的區別就是Objective C的成員函數調用是基于動態綁定的,類本身并沒有限制對象可以有什么函數。相對于C++類會規定好成員有什么函數。這使得Objective C的靈活性很大,但是執行效率也很低。
3、在NeXT系統的時代C++和Objective C都不是那么大眾的東西,C++也還沒完善,而且那個時代編譯器的有優化能力也沒現在那么變態。所以選擇Objective C也不是很奇怪的事。但是現在Objective C的劣勢就越來越明顯了,所以蘋果開發了Swift,而且就內部消息蘋果很可能會準備放棄OC。
- __unsafe_unretained vs__weak; purposeof __block; NSString const * vs NSString *const
unsafe_unretained往往都是用來聲明屬性的,如果想聲明臨時變量就得用__strong,__weak,__unsafe_unretained,__autoreleasing;
block閉包就是能夠讀取其它函數內部變量的函數;
NSString const HSCoder = @"漢斯哈哈哈";
"HSCoder"不能被修改,"HSCoder"能被修改
NSString * const HSCoder = @"漢斯哈哈哈";
"HSCoder"不能被修改,"*HSCoder"能被修改
191.我們說的OC是動態運行時語言是什么意思?
多態。
答:主要是將數據類型的確定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來說,運行時機制使我們直到運行時才去決定一個對象的類別,以及調用該類別對象指定方法。多態:不同對象以自己的方式響應相同的消息的能力叫做多態。
意思就是假設生物類(life)都用有一個相同的方法-eat;那人類屬于生物,豬也屬于生物,都繼承了life后,實現各自的eat,但是調用是我們只需調用各自的eat方法。
也就是不同的對象以自己的方式響應了相同的消息(響應了eat這個選擇器)。
因此也可以說,運行時機制是多態的基礎。
185.obj-c的優缺點
答:
objc優點:
1)Cateogies
2)Posing
3)動態識別
4)指標計算
5)彈性訊息傳遞
6)不是一個過度復雜的C衍生語言
7)Objective-C與C++可混合編程缺點:
1)不支援命名空間
2)不支持運算符重載
3)不支持多重繼承
4)使用動態運行時類型,所有的方法都是函數調用,所以很多編譯時優化方法都用不到。(如內聯函數等),性能低劣。OC沒有多重繼承,Java也沒有,C++才有
OC使用協議來實現多重繼承
181.static關鍵字的作用
答案:
(1)設置變量的存儲域,函數體內static變量的作用范圍為該函數體,不同于auto變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
(2)限制變量的作用域,在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)限制函數的作用域,在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明它的模塊內;
(4)在類中的static成員變量意味著它為該類的所有實例所共享,也就是說當某個類的實例修改了該靜態成員變量,其修改值為該類的其它所有實例所見;
(5)在類中的static成員函數屬于整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。
160.static關鍵字的作用?
在C語言中,關鍵字static有三個明顯的作用:
1).在函數體,一個被聲明為靜態的變量在這一函數被調用過程中維持其值不變。
2).在模塊內(但在函數體外),一個被聲明為靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
3).在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。
188.類別的作用?
答:類別主要有3個作用:
(1)將類的實現分散到多個不同文件或多個不同框架中。
(2)創建對私有方法的前向引用。
(3)向對象添加非正式協議
167.類別的作用
作用:
1.對系統的類或自己定義的類的擴充(只是指,不能聲明屬性Instance variable)e.g. base64 MD5.但是不能保證所有的方法都能被調用。尤其是在指定一個與系統的方法相同的方法時一定要注意。
文件名:NSString+additions.h
NSString+additions.m
@interface NSString (Base64)
2.可以聲明私有方法。
ZYViewController.m
@interfaceZYViewController (additions)
//{
//BOOL isOK;
//}
-(void)ok;
@property
@end
3.可以聲明分散類的方法(NSIndexPath)
分散類體現出類別不僅可以擴充系統的方法,而且可以擴充自己定義的類。
由第3個作用可知:不管是否使用的分散類在任何的.h文件中,我只考慮類別中的方法包裹在@interface className ..@end,那么我只明確將來類別中的方法就屬于className這個類。
iOS里面是否有GBK的字符編碼描述?即NSUTF8StringEncoding如果有,是怎樣的?
什么情況下使用關鍵字weak和assign有何不同?
答:assign指針賦值,不對引用計數操作,使用之后如果沒有置為nil,可能就會產生野指針;
而weak一旦不進行使用后,永遠不會使用了,就不會產生野指針!
- 下面說法不正確的是 C
A readwrite 是可讀可寫特性;需要生成getter方法和setter方法時
B readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變
C assign 是賦值特性,和weak一樣,可用weak代替;
D retain 表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
18、下面關于#import和#include的描述正確的是
A. #import 是 #include 的替代指令,防止重復引用
B. #import 和 #include 不可以混合使用
C. #import 只用于引用 Objective-C的文件, #include 只用于引用C和C++的文件
D. #import 和 #include 的使用效果完全相同(A)
7.#import跟#include有什么區別,@class呢?#import<>跟#import””有什么區別?
答:#import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字,使用#import頭文件會自動只導入一次,不會重復導入,相當于#include和#pragma once;@class告訴編譯器某個類的聲明,當執行時,才去查看類的實現文件,可以解決頭文件的相互包含;
import<>用來包含系統的頭文件,#import””用來包含用戶頭文件。
8.屬性readwrite,readonly,assin,retain,copy,nonatomic各是什么作用,在哪種情況下用?
答:
readwrite是可讀可寫特性;需要生成getter方法和setter方法時
readonly是只讀特性只會生成getter方法不會生成setter方法;不希望屬性在類外改變
assign是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy表示拷貝特性,setter方法將傳入對象復制一份;需要完全一份新的變量時。
nonatomic非原子操作,決定編譯器生成的setter
getter是否是原子操作,atomic表示多線程安全,一般使用nonatomic
199..屬性readwrite , readonly , assign , retain , copy , nonatomic ,各是什么作用,在哪種情況下用?
答:
assign用于簡單數據類型,如NSInteger,double,bool,
retain和copy用于對象,
readwrite是可讀可寫特性;需要生成getter方法和setter方法時
readonly是只讀特性只會生成getter方法不會生成setter方法;不希望屬性在類外改變
assign是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy表示賦值特性,setter方法將傳入對象復制一份;需要一份新的變量時。
nonatomic非原子操作,atomic原子性操作。原子性指的是一個操作不可以被中途cpu暫停然后調度,即不能被中斷,要不就執行完,要不就不執行,就是為了多線程安全的。
一般使用nonatomic。
70.用預處理指令#define聲明一個常數,用以表明一年中有多少秒?(忽略閏年問題)
答:#define second 3652460*60
98.設有以下宏定義:
.#defineN4
.#defineY(n)((N + 1) * n)
則執行語句: Y(5 + 1)為:(26)
*93.C++和Objective-C的混合使用,以下描述錯誤的是()
//未找到答案或是C++JAVA
A. cpp文件只能使用C/C++代碼
B. cpp文件include的頭文件中,可以出現objective-C的代碼
C. mm文件中混用cpp直接使用即可
D. cpp使用objective-C的關鍵是使用接口,而不能直接使用代碼
94.以下哪一段代碼不會拋出異常( C& D )
A. NSArray array = @[1, 2, 3];NSNumbernumber = array[3];// @[@1,@ 2,@ 3]
B. NSDictionary *dict = @{@”key”: nil};//value不能為空
C. NSString *str = nil; NSString *str2 =[str substringFromIndex:3];
D. NSString *str = @”hi”;NSString *str2 =[str substringFromIndex:3];
99.如下程序用于把"blue"字符串返回,請指出其中的錯誤.
//不確定
char GetBlue(){
char pcColor;
charpcNewColor;
pcColor = “blue”;
pcNewColor =(char)malloc(strlen(pcColor));
strcpy(pcNewColor, pcColor);
return pcNewColor;
}
答:strcpy是一個字符串拷貝的函數,它的函數原型為strcpy(char *dst, c*****t char *src);將src開始的一段字符串拷貝到dst開始的內存中去,結束的標志符號為'\0',由于拷貝的長度不是由我們控制的,所以這個字符串拷貝很容易出錯
106.請寫出一個xml文件,用于描述一個書架,書架上有2本書,書本的類別(category)分別是cooking,children.要求tag中包含書名(title),作者(author).類別(category)要用屬性表示.
答:
書名1<\title>
作者1<\author>
<\book>
書名2<\title>
作者2<\author>
<\book>
關鍵字
107.strcpy和memcpy的最大區別是什么?
答:
1、復制的內容不同。strcpy只能復制字符串,而memcpy可以復制任意內容,例如字符數組、整型、結構體、類等。
2、復制的方法不同。strcpy不需要指定長度,它遇到被復制字符的串結束符"\0"才結束,所以容易溢出。memcpy則是根據其第3個參數決定復制的長度。
3、用途不同。通常在復制字符串時用strcpy,而需要復制其他類型數據時則一般用memcpy
109.@class用途
答:@class一般用于頭文件中聲明某個類的實例變量的時候用到.它只是聲明,至于內部的實現是沒有告訴編譯器的.
110.delegate使用assign or retain簡述理由.
答:assign,防止出現循環引用;
111.NSString與NSData之間的轉換過程中要特別注意的事項是什么?
解:
NSString轉換成NSData對象
NSData *xmlData = [@"testdata"dataUsingEncoding:NSUTF8StringEncoding];NSData轉換成NSString對象
NSData *data;
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];NSData轉換成char*
NSData *data;
char *test=[data bytes];char轉換成NSData對象
byte tempData = malloc(sizeof(byte)*16);
NSData *content=[NSData dataWithBytes:tempData length:16];轉換過程中要注意NSData的編碼格式問題.
解決方法:
先設置斷點然后在控制臺po出NSData的變量,看看會顯示什么。
如果po出的NSData是可閱讀的,直接能看到文本的內容,則使用[NSString stringWithFormat:NSData] (這里的NSData指的是你需要轉換成NSString的NSData變量)即可。
如果po出的NSData是不可閱讀的亂碼,那一般都是有編碼格式的,最常用的是NSUTF8StringEncoding,另外還有NSASCIIStringEncoding等,你可以在Apple文檔里找到編碼格式的那個枚舉類型,挨個嘗試。
112.請用代碼如何判斷某個對象obj是否支持某個method.
解:
if ([srespondsToSelector:@selector(print:)]) {
[s print:@"支持這個方法"];
}
113.請用簡單的代碼展示@protocol的定義及實現.
解:
#warning代理第一步:聲明協議
@protocol MarryMe
-(void)makeMoney;
@end
#warning代理第二步:聲明代理
@property(nonatomic,assign)id myDeleget;
.m文件中
#warning代理第三步:代理人執行協議方法
[self.myDeleget makeMoney];
代理人.m文件中
#warning代理第四步:簽訂協議
@interface Boy : NSObject
Girl *girl = [[Girl alloc] init];
#warning代理第五步:成為代理人
girl.myDeleget = self;
[girl getMessage:message];
#warning協議代理第六步:實現協議方法
-(void)makeMoney{
NSLog(@"aaa");
}
4.描述下Abstract Class和interface的異同,寫出Objective-C Interface的定義語句。
抽象類和接口的異同
抽象類的變體
2.描述下#import和#include的作用,說下它們的區別。
導入文件的可避免重復性問題
.h文件中的變量,外部可以直接訪問么?(注意是變量,不是property)
直接訪問的話是沒法訪問到的,可以通過runtime的ivar去獲取他的所有變量信息遍歷就可以獲取到二叉搜索樹的概念,時間復雜度多少?
它獲取是一個空樹、或者是具有以下性質的二叉樹:若他的左子樹不空,則左子樹上所有節點上的值均小于他根節點的值,若他的右子樹不空,則右子樹上所有節點的值均大于他根節點的值。
<時間復雜度不知>
.#define和const定義的變量,有什么區別
define:無類型校驗、無分配內存、使用的話內存上多次拷貝、預處理的時候展開
const:有類型校驗、有分配內存、使用的話內存上一次拷貝、編譯運行階段使用
14、如何淺拷貝與深拷貝的理解?
參考答案:
所謂淺拷貝是指只復制指向對象的指針,而不復制引用對象本身(同一份內存),而所謂深拷貝是指復制引用對象本身(新創建了一份內存)。
打個比方:
淺復制好比是你的影子,當你掛了,影子也消失了。 深復制好比克隆你,即使你掛了,新克隆出來的人是新的生命,不會因為你掛了也跟著掛。
15、使用是懶加載?常見場景?
參考答案:
所謂懶加載是指在真正需要到的時候才真正載入內存。常見的場景就是重寫屬性的getter方法,在getter方法中判斷是否創建過或者加載過,若未創建過或者未加載過,則創建或者加載。
懶加載可以優化性能,有的功能一般情況下不會使用到,但是這些功能一使用就會占較大的內存,此時使用懶加載就非常的好了。
常見的寫法:
-(NSMutableArray *)dataSource {
if (_dataSource == nil) {
_dataSource = [[NSMutableArray alloc]init];
// 添加默認數據等
// ...
}
}
7、頭文件中聲明的成員變量(不是屬性),外部可直接訪問么?
參考答案:
外部不能直接訪問頭文件所聲明的成員變量,需要提供成員變量的getter方法才能在外部訪問。
而屬性已經直接給我們自動生成了getter方法,因此外部可以直接訪問屬性。
3、#define定義的宏和const定義的常量有什么區別?
參考答案:
* #define定義宏的指令,程序在預處理階段將用#define所定義的內容只是進行了替換。因此程序運行時,常量表中并沒有用#define所定義的宏,系統并不為它分配內存,而且在編譯時不會檢查數據類型,出錯的概率要大一些。
* const定義的常量,在程序運行時是存放在常量表中,系統會為它分配內存,而且在編譯時會進行類型檢查。
* #define定義表達式時要注意“邊緣效應”,例如如下定義:
#define N 2 + 3 // 我們預想的N值是5,我們這樣使用N
int a = N / 2; // 我們預想的a的值是2.5,可實際上a的值是3.5
322、全局變量可不可以定義在可被多個.C文件包含的頭文件中?為什么?
答:可以。在不適用static或者const(隱式static)情況下,變量的定義只能出現一次,否則會導致重復定義。但卻可以聲明多次。因此全局變量不可以定義在頭文件中。因為當該頭文件被多個c文件包含的話,會導致重復定義。因此一般做法是在某個特定的頭文件中聲明,而在另外一個特定的c文件中定義。需要使用就包含前者。
312、聲明NSString類型的屬性時,用copy和strong的區別是什么?
copy修飾的NSString,在初始化時,如果來源是NSMutableString的話,會對來源進行一次深拷貝,將來源的內存地址復制一份,這樣,兩個對象就一點關系就沒有了,無論你怎么操作來源,都不會對自己的NSString有任何影響。
314、static全局變量與普通的全局變量有什么區別?static普通函數有什么區別?
全局變量(外部變量)的說明之前再冠以static就構成了靜態的全局變量。全局變量本身就是靜態存儲方式,靜態全局變量當然也是靜態存儲方式。這兩者在存儲方式上并無不同。這兩者的區別雖在于非靜態全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。而靜態全局變量則限制了其作用域,即只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它。由于靜態全局變量的作用域局限于一個源文件內,只能為該源文件內的函數公用,因此可以避免在其它源文件中引起錯誤。從以上分析可以看出,把局部變量改變為靜態變量后是改變了它的存儲方式即改變了它的生存期。把全局變量改變為靜態變量后是改變了它的作用域,限制了它的使用范圍。static函數與普通函數有什么區別?只在當前源文件中使用的函數應該說明為內部函數(static),內部函數應該在
當前源文件中說明和定義。對于可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件。
6、用預處理指令#define聲明一個常數,用以表明一年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在這想看到幾件事情:
#define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)
懂得預處理器將為你計算常數表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。
意識到這個表達式將使一個16位機的整型數溢出-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。
如果你在你的表達式中用到UL(表示無符號長整型),那么你有了一個好的起點。記住,第一印象很重要。
7、定義屬性時,什么時候用copy,assign和retain
當用copy時,set方法會先release舊值,再copy一個新的對象,reference count 為1(減少了對上下文的依賴);
當用assign,直接賦值,無retain操作。當用retain,release舊值,retain新值;
1.非ARC
1> copy : 只用于NSString\block
2> retain : 除NSString\block以外的OC對象
3> assign : 基本數據類型、枚舉、結構體(非OC對象),當2個對象相互引用,一端用retain,一端用assign2.ARC
1> copy : 只用于NSString\block
2> strong : 除NSString\block以外的OC對象
3> weak : 當2個對象相互引用,一端用strong,一端用weak
4> assgin : 基本數據類型、枚舉、結構體(非OC對象)NSString、NSArray、NSDictionary 等等經常使用copy關鍵字,是因為他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary;
block 使用 copy 是從 MRC 遺留下來的“傳統”,在 MRC 中,方法內部的 block 是在棧區的,使用 copy 可以把它放到堆區.在 ARC 中寫不寫都行:對于 block 使用 copy 還是 strong 效果是一樣的,但寫上 copy 也無傷大雅,還能時刻提醒我們:編譯器自動對 block 進行了 copy 操作。如果不寫 copy ,該類的調用者有可能會忘記或者根本不知道“編譯器會自動對 block 進行了 copy 操作”,他們有可能會在調用之前自行拷貝屬性值。這種操作多余而低效。
下面做下解釋: copy 此特質所表達的所屬關系與 strong 類似。然而設置方法并不保留新值,而是將其“拷貝” (copy)。 當屬性類型為 NSString 時,經常用此特質來保護其封裝性,因為傳遞給設置方法的新值有可能指向一個 NSMutableString 類的實例。這個類是 NSString 的子類,表示一種可修改其值的字符串,此時若是不拷貝字符串,那么設置完屬性之后,字符串的值就可能會在對象不知情的情況下遭人更改。所以,這時就要拷貝一份“不可變” (immutable)的字符串,確保對象中的字符串值不會無意間變動。只要實現屬性所用的對象是“可變的” (mutable),就應該在設置新屬性值時拷貝一份。
用@property 聲明 NSString、NSArray、NSDictionary 經常使用 copy 關鍵字,是因為他們有對應的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary,他們之間可能進行賦值操作,為確保對象中的字符串值不會無意間變動,應該在設置新屬性值時拷貝一份。
2.屬性readwrite、readonly、assign、retain、copy、nonatomic各是什么作用,在哪種情況下用?
1.readwrite:修飾對象可讀可寫,會生成getter和setter方法
2.readonly:修飾對象僅可讀,只生成getter方法
3.assign:修飾基本數據類型(NSInteger,CGFloat)和C數據類型(int, float, double, char)
4.retain:修飾對象類型,指定強引用與strong一樣,引用計數+1
5.copy:深拷貝,源對象引用計數不變,副本對象引用計數+1,常用修飾字符串
- copy 與 retain 的區別
copy: 創建一個新的對象,新的對象引用計數加1,被copy對象的引用計數不變,改變新拷貝的對象時,被拷貝的對象不會發生改變,兩者無直接聯系
retain:創建一個指針,對象的引用計數加1,兩個指針同時指向同一對象,新舊指針都可以改變對象的值
retain屬性表示兩個對象地址相同(建立一個指針,指針拷貝),內容當然相同,這個對象的retain值+1。也就是說,retain 是指針拷貝,copy 是內容拷貝。6.nonatomic:如果該對象無需考慮多線程的情況,請加入這個屬性,這樣會讓編譯器少生成一些互斥加鎖代碼,不用耗費系統資源,可以提高效率。
- nonatomic和atomic對比
atomic:線程安全,需要消耗大量的資源
nonatomic:非線程安全,適合內存小的移動設備總結
關于nonatomic是線程不安全的,當有多個線程同時修改屬性name的值的時候,拿到的結果可能不是自己想要的,因為當屬性設置nonatomic的話是允許多個線程是可以同時修改name的值。
簡單來說atomic是串行,nonatomic是并行,但如果要真正實現防止多線程修改某屬性的值的時候,單單設atomic是不夠的,還需要更完善的防止手法
2、引用與指針有什么區別?
答 引用是給變量起一個別名 也就是一個變量有兩個名字 他們是同一塊空間 指針是分配一塊內存用來保存變量的地址 間接引用變量
15、OC中加號方法與減號的區別?
答 加號方法是類方法 可以用類名來調用 減號方法是實例方法 必須由類的實例來調用
16、如何修飾私有變量?
答 在OC中默認變量屬性都是有私有的 我們可以property關鍵字來修飾 以便可以不同過接口直接訪問
17、建一個工程用到最基本的兩個框架是什么?
答 cocoa Touch框架 Function框架
22、self.name = "object" name = "object"的區別
答: self.name 需要要合成屬性然后系統會默認生成set get方法 所以在賦值是會調用set方法,name = "object"則直接賦值
10.對于語句NSString *obj = [[NSData alloc] init]; obj在編譯時和運行時分別是什么類型的對象?
答:編譯時是NSString的類型;運行時是NSData類型的對象
1、引用與指針有什么區別?
引用就是給變量起一個別名,在使用的時候,直接用別名調用就可以了,引用最好初始化,因為引用為空,對象都不存在就更別提別名了,引用的內容一般也是固定的,所以相對來說比較安全。
指針想要使用變量的時候,是一種間接引用,一般要通過&或者*來達到效果。指針可以為空指針,因為只是指向空地址而已,可以任意改變,只要改指其他內存地址就可以了。
指針和引用的聯系與區別
★ 相同點:
- 都是地址的概念;
指針指向一塊內存,它的內容是所指內存的地址;引用是某塊內存的別名。★ 區別:
- 指針是一個實體,而引用僅是個別名;
- 引用使用時無需解引用(*),指針需要解引用;
- 引用只能在定義時被初始化一次,之后不可變;指針可變;
- 引用沒有 const,指針有 const;
- 引用不能為空,指針可以為空;
- “sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大小;
- 指針和引用的自增(++)運算意義不一樣;
8.從內存分配上看:程序為指針變量分配內存區域,而引用不需要分配內存區域。參考答案:
(1)當引用被創建時,它必須被初始化。而指針則可以在任何時候被初始化。
(2)一旦一個引用被初始化為指向一個對象,它就不能被改變為對另一個對象的引用。而指針則可以在任何時候指向另一個對象。
(3)不可能有NULL引用。必須確保引用是和一塊合法的存儲單元關聯。進一步解析:
指針和引用都是C++中的基本語法成份,它們既有聯系,也有不同之處。
它們都是地址的概念,其中指針指向一塊內存,它的內容是所指內存的地址;而引用是某塊內存的別名,具體來說,指針是一個變量的地址,引用是一個變量的別名。但它們的不同之處也很明顯,體現在以下方面:
指針是一個實體,而引用僅是個別名;
引用必須被初始化,指針不必;
引用只能在定義時被初始化一次,之后不可變;指針可以改變所指的對象;
可以有const指針,但是沒有const引用;
不存在指向空值的引用,但是存在指向空值的指針,即引用不能為空,指針可以為空;
“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大小;
指針和引用的自增(++)運算意義不一樣;
程序為指針變量分配內存區域,而引用不需要分配內存區域;
指針可以有多級,但是引用只能是一級,例如int **p是合法的,而 int &&a是不合法的;
指針和引用作為函數參數進行傳遞時也不同。用指針傳遞參數,可以實現對實參進行改變的目的;在將引用作為函數參數進行傳遞時,實質上傳遞的是實參本身,而不是實參的一個拷貝,因此對形參的修改其實是對實參的修改。
2、簡述struct和class的區別。
首先,討論這個問題應該僅從語法上討論,如果討論不同人之間編程風格上的差異,那這個問題是沒有答案的。畢竟不同的人偏好不同。
從語法上,在C++中(只討論C++中)。class和struct做類型定義時只有兩點區別:
(一)默認繼承權限。如果不明確指定,來自class的繼承按照private繼承處理,來自struct的繼承按照public繼承處理;
(二)成員的默認訪問權限。class的成員默認是private權限,struct默認是public權限。
除了這兩點,class和struct基本就是一個東西。語法上沒有任何其它區別。不能因為學過C就總覺得連C++中struct和class都區別很大,下面列舉的說明可能比較無聊,因為struct和class本來就是基本一樣的東西,無需多說。但這些說明可能有助于澄清一些常見的關于struct和class的錯誤認識:
(1)都可以有成員函數;包括各類構造函數,析構函數,重載的運算符,友元類,友元結構,友元函數,虛函數,純虛函數,靜態函數;
(2)都可以有一大堆public/private/protected修飾符在里邊;
(3)雖然這種風格不再被提倡,但語法上二者都可以使用大括號的方式初始化:Aa={1,2,3};不管A是個struct還是個class,前提是這個類/結構足夠簡單,比如所有的成員都是public的,所有的成員都是簡單類型,沒有顯式聲明的構造函數。
(4)都可以進行復雜的繼承甚至多重繼承,一個struct可以繼承自一個class,反之亦可;一個struct可以同時繼承5個class和5個struct,雖然這樣做不太好。
(5)如果說class的設計需要注意OO的原則和風格,那么沒任何理由說設計struct就不需要注意。
(6)再次說明,以上所有說法都是指在C++語言中,至于在C里的情況,C里是根本沒有“class”,而C的struct從根本上也只是個包裝數據的語法機制。
最后,作為語言的兩個關鍵字,除去定義類型時有上述區別之外,另外還有一點點:“class”這個關鍵字還用于定義模板參數,就像“typename”。但關鍵字“struct”不用于定義模板參數。
26、私有屬性和私有方法
/*
1.寫一個私有屬性
不能被外界訪問的,并且在外面也不會有提示,做到真正的私有。
在@interface大括號里面就不要寫聲明,而是在implementation里面加上大括號,在大括號里面寫屬性的聲明。
那么這個屬性就是真正的私有,就只能在本類中訪問, 外面不能訪問,并且連提示都不會有。
此時這個屬性,用任何訪問修飾符修飾,都是不起作用的,默認這個屬性就是私有的。
2.如果我們寫一個方法,只想讓他在本類中調用,而不能在外面調用。
那么這個方法就不要寫聲明,直接寫實現。
3.私有屬性和私有方法,都是可以繼承給子類的。只不過子類里面是不能訪問從父類繼承過來的的私有屬性和私有方法的。
*/
/*
1.方法的重寫
如果子類的從父類繼承過來的方法,他的實現和父類不同,他有自己的實現,那么這個從父類繼承過來的方法,就要重寫。
2.重寫的語法:
就是在子類中,重新的實現一下這個從父類繼承過來需要被重寫的方法。
*/
22、淺復制和深復制的區別?
淺復制和深復制的區別:淺拷貝只是增加了一個指針指向已經存在的內存,兩個指針指向同一快內存,就相當于本來一個人有自己的名字A,然后那,又給他取了個名字B,但是你在叫A、B的時候,都是同一個人來答復;而深拷貝就是增加一個指針并且申請一個新的內存,使這個增加的指針指向這個新的內存,就相當于本來一個人有自己的名字A,然后那,他有一個孿生兄弟名字叫做B,所以你叫A、B的時候是不同的人答復。
針對指針型對象的拷貝,有淺復制和深復制兩種。
淺復制:將原始對象的指針值復制到副本中,即指針拷貝,原始對象和副本共享引用的數據;相當于創建了一個文件的快捷方式。
深復制:復制原始對象指針所引用的數據,并將其賦給副本對象,即內容拷貝,相當于創建了一份新的文件。
例如,當我們為一個類的屬性添加copy關鍵字時,那么對這個屬性賦值時(即:調用setter方法),就會執行深拷貝操作。當我們把屬性關鍵字改為strong或者weak時,那么對這個屬性賦值時,就會執行淺拷貝(只拷貝指針地址)。
NSString *string = @"test";NSString *string1 = [string copy];NSString *string2 = [string mutableCopy];copy->復制指針(創建一個指針指向原始的內存地址)
mutableCopy->復制指針及內容(創建新的內存地址)
string:[0x100001058]test
string1:[0x100001058]test
string2:[0x100201600]test
23、類別的作用?繼承和類別在實現中有何區別?
category 可以在不獲悉,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。// category:類、種類
并且如果類別和原來類中的方法產生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優先級。//類別跟類的優先級
類別主要有3個作用:
(1)將類的實現分散到多個不同文件或多個不同框架中。
(2)創建對私有方法的前向引用。
(3)向對象添加非正式協議。
繼承可以增加,修改或者刪除方法,并且可以增加屬性。//非正式協議:是使用類別category來實現,非正式協議是NSObject的一個類別,這樣任何類的對象都可以作為委托對象來使用,它可以列出對象能夠執行的所有方法,這樣用來實現委托, 我們可以使用選擇器來判斷該非正式協議中是否有這個方法。正式協議:是一個命名的方法列表,與非正式協議相比不同的是,它要求顯示的采用協議,采用協議的方法是在類的@interface聲明中列出協議的名稱,此時,實現協議的類應該遵守協議,承諾實現協議中的所有方法。
1、Object-C有多繼承嗎?沒有的話用什么代替?
cocoa 中所有的類都是NSObject 的子類 多繼承在這里是用protocol 委托代理 來實現的 你不用去考慮繁瑣的多繼承 ,虛基類的概念. ood的多態特性 在 obj-c 中通過委托來實現.
2、Object-C有私有方法嗎?私有變量呢?
objective-c – 類里面的方法只有兩種, 靜態方法和實例方法. 這似乎就不是完整的面向對象了,按照OO的原則就是一個對象只暴露有用的東西. 如果沒有了私有方法的話, 對于一些小范圍的代碼重用就不那么順手了. 在類里面聲名一個私有方法
@interface Controller : NSObject { NSString *something; } + (void)thisIsAStaticMethod; – (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) - (void)thisIsAPrivateMethod;
@end
@private可以用來修飾私有變量
在Objective--‐C中,所有實例變量默認都是私有的,所有實例方法默認都是公有的
3、關鍵字const什么含義?
const意味著”只讀”,下面的聲明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數。第三個意味著a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最后一個意味著a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。結論:
?; 關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清 理的。)
?; 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
?; 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。
欲阻止一個變量被改變,可以使用 const 關鍵字。在定義該 const 變量時,通常需要對它進行初 始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為 const,也可以指定指針所指的數據為 const,或二者同時指 定為 const;
(3)在一個函數聲明中,const 可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
(4)對于類的成員函數,若指定其為 const 類型,則表明其是一個常函數,不能修改類的成員變量;
(5)對于類的成員函數,有時候必須指定其返回值為 const 類型,以使得其返回值不為“左值”。
4、關鍵字volatile有什么含義?并給出三個不同例子?
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
? 并行設備的硬件寄存器(如:狀態寄存器)
? 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
? 多線程應用中被幾個任務共享的變量
? 一個參數既可以是const還可以是volatile嗎?解釋為什么。 ? 一個指針可以是volatile 嗎?解釋為什么。
4.如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關鍵字的 setter
若想令自己所寫的對象具有拷貝功能,則需實現 NSCopying 協議。如果自定義的對象分為可變版本與不可變版本,那么就要同時實現 NSCopying 與 NSMutableCopying 協議。
具體步驟:
1.需聲明該類遵從 NSCopying 協議
2.實現 NSCopying 協議。該協議只有一個方法:
-(id)copyWithZone:(NSZone *)zone;
注意:一提到讓自己的類用 copy 修飾符,我們總是想覆寫copy方法,其實真正需要實現的卻是 “copyWithZone” 方法。
14.建一個工程用到最基本的兩個框架是什么?
Foundation和UIKit框架
i++和++i的區別
如果有表達式 a = i++ 它等價于 a = i ; i = i + 1;
如果有表達式 a = ++i 它等價于 i = i + 1; a = i;
兩者的區別是:
- i++:是先賦值,然后再自增;
- ++i是先自增,后賦值
&和&&的區別
一、簡要說明
按位與:a&b是把a和b都轉換成二進制數然后再進行與的運算;
邏輯與:a&&b就是當且僅當兩個操作數均為 true時,其結果才為 true;只要有一個為零,a&&b就為零。
例如:
a&b 9&8
1001
1000
結果是1000
a&&b 9&&8 結果是1
&對每一個都判斷;
&&只要前面是false就輸出false,而不繼續判斷后面了二、詳細解釋
有關&和&&的詳細解釋如下:
&,雙目運算符:將兩個表達式的值按二進制位展開,對應的位(bit)按值進行“與”運算,結果保留在該位上…
比如170&204
對應二進制就是
10101010B
&11001100B
=10001000B…
170&204=136…
該位只要有一個值為0結果為0,否則結果為1。
如果兩數位數不同,則較短數高位補零,再運算,比如char a=100;int b=260;
a&b實際是0000 0000 0110 0100&0000 0001 0000 0100.其結果為int型0000 0000 000 0100即4…
&&:雙目運算符,計算兩個表達式同時成立的“真值”(同時成立真值為真否則為假)
邏輯真值有兩種,1為真,0為假,但在運算時用非零表示真,0表示假…
即:數值->邏輯真值--非0為真,0為假/邏輯真值->數值--真為1,假為0…
例如:char a=1,b=0,c=-1;那么a真b假c真。a&&b和c&&b為假值為0,a&&c為真值為1
3.OC中加好方法和減號方法的區別
+的方法,其實就是類方法了,通過類名調用。
-的話,實咧方法,類的實列(對象)才可以調用的。
4.類別的作用,繼承與類別在實現中有何區別
類別歧視就是情況下往里面添加新的方法,只能添加,不能刪除修改,繼承可以增加,修改或者刪除方法,并且可以增加屬性。
1、Object-c的類可以多重繼承么?可以實現多個接口么?Category是什么?重寫一個類的方式用繼承好還是分類好?為什么?
Object-c的類不可以多重繼承;可以實現多個接口,通過實現多個接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關系。
2、#import 跟#include 又什么區別,@class呢, #import<> 跟 #import”"又什么區別?
.#import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字,使用#import頭文件會自動只導入一次,不會重復導入,相當于#include和#pragma once;
@class告訴編譯器某個類的聲明,當執行時,才去查看類的實現文件,可以解決頭文件的相互包含;
.#import<>用來包含系統的頭文件,#import””用來包含用戶頭文件。
3、屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用?
readwrite 是可讀可寫特性;需要生成getter方法和setter方法時
readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變
assign 是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain 表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy 表示拷貝特性,setter方法將傳入對象復制一份;需要完全一份新的變量時。
nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作,
atomic表示多線程安全,一般使用nonatomic
4.寫一個setter方法用于完成@property (nonatomic,retain)NSString *name,寫一個setter方法用于完成@property(nonatomic,copy)NSString *name
[cpp] view plain copy print?在CODE上查看代碼片派生到我的代碼片
- (void)setName:(NSString *) str
{
[str retain];
[name release];
name = str;
}
- (void)setName:(NSString *)str
{
id t = [str copy];
[name release];
name = t;
}
22、淺拷貝和深拷貝區別?
在有指針的情況下,淺拷貝只是增加了一個指針指向已經存在的內存,而深拷貝就是增加一個指針并且申請一個新的內存,使這個增加的指針指向這個新的內存,采用深拷貝的情況下,釋放內存的時候就不會出現在淺拷貝時重復釋放同一內存的錯 誤。
6、當A類中的某個方法執行到某處時,這時想在B類中執行某個方法,如何做?舉出一個方法說明。
答:可以用委托方法來實現,在A類中初始化一個成員讓他指向B類就可以調用B的方法了。
7、int retVal = UIApplicationMain(argh,argue,nil,nil);是什么意思?
對UIApplication對象進行了初始化,這個方法除了argc 和 argv 參數外,另外這個函數還有2個兩個字符串參數來識別UIApplication類和UIApplication代理類,在這里默認是2個nil,第一個參數為nil就默認把UIApplication類作為缺省值進行初始化,可以在這里不填nil而是使用自己定義的UIApplication子類。至于第二個參數nil就設置為nil就把模板生成的HelloWorldAppdelegate類作為默認值。
4、建一個工程用到最基本的兩個框架是什么?
cocoa Touch框架 Function框架
2 引用與指針有什么區別?
答:
引用是給變量起一個別名,也就是一個變量有兩個名字,他們是同一塊空間。
指針是分配一塊內存用來保存變量的地址,間接引用變量。
1、請說明一下在objective_c里定義屬性copy與assign的區別
assign:指定setter方法用簡單的賦值,這是默認操作。你可以對標量類型(如int)使用這個屬性。你可以想象一個float,它不是一個對象,所以它不能retain、copy。
assign: 簡單賦值,不更改索引計數(Reference Counting).使用assign: 對基礎數據類型 (NSInteger)和C數據類型(int, float, double, char,等)
copy:指定應該使用對象的副本(深度復制),前一個值發送一條release消息。基本上像retain,但是沒有增加引用計數,是分配一塊新的內存來放置它。copy是創建一個新對象,retain是創建一個指針,引用對象計數加1。
copy: 建立一個索引計數為1的對象,然后釋放舊對象,copy是創建一個新對象,retain是創建一個指針,引用對象計數加1。
retain:指定retain應該在后面的對象上調用,前一個值發送一條release消息。你可以想象一個NSString實例,它是一個對象,而且你可能想要retain它。
retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1 ,使用retain: 對其他NSObject和其子類 ,retain,是說明該屬性在賦值的時候,先release之前的值,然后再賦新值給屬性,引用再加1。
readonly:將只生成getter方法而不生成setter方法(getter方法沒有get前綴)。
readwrite:默認屬性,將生成不帶額外參數的getter和setter方法(setter方法只有一個參數)。
atomic:對于對象的默認屬性,就是setter/getter生成的方法是一個原子操作。如果有多個線程同時調用setter的話,不會出現某一個線程執行setter全部語句之前,另一個線程開始執行setter的情況,相關于方法頭尾加了鎖一樣。
nonatomic:不保證setter/getter的原子性,多線程情況下數據可能會有問題。nonatomic,非原子性訪問,不加同步,多線程并發訪問會提高性能。先釋放原先變量,再將新變量 retain然后賦值;
注意,如果不加此屬性,則默認是兩個訪問方法都為原子型事務訪問。
2、什么時候使用NSMutableArray,什么時候使用NSArray?
NSArray是靜態的數組,就是它所指向的內容是不可改變的,它指向一段內存區域,一旦初始化,不能通過它對該內存區域的數據進行修改操作,但是它可以讀數據。
NSMutableArray是動態的是NSArray的子類,可以對所指向的內存區域內容進行更改,并可以增加數組內容
NSArray和NSmutableArray的第一個數據的下標為0。