new 是c++中的操做符,malloc是c 中的一個函數css
new 不止是分配內存,並且會調用類的構造函數,同理delete會調用類的析構函數,而malloc則只分配內存,不會進行初始化類成員的工做,一樣free也不會調用析構函數ios
內存泄漏對於malloc或者new均可以檢查出來的,區別在於new能夠指明是那個文件的那一行, 而malloc沒有這些信息。c++
new 和 malloc效率比較面試
new能夠認爲是malloc加構造函數的執行。objective-c
new出來的指針是直接帶類型信息的。編程
SEL就是對方法的一種包裝。包裝的SEL類型數據它對應相應的方法地址,找到方法地址就能夠調用方法。在內存中每一個類的方法都存儲在類對象中,每一個方法都有一個與之對應的SEL類型的數據,根據一個SEL數據就能夠找到對應的方法地址,進而調用方法。api
SEL s1 = @selector(test1); // 將test1方法包裝成SEL對象 數組
SEL s2 = NSSelectorFromString(@"test1"); // 將一個字符串方法轉換成爲SEL對象安全
調用方法有兩種方式:多線程
1.直接經過方法名來調用 [person text]
2.間接的經過SEL數據來調用 SEL aaa=@selector(text); [person performSelector:aaa];
繼承:繼承是從已有類獲得繼承信息建立新類的過程。提供繼承信息的類被稱爲父類(超類、基類);獲得繼承信息的類被稱爲子類(派生類)。 繼承讓變化中的軟件系統有了必定的延續性,同時繼承也是封裝程序中可變因素的重要手段。
封裝:封裝是把數據和操做數據的方法綁定起來,對數據的訪問只能經過已定義的接口。咱們在類中編寫的方法就是對實現細節的一種封裝;咱們編寫一個類就是對數據和數據操做的封裝。能夠說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。
多態性:多態性是指容許不一樣子類型的對象對同一消息做出不一樣的響應。簡單的說就是用一樣的對象引用調用一樣的方法可是作了不一樣的事情。多態性分爲編譯時的多態性和運行時的多態性。方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。運行時的多態是面向對象最精髓的東西,要實現多態須要作兩件事:1. 方法重寫(子類繼承父類並重寫父類中已有的或抽象的方法);2. 對象造型(用父類型引用引用子類型對象,這樣一樣的引用調用一樣的方法就會根據子類對象的不一樣而表現出不一樣的行爲)。
抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行爲抽象兩方面。抽象只關注對象有哪些屬性和行爲,並不關注這些行爲的細節是什麼。
主要是將數據類型的肯定由編譯時,推遲到了運行時。這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來講, 運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。
多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。
意思就是假設生物類(life)都擁有一個相同的方法-eat;那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。也就是不一樣的對象以本身的方式響應了相同的消 息(響應了eat這個選擇器)。所以也能夠說,運行時機制是多態的基礎.
KVC(Key-Value-Coding):是鍵值編碼, 一個對象在調用setValue的時候,
檢查是否存在相應key的set方法,存在就調用set方法。
set方法不存在,就查找_key的成員變量是否存在,存在就直接賦值。
若是_key沒找到,就查找相同名稱的key,存在就賦值。
Delegate: 一般發送者和接收者的關係是直接的一對一的關係。
代理的目的是改變或傳遞控制鏈。容許一個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。
能夠減小框架複雜度。消息的發送者(sender)告知接收者(receiver)某個事件將要發生,delegate贊成然而後發送者響應事件,delegate機制使得接收者能夠改變發送者的行爲。
Notification: 觀察者模式, 一般發送者和接收者的關係是間接的多對多關係。 消息的發送者告知接收者事件已經發生或者將要發送,僅此而已,接收者並不能反過來影響發送者的行爲。
區別
淺複製(copy):只複製指向對象的指針,而不復制引用對象自己。
深複製(mutableCopy):複製引用對象自己。深複製就好理解了,內存中存在了兩份獨立對象自己, 當修改A時,A_copy不變。
變量的做用域不一樣。
優勢:1.Cateogies 2.Posing 3.動態識別 4.指標計算 5.彈性訊息傳遞 6.不是一個過分複雜的C衍生語言 7.Objective-C與C++可混合編程
缺點:1.不支持命名空間 2.不支持運算符重載 3.不支持多重繼承 4.使用動態運行時類型,全部的方法都是函數調用,因此不少編譯時優化方法都用不到。(如內聯函數等),性能低劣。
謂詞就是經過NSPredicate給定的邏輯條件做爲約束條件,完成對數據的篩選。
//定義謂詞對象,謂詞對象中包含了過濾條件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age<%d",30];
//使用謂詞條件過濾數組中的元素,過濾以後返回查詢的結果
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
//可使用&&進行多條件過濾
predicate = [NSPredicate predicateWithFormat:@"name='1' && age>40"];
array = [persons filteredArrayUsingPredicate:predicate];
//包含語句的使用
predicate = [NSPredicate predicateWithFormat:@"self.name IN {'1','2','4'} || self.age IN{30,40}"];
//指定字符開頭和指定字符結尾,是否包含指定字符
//name以a開頭的
predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'a'"];
//name以ba結尾的
predicate = [NSPredicate predicateWithFormat:@"name ENDSWITH 'ba'"];
//name中包含字符a的
predicate = [NSPredicate predicateWithFormat:@"name CONTAINS 'a'"];
//like進行匹配多個字符
//name中只要有s字符就知足條件
predicate = [NSPredicate predicateWithFormat:@"name like 's'"];
//?表明一個字符,下面的查詢條件是:name中第二個字符是s的
predicate = [NSPredicate predicateWithFormat:@"name like '?s'"];
處理.m能夠識別c和oc,.mm能夠識別c c++ oc 可是cpp只能用c/c++
NSNull:NSNull是繼承於NSObject的類型。它是很特殊的類,它表示是空,什麼也不存儲,可是它倒是對象,只是一個佔位對象。使用場景就不同了,好比說服務端接口中讓咱們在值爲空時,傳空。NSDictionry *parameters = @{@"arg1" : @"value1",@"arg2" : arg2.isEmpty ? [NSNull null] : arg2};
NULL、nil、Nil這三者對於Objective-C中值是同樣的,都是(void *)0,那麼爲何要區分呢?又與NSNull之間有什麼區別:
向nil發送消息是徹底有效的——只是在運行時不會有任何做用。
若是一個方法返回值是一個對象,那麼發送給nil的消息將返回0(nil)
若是方法返回值爲指針類型,其指針大小爲小於或者等於sizeof(void*),float,double,long double 或者long long的整型標量,發送給nil的消息將返回0。
-若是方法返回值爲結構體,正如在《Mac OS X ABI 函數調用指南》,發送給nil的消息將返回0。結構體中各個字段的值將都是0。其餘的結構體數據類型將不是用0填充的。
類方法 | 實例方法 | |
---|---|---|
屬於類對象 | 屬於實例對象 | |
只能類對象調用 | 實例對象調用 | |
self是類對象 | self是實例對象 | |
類方法能夠調用其餘類方法 | 實例方法能夠調用實例方法 | |
類方法不能訪問成員變量 | 實例方法能夠訪問成員變量 | |
類方法不能直接調用對象方法 | 實例方法能夠調用類方法 |
NSString *str = [[NSString alloc]initWithCString:nullTerminatedCString encoding:encoding];
extern "C" {
}
顯然,頭文件中的編譯宏「#ifndef INCvxWorksh、#define INCvxWorksh、#endif」 的做用是防止該頭文件被重複引用
@property的本質: @property = ivar(實例變量) + getter(取方法) + setter(存方法) 「屬性」 (property)有兩大概念:ivar(實例變量)、存取方法(access method = getter + setter) ivar、getter、setter如何生成並添加到類中: 這是編譯器自動合成的,經過@synthesize關鍵字指定,若不指定,默認爲@synthesize propertyName = _propertyName;若手動實現了getter/setter方法,則不會自動合成。 如今編譯器已經默認爲咱們添加@synthesize propertyName = _propertyName;所以再也不須要手動添加了,除非你真的要改爲員變量名。 生成getter方法時,會判斷當前屬性名是否有_,好比聲明屬性爲@property (nonatomic, copy) NSString *_name;那麼所生成的成員變量名就會變成__name,若是咱們要手動生成getter方法,就要判斷是否以_開頭了。 不過,命名都要有規範,是不容許聲明屬性是使用_開頭的,不規範的命名,在使用runtime時,會帶來不少的不方便的。
• 在protocol中使用@property只會生成setter和getter方法聲明,咱們使用屬性的目的是但願遵照我協議的對象能實現該屬性 • category使用@property也是隻會生成setter和getter方法的聲明,若是咱們真的須要給category增長屬性的實現,須要藉助於運行時的兩個函數: • objc_setAssociatedObject • objc_getAssociatedObject
原子性 (atomic,nonatomic)
讀寫(readwrite, readonly)
內存管理(assign, strong, weak, unsafe_unretained,copy)
getter、setter
在頭文件中將屬性定義爲readonly,在.m文件中將屬性從新定義爲readwrite
meta-class 是 Class 對象的類,爲這個Class類存儲類方法,當一個類發送消息時,就去這個類對應的meta-class中查找那個消息,每一個Class都有不一樣的meta-class,全部的meta-class都使用基類的meta-class(假如類繼承NSObject,那麼他所對應的meta-class也是NSObject)做爲他們的類
@selector()基本能夠等同C語言的中函數指針,只不過C語言中,能夠把函數名直接賦給一個函數指針,而Object-C的類不能直接應用函數指針,這樣只能作一個@selector語法來取.
@interface foo -(int)add:int val; @end SEL class_func ; //定義一個類方法指針 class_func = @selector(add:int);
@selector是查找當前類的方法,而[object @selector(方法名:方法參數..) ] ;是取object對應類的相應方法.
能夠運行中用SEL變量反向查出方法名字字符串。NSString *變量名 = NSStringFromSelector(SEL參數);
取到selector的值之後,執行seletor。 SEL變量的執行.用performSelecor方法來執行.
[對象 performSelector:SEL變量 withObject:參數1 withObject:參數2];
- @property有兩個對應的詞,一個是 @synthesize,一個是 @dynamic。若是 @synthesize和 @dynamic都沒寫,那麼默認的就是@syntheszie var = _var; - @synthesize 的語義是若是你沒有手動實現 setter 方法和 getter 方法,那麼編譯器會自動爲你加上這兩個方法。 - @dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶本身實現,不自動生成。(固然對於 readonly 的屬性只需提供 getter 便可)。假如一個屬性被聲明爲 @dynamic var,而後你沒有提供 @setter方法和 @getter 方法,編譯的時候沒問題,可是當程序運行到 instance.var = someVar,因爲缺 setter 方法會致使程序崩潰;或者當運行到 someVar = var 時,因爲缺 getter 方法一樣會致使崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。
OC中NSString爲不可變字符串的時候,用copy和strong都是隻分配一次內存,可是若是用copy的時候,須要先判斷字符串是不是不可變字符串,若是是不可變字符串,就再也不分配空間,若是是可變字符串才分配空間。若是程序中用到NSString的地方特別多,每一次都要先進行判斷就會耗費性能,影響用戶體驗,用strong就不會再進行判斷,因此,不可變字符串能夠直接用strong。
NSString *timeStr = @"2015-04-10"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd"; formatter.timeZone = [NSTimeZone defaultTimeZone]; NSDate *date = [formatter dateFromString:timeStr]; // 2015-04-09 16:00:00 +0000 NSLog(@"%@", date);
- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
由於系統提供的performSelector的api中,並無提供三個參數。所以,咱們只能傳數組或者字典,可是數組或者字典只有存入對象類型,而結構體並非對象類型,那麼怎麼辦呢?
沒有辦法,咱們只能經過對象放入結構做爲屬性來傳過去了:
ypedef struct HYBStruct { int a; int b; } *my_struct; @interface HYBObject : NSObject @property (nonatomic, assign) my_struct arg3; @property (nonatomic, copy) NSString *arg1; @property (nonatomic, copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的內存,咱們要手動釋放掉 - (void)dealloc { free(self.arg3); } @end
測試:
my_struct str = (my_struct)(malloc(sizeof(my_struct))); str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc] init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [self performSelector:@selector(call:) withObject:obj]; // 在回調時獲得正確的數據的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d", obj.arg3->a, obj.arg3->b); }
實際上,編譯器在編譯時會轉換成objc_msgSend,大概會像這樣:
((void (*)(id, SEL))(void)objc_msgSend)((id)obj, sel_registerName("foo")); 也就是說,[obj foo];在objc動態編譯時,會被轉換爲:objc_msgSend(obj, @selector(foo));這樣的形式,可是須要根據具體的參數類型及返回值類型進行相應的類型轉換。
@implementation Son : Father - (id)init { self = [super init]; if (self) { NSLog(@"%@", NSStringFromClass([self class])); NSLog(@"%@", NSStringFromClass([super class])); } return self; } @end // 輸出 NSStringFromClass([self class]) = Son NSStringFromClass([super class]) = Son 這個題目主要是考察關於Objective-C中對self和super的理解。咱們都知道:self是類的隱藏參數,指向當前調用方法的這個類的實例。那super呢? 不少人會想固然的認爲「super和self相似,應該是指向父類的指針吧!」。這是很廣泛的一個誤區。其實 super是一個 Magic Keyword,它本質是一個編譯器標示符,和self 是指向的同一個消息接受者!他們兩個的不一樣點在於:super會告訴編譯器,調用class 這個方法時,要去父類的方法,而不是本類裏的。 上面的例子無論調用[self class]仍是[super class],接受消息的對象都是當前 Son *xxx 這個對象。 當使用self調用方法時,會從當前類的方法列表中開始找,若是沒有,就從父類中再找;而當使用super時,則從父類的方法列表中開始找。而後調用父類的這個方法。
什麼是構造方法:構造方法是對象初始化並一個實例的方法。
構造方法有什麼用: 通常在構造方法裏 對類進行一些初始化操做
注意點:方法開頭必須以init開頭,接下來名稱要大寫 例如 initWithName ,initLayout
Get方法的做用:爲調用者返回對象內部的成員變量
不能, 由於結構體當中只能是類型的聲明不能進行分配空間
@implementation Person - (void)setAge:(int)newAge { self.age = newAge; } @end 會死循環,會重複調用本身!self.age 改成_age便可; 而且書寫不規範:setter方法中的newAge應該爲age
NSString * str = @"20 | http://www.baidu.com"; NSArray *array = [str componentsSeparatedByString:@"|"]; //這是分別輸出的截取後的字符串 for (int i = 0; i<[array count]; ++i) { NSLog(@"%d=%@",i,[array objectAtIndex:i]); }
//建立 @protocol MyDelagate @required -(void)eat:(NSString *)foodName; @optional -(void)run; @end //聲明 @interface person: NSObject< MyDelagate> //實現 @implementation person -(void)eat:(NSString *)foodName; { NSLog(@"吃:%@!",foodName);} -(void)run { NSLog(@"run!");} @end
isKindOfClass,做用是,某個對象屬於某個類型或者繼承自某類型
isMemberOfClass:某個對象確切屬於某個類型
selector:經過方法名,獲取在內存中的函數的入口地址
SEL是「selector」的一個類型,表示一個方法的名字-------就是一個方法的入口地址
id是一個指向任何一個繼承了Object(或者NSObject)類的對象。須要注意的是id是一個指針,因此在使用id 的時候不須要加*。
int:基本整型,當字節數爲2時 取值範圍爲-32768~32767,當字節數爲4時 取值範圍
負的2的31次方 到 2的31次方減1
unsigned int:無符號基本整型,當字節數爲2時 取值範圍爲0~65535,當字節數爲4時 取值範圍爲0到2的32次方減1
+ (void)deleteFiles:(NSString *)path;{ // 1.判斷文件仍是目錄 NSFileManager * fileManger = [NSFileManager defaultManager]; BOOL isDir = NO; BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir]; if (isExist) { // 2. 判斷是否是目錄 if (isDir) { NSArray * dirArray = [fileManger contentsOfDirectoryAtPath:path error:nil]; NSString * subPath = nil; for (NSString * str in dirArray) { subPath = [path stringByAppendingPathComponent:str]; BOOL issubDir = NO; [fileManger fileExistsAtPath:subPath isDirectory:&issubDir]; [self deleteFiles:subPath]; } }else{ NSLog(@"%@",path); [manager removeItemAtPath:filePath error:nil]; } }else{ NSLog(@"你打印的是目錄或者不存在"); } }
文章若有問題,請留言,我將及時更正。