1. xcode 4.3.3以後 NSAutoreleasePool 的用法發生改變,由
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
….
[pool drain];
變爲:
@autoreleasepool {
….
}
2. 在objc中也存在static 關鍵字,作用與Java中的static 相同即, 內存中只有一份。For example:
類Maths_, 其中有一個屬性是 static int number(初始化爲 0 ), 類方法使number++,然後new了10個Maths_類, 每個類都調用類方法使number++,看最後結果。
正常,每個類的number屬性是獨立的,若加上static 因爲內存中只有一份,所以10個類操作的都是同一個number.
3. self 關鍵字作用同Java中的this相同,即誰調用誰就是self/this.
4. 在方法中如果用了new/[~ alloc]分配內存,就要在方法的結尾手動的釋(release)內存.
5. objc中的繼承我個人稱之爲向上繼承,即,子類可以向上繼承所有父類,父類的父類的屬性和方法。
6. @class A和#import "A.h"兩種方法注入類時 ,有什麼區別?
答:@class只是告訴當前類, A是一個類,並不用處理。(效率高,因爲只注入類名)
#import "A.h" 是把整個A類注入到當前類中。(相對是@class效率低,因爲把整個類注入)
那麼什麼時候用@class A ,什麼時候用#import "A.h"呢?
答:當前類沒有調用任何A類的方法和屬性的時候,無需用#import.
繼承的時候,必須用#import
7. 如何在當前類中,釋放繼承的類所佔的內存:
答: 重寫dealloc方法
- (void) dealloc {
[super dealloc];
// [~ release];
...
}
8. objc特徵 :多態,動態類型和動態綁定
多態:存在繼承關係的幾個類,在定義的時候,都用到根類的名字,不過在運行時,會根據具體的類型,調用不同子類的方法。
動態類型:id 可以接受任何的數據類型,缺點就是容易發生運行時異常。
id定義的時候,不用加星號。 id a = b;
運行階段,才能確定的類型。
動態綁定:程序運行過程中,一些id類型的類,會根據實際情況,進行響應的類分配。
運行階段,才能確定調用的方法。
9. 如何定義一個objc的字符串?
基本上objc的東西都帶ns前綴。
NSString *str = @"hello world!"
10. 處理動態類型的一些方法有哪些?
首先要知道獲得類實例(class-object)的方法,例如class a , [a class];
下面是一些方法:
(1) 對象是不是class-object或其子類的成員- ( BOOL) isKindOfClass: class-object
(2) 對象是不是class-object的成員? - (BOOL) isMemberOfClass: class-object
(3) 對象是否包含selector所指定的成員? - (BOOL) respondsToSelector: @selector
(4) 指定的類實例是否包含selector所指定的方法? + (BOOL) instancesRespondToSelector: @selector
(5) 對象是指定類的子類嗎? + (BOOL) isSubclassOfClass: class-object
(6) 調用selector指定的方法? - (id) performSelector: @selector
(7) 同6 - (id) performSelector: selector withObject: object
(8) -(id) performSelector: @selector withObject:object withObject:object
isKindOfClass and isMemberOfClass的區別?答:isKindOfClass檢測繼承層次中的關係,isMemberOfClass檢測直接成員的關係。
11. objc 中也存在異常處理機制, try..catch…
格式如下:
@try {
}
@catch(NSException *exception) {
}
12. 如何初始化NSArray?
答:NSArray *arrs = [[NSArray alloc] initWithObjects: @"a", @"b", @"c", nil];
or
NSArray *arrs = [NSArray arrayWithObjects:@"a", @"b", nil];
13. 編寫初始化方法的時候,一般都要在首行編寫:
self = [super init]; // 即調用父類的初始化方法,不一行是init的寫法。
然後判斷是否初始化成功了:
if ( self ) {
}
14. objc中也存在作用域修飾關鍵字,不過只有對實例變量的修飾:
@propected (默認)
可以被任何子類訪問
@private
只能被自己訪問,不能被子類訪問
@public
能被其他類或模塊訪問,此修飾之後,還能用->的方式訪問修飾的變量,根C++中相同。
@package
@package is similar to internal for .NET. It means the member is accessible only from the framework in which it is defined.
Note: In 32-bit it acts like @public.
舉例寫法:
@interface Person : NSObject {
@private
int handNum;
@propected
int headNum;
}
@end
15. objc中定義全局變量的命名規則。
舉例:int gMoveNumber = 0;
前面都要加一個 g 代表是全局變量
16. 定義全局變量2中方法。
(1)在所有類,方法外,直接定義 int gCount;
(2)在方法裏面,用關鍵字extern修飾。
- (void) setABC : (int) val {
// 定義全局變量
// extern int gCount = 0; 這種寫法是錯誤的 extern定義的變量不能直接賦值
extern int gCount;
gCount = 1;
}
17. 在objc中,應該儘量少用extern即外部/全局變量,應該用static來代替extern.
爲什麼要這樣? 因爲外面變量可以被其他任何文件訪問到,而static 可以編寫相應的方法進行訪問,在安全性上比全局變量好。
18. auto關鍵字,這個關鍵字幾乎天天看到,只不過“隱形”了。例如
int count < == > auto int count;
語義就是,進入方法,分配內存,結束方法,釋放內存。
19. 常量的定義關鍵字 const
const int a = 100;
20. volatile關鍵字的作用。
與const相反,定義變量是可變的。
爲什麼要用呢?
*outPort = 'O' ;
*outPort = 'N' ;
正常的情況下,編譯器發現outPort被重複賦值,就會把第一次outPort從編譯器中除去。
如果定義:
volatile char *outPort;之後,就不會在編譯環境中除去了。這在特殊環境中有作用。
21. 枚舉數據類型 enum 如何定義及作用?
答:
定義:
enum month {
january = 1,
february,
march,
april,
may,
june,
july,
august,
september,
october,
november,
december
};
作用:
歸類,把一組有意義的詞語封裝起來。
22. objc中typedef的作用是什麼?
答:顧名思義: typedef = type(類型) + define(定義)
爲數據類型,另外指派一個名稱。
作用是增加了變量定義的可讀性。
例如:
typedef int Counter;
Counter num = 0;
23. 通常typedef 與enum連用。如下:
typedef enum {
january = 1,
february
} MONTH;
// typedef enum { january =1, february } Month;
這樣與enum Month {…} 有什麼區別呢?
答: 這樣 在定義變量的時候就不用enum了
Month thisMonth = february;
enum Month thisMonth = february;
24. 擴展新類方法的方式有哪些?
答:(1)繼承 (2)重載 (3)分類 (4)協議
25. 分類擴展的方式舉例
#import "Fraction.h"
@interface Fraction (MathOps)
- (void) methodA;
- (void) methodB;
@end
@implementation Fraction (MathOps)
- (void) methodA {
}
/* 分類中的方法可以不實現
- (void) methodB {
}
*/
@end
26. 使用分類時的注意事項。
(1)使用分類時,不能添加實例變量。
(2) 在分類中定義方法時,注意不能與原類方法重名,不然原方法將被覆蓋。
(3) 分類中的方法,可以不實現。
27. objc的協議。
(1)格式:
@protocol XXX
- (void) methodX;
@end
(2)本質,定義了一系列沒有實現的方法。
(3)協議的使用
@interface Fraction <XXX /* , ??? 多個協議用‘,’隔開*/>
@end
@implementation Fraction
// XXX中的方法不是必須實現的,如果沒有實現,xcode會產生警告
- (void) methodX {
NSLog(@"implement the method which in @protocol XXX");
}
@end
28. 父子類協議示意圖
父 ----<遵守協議a>
| |
| |
|
子 <-----
29. 問,我用了一個自己寫的協議XY, 但是我沒有實現協議中的方法,這樣編譯器就會給我發一則警告,如何讓它不警告。
代碼如下:(協議應該定義在單獨的文件中)
@protocol XY
- (void) xyMethod;
@end
/////////////////////
@interface Fraction <XY>
@end
@implementation Fraction
// 不實現xyMethod方法
@end
==== 若修改代碼 ====
@protocol XY
@optional
- (void) xyMethod;
@end
加上@optional關鍵字 就不會產生警告了。
30. 如何檢查一個對象是否遵循某項協議
- (BOOL) conformsToProtocol: 方法
例如:[currentObject conformsToProtocol: @protocol (Drawing)]
31. 什麼是合成對象?
一個類包含其他類的一個或多個對象。 這個類實例化出來的對象就叫做合成對象。
例如:
@interface Square : NSObject {
Rectangle *rect;
}
@end
32. 簡單說說預處理程序?
& 幾點理解:
(1)定義‘特殊常量’
(2)定義表達式和任何東西
(3)類似於程序中的全局文本替換
& 定義預定義名稱的時候,一種寫法是全都用大寫,另一個是名稱前面加k,例如:
#define TURE 1 #define kTure 1
&#define 語句的基本用途之一就是給符號名稱指派程序常量,例如:
#define TURE 1
& 定義表達式,例如:
#define TWO_PI 2.0 * 3.141592653
& 爲什麼預定義後面不能寫';'?
答:因爲預定義的本質是文本替換,如果最後加上了分號,分號也將被替換到程序中。例如:
#define PI 3.1415926 ;
return PI * r; == > return 3.1415926; * r;
& 看如下預定義是否正確,若錯誤,錯在哪裏?
#define IS_LEAP_YEAR year % 4 == 0 && year % 100 != 0
|| year % 400 == 0
答:錯誤,預定時語句,如果過長,寫在兩行時,第一行的結尾處要添加 ‘\’告知編譯器還有後續
內容。 修改如下:
#define IS_LEAP_YEAR year % 4 == 0 && year % 100 != 0 \
|| year % 400 == 0
& 預定義語句可以帶參數,如下:
#define IS_LEAP_YEAR(y) y % 4 == 0 && y % 100 !=0 \
|| y % 400 == 0
*** 注意,這種寫法有陷阱存在,正在下面有提到. 正確的寫法是 #define IS_LEAP_YEAR(y) (y)%4 ==0 && (y)%100 != 0 || (y) %400 ==0
使用預定義的時候,寫法如下:
int year = 2012;
if (IS_LEAP_YEAR(year)) {
NSLog(@"2012 year is leap year! ");
}
這裏有一點需要注意:帶有參數的預定義,預定義名稱與參數列表的左半邊括號不能有空格。例如:
#define IS_LEAP_YEAR (y) .. 就是錯誤的寫法。爲什麼呢??
答:因爲預定義時文本替換,如果有空格,就會把 IS_LEAP_YEAR替換成 “(y) y % 4 == 0 && y %
100 !=0 \ || y % 400 == 0 ”
& 預定義也叫宏定義,宏定義存在一個‘陷阱’, 如下:
#define kSquare(x) x * x
int v = 100;
return kSquare(v + 1);
這裏,通常人們會認爲kSquare(v + 1) 得到的結果時 (v + 1) * (v + 1),可時宏定義時文本替換,所以
看替換的結果,
x * x == > v + 1 * v + 1 ;
解決辦法:
#define kSquare(x) ( (x) * (x))
這樣替換的結果爲 ((v + 1) * (v + 1))
& 定義一個宏,判斷某字母是否是小寫字母?
答:
#define IS_LOWER_CASE(x) ( ( (x) > 'a' ) && ( (x) < 'z') )
& 定義一個預定義,把小寫字母轉換成大寫字母?
答:
#define TO_UPPER(x) ( IS_LOWER_CASE(x) ? ((x) - 'a' + 'A') : (x) )
& 宏定義中的 #
若果在定義宏的時候,在參數前放置# ,則結果不是替換,是把宏參數轉成c風格的字符串。如下:
#define str(s) #s
str(testing);的結果爲: "testing"
另一個例子:
#define printInt(var) printf(#var " = %i\n", var)
int count = 100;
printInt(count) == > printf("count" "= %i\n", count);
& 宏定義中的 ##
答:##在宏定義中是連接符作用。如下:
#define printf(n) printf(x ## n )
int n = 100;
printf(n) == > printf(x100)
33. 簡單說說條件編譯?
& objc中預處理程序提供了一項名爲條件編譯(conditional compilation)的功能。
& 條件編譯的用途是什麼?
條件編譯通常用於創建可以在不同計算機系統上編譯運行的程序。它還經常用來開關程序中的各種語
句,例如:用來輸出變量值或跟蹤程序執行流程的調試語句。
& 條件編譯的關鍵子有哪些?
答:#ifdef , #endif, #else , #elif , #ifndef. 舉例如下:
#ifdef MAC_OS_X
# define DATADIR "/uxn1/data"
#else
# define DATADIR "\usr\data"
#endif
& 在程序中,如何應用呢?
答:[預留]
34. 什麼是框架, 及其作用?舉幾個常用的框架。
答:框架是由許多類,方法,函數,文檔按照一定的邏輯組織起來的集合。以便使研發程序變得更容易。
— Foundation框架是基礎框架,主要是允許用一些基礎對象,如數字和字符串。還允許使用對象集合 如,數組,字典和集合,還由一些日期處理,自動化內存管理,文件系統等
— Application Kit 框架:用來開發交互式圖形應用程序。
Cocoa = Foundation + Application Kit
Cocoa Touch = Foundation + UIKit
35. Foundation框架提供的基礎對象是什麼?
答:數字,字符串, 集合。
集合包括:數組, 字典, 集。
36. NSNumber 是對象,還是typedef? 它可以封裝哪些基礎類型?
答:NSNumber 是對象,他可以封裝int float double BOOL char long. 他們的初始化方法都是對應的。
[NSNumber numberWith…];
例如:int類型就是NSNumber *myInt = [NSNumber numberWithInteger: 100];
37. Xcode 4.3.3 以後的release爲何不可用了??
答:Xcode4 ARC(Automatic Reference Counting)有所變動,Xcode4.3自動在compile time處理release,也就是,你寫alloc,compiler自動在code gen時加入相對的release,這作法是爲了解決iOS仰賴程式設計師(app designer)負責memory management的問題(也就是你alloc後必需自己release這問題)。
不想用ARC的話,在Xcode4.3 File/New/New project及Choose a template for your new project選定template後的Choose options for your new project畫面,"不勾選"UseAutomatic Reference Counting,這樣你就可在你的project中試用alloc/release了。
38. #define 與 typedef 如何區分?
答:& define 定義,文本替代。
#define PI 3.14
& typedef 類型定義,顧名思義,就重新定義類型的。
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;
39. NSLog(@"%2i") 與 NSLog(@"%i") 的區別是什麼?
答:2i,不足2位的值不是補零,就是補空格
40. NSArray不能存放簡單類型,只能存放對象。
41. C語言本身提供數組與Foundation提供的數組,你用哪個?爲什麼?
答: C語言本身提供的數組是最底層的數組,雖然操作複雜,但是效率高.
Foundation提供的數組,操作相對容易,但是效率相對比C語言本身低。
42. 數組的一種快速循環的方法是什麼?
NSArray *arr = [NSArray arrayWithObjects:@"sdf",@"dfdsa", nil];
for (NSString* temp in arr) {
NSLog(@"%@", temp);
}
43. 數組的排序問題,也是面試、工作長問的問題?
答:
44. 分別說出NSArray 和 NSMutableArray的5個常用方法。
答:& NSArray : [NSArray arrayWithObjects: obj1, obj2, obj3…, nil]
[array1 containsObject: obj]
[array1 objectAtIndex: i]
[array1 count]
[array1 indexOfObject: obj];
& NSMutableArray: addObject:obj
insertObject:index
arrayWithCapacity: size
replaceObjectAtIndex: i withObject:obj
removeObject: obj
removeObjectAtIndex: i
45. 詞典對象,和鍵關聯的值可以是任何對象,但他們不能爲nil.
46. 用for( in ) 遍歷字典的時候,例如:
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
@"HELLO WORLD",@"name" ,
nil];
for (NSString *key in dic) {
NSLog(@"%@",[dic objectForKey:key]);
}
從字典遍歷出來的是key值,然後通過key值,取出value.
48. NSSet 和NSMutableSet裏面如果存放了相同的對象,則會自動刪除重複的。 如果要保持重複的,那麼用NSCountedSet。
49. 兩個集合如何求交集和並集?
答:& 舉例如下:
NSMutableSet *set1 = [NSMutableSet setWithObjects:@"1", @"2", @"3", nil];
NSMutableSet *set2 = [NSMutableSet setWithObjects:@"1", @"4", @"5", nil];
[set1 unionSet: set2];
NSLog(@"%@", set1);
& 交集: 可以通過 BOOL flag = [ set1 intersectsSet: set2] ; 判斷是否存在交集. 如果有. 循環倆個Set 進行比較.
50. NSCountedSet的本質?
答:NSCountedSet 並不是存儲相同對象的兩份,而是由幾個計數器,專門計算每個對象存儲的數量。
countForObject專門計算每個對象的數量。
51. xcode 4.3.3以後的內存管理髮生了什麼改變?例如:[obj retainCount]; [obj retain]; [obj release];都不可
用了。
答: 同標籤 37.
52. 正是協議與非正式協議的區別?
答:正是協議的方法必須全部實現,非正是協議的方法不必全部實現。
53. 在@interface中,不能直接賦值,如下是錯誤的:
@interface a : NSObject {
// int a = 100;
int a; // 正確的寫法
}
@end
54. 全局變量 和 extern的使用舉例 ?
答: 先看例子:
蒼井空.h 文件:
#import <Foundation/Foundation.h>
int gCount;
@interface 蒼井空 : NSObject
@end
孫悟空.m文件中的方法:
@implement 孫悟空
- (void) use蒼井空 {
// 這裏要使用 蒼井空.h中的 gCount
1.要告訴編譯器,我要用一個全局變量.
extern int gCount;
2.就可以正常的應用全局變量了
gCount = 1;
}
@end