objective-c 语法快速过(4)
oc 里的字符串
字符串的快速創(chuàng)建(最簡(jiǎn)單的方法)
NSStirng *str = @“Hello”;//oc的字符串都是@“”形式的oc的字符串也是類的對(duì)象,是NSString類的對(duì)象,創(chuàng)建沒有那么麻煩不用[ ],使用面向?qū)ο蟮乃枷雭聿倏v字符串。
char *name = "xxxxx";//c風(fēng)格字符串oc使用 %@ 輸出字符串,不是%s
NSString *name = @”dashuai”;NSLog(@“我的名字是%@”, name);c 風(fēng)格字符串輸出解析的用法是%s
NSLog(@"%s", name);//%s是c風(fēng)格的格式化解析OC字符串的另一方式,Foundation 框架里的 NSString 類
NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];NSLog(@"---- %ld", [newStr length]);length方法,返回unsigned long類型 NSString *name = @"哈哈達(dá)到"; // length方法算的是字?jǐn)?shù)總數(shù),包含的文字的數(shù)目!不是求字符個(gè)數(shù)!! int size = [name length];
不懂就去查詢文檔!百度!
?
// main.m #import <Foundation/Foundation.h> /*NSString : 不可變字符串NSMutableString : 可變字符串*/ int main() {NSMutableString *s1 = [NSMutableString stringWithFormat:@"my age is 10"];// 拼接內(nèi)容到s1的后面[s1 appendString:@" 11 12"];// 獲取is的范圍NSRange range = [s1 rangeOfString:@"is"];[s1 deleteCharactersInRange:range];NSString *s2 = [NSString stringWithFormat:@"age is 10"];//新建字符串,拼接好的字符串到新建的字符串里,但是原來的字符串沒有變!兩個(gè)方法不一樣。NSString *s3 = [s2 stringByAppendingString:@" 11 12"];NSLog(@"s1=%@, s2=%@", s1, s2);return 0; }void stringExport() {// 字符串的導(dǎo)出[@"Jack\nJack" writeToFile:@"/Users/apple/Desktop/my.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];NSString *str = @"4234234";NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/my2.txt"];[str writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:nil]; }void stringCreate() {/*1.字符串的創(chuàng)建*/NSString *s1 = @"jack";//NSString *s2 = [[NSString alloc] initWithString:@"jack"];這種方法不推薦! NSString *s3 = [[NSString alloc] initWithFormat:@"age is %d", 10];// C字符串 --> OC字符串NSString *s4 = [[NSString alloc] initWithUTF8String:"jack"];// OC字符串 --> C字符串const char *cs = [s4 UTF8String];// NSUTF8StringEncoding 用到中文就可以用這種編碼NSString *s5 = [[NSString alloc] initWithContentsOfFile:@"/Users/apple/Desktop/1.txt" encoding:NSUTF8StringEncoding error:nil];// URL : 資源路徑// 協(xié)議頭://路徑// 本地文件 file://// ftp://// 網(wǎng)頁資源 http://weibo.com/a.png// http://www.baidu.com// NSURL *url = [[NSURL alloc] initWithString:@"file:///Users/apple/Desktop/1.txt"];NSURL *url = [NSURL fileURLWithPath:@"/Users/apple/Desktop/1.txt"];NSString *s6 = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];NSLog(@"s6=\n%@", s6);/*一般都會(huì)有一個(gè)類方法跟對(duì)象方法配對(duì)[NSURL URLWithString:<#(NSString *)#>];[NSString stringWithFormat:@""];[NSString stringWithContentsOfFile:<#(NSString *)#> encoding:<#(NSStringEncoding)#> error:<#(NSError *__autoreleasing *)#>]; */ }?
OC的 set 和 get 方法
類的成員變量盡量不要@public,保持?jǐn)?shù)據(jù)的隱蔽性和封裝性,使用對(duì)象直接訪問類的成員變量也不推薦,因?yàn)檫@樣類的成員變量可以被隨意的修改,不安全,而是應(yīng)該間接的調(diào)用。并且直接調(diào)用會(huì)讓別人一下子就看到了類的內(nèi)部結(jié)構(gòu)和信息,失去了封裝的意義。
set方法
1)?? 作用:用來設(shè)置成員變量,可以在方法里面過濾掉一些不合理的值
2)?? 命名規(guī)范:
- 方法名都是以set開頭,而且后面跟上成員變量名,成員變量名的首字母必須大寫
- 一定接受參數(shù),且形參名稱不要跟成員變量同名
- 返回值void
get方法
1)?? 作用:返回對(duì)象內(nèi)部的成員變量
2)?? 命名規(guī)范:get方法的名稱一般就跟成員變量同名
/*成員變量的命名規(guī)范:一定要以下劃線 _ 開頭 @interface Student : NSObject { 1.讓成員變量和get方法的名稱區(qū)分開2.可以跟局部變量區(qū)分開,一看到下劃線開頭的變量,一般都是成員變量*/int _no;Sex _sex; } // sex的set和get方法 - (void)setSex:(Sex)sex; - (Sex)sex; // no的set和get方法 - (void)setNo:(int)no; - (int)no; @endoc特有的語法—兼容c系列的點(diǎn)語法?
可以使用點(diǎn)語法來代替oc古怪的對(duì)象調(diào)用的形式。這是oc特有的讓其他(主要是習(xí)慣了 c 系列編程語言的程序員,比如 c,c++,java等)程序員快速看懂的一個(gè)做法。
// 點(diǎn)語法的本質(zhì)還是方法調(diào)用p.age = 10; // [p setAge:10];這里還是古怪,到底是get還是set方法,要看是給它賦值了(set),還是被賦值了(get)。還是和java或c++的點(diǎn)語法區(qū)分。
oc 中類的成員變量的作用于
?@public : 在任何地方都能直接訪問對(duì)象的成員變量
?@private : 只能在當(dāng)前類的對(duì)象方法中直接訪問。私有成員只能在本類被直接訪問,子類不可見,只能是set和get方法訪問(@implementation中默認(rèn)是@private,因?yàn)橐话悴粫?huì)包含實(shí)現(xiàn)文件,都是包含頭文件,故實(shí)現(xiàn)文件默認(rèn)是私有的)
?@protected : 可以在當(dāng)前類及其子類的對(duì)象方法中直接訪問? (@interface中默認(rèn)就是@protected)
?@package : 只要處在同一個(gè)框架中,就能直接訪問對(duì)象的成員變量,不常用
?@interface和@implementation中不能聲明同名的成員變量,同名沖突,很好理解
Xcode的一個(gè)特性@property和@synthesize
s?nθ??sa?z v綜合合成;(通過化學(xué)或生物)合成;(音響)合成
@property
自動(dòng)生成set和get方法,類似java的eclipse的 setter 和 getter選項(xiàng)
#import <Foundation/Foundation.h> @interface Person : NSObject {int _age;int _height;double _weight;NSString *_name; } // @property:只能用在聲明里,可以自動(dòng)生成某個(gè)成員變量的setter和getter聲明,并且和java還不一樣,xcode把自動(dòng)的聲明隱藏,不可見。這是編譯器的特性! 下面這一句,代表注釋的那兩句。 @property int age; //- (void)setAge:(int)age; //- (int)age; @property int height;//先生成set再get //- (void)setHeight:(int)height; //- (int)height; - (void)test; @property double weight; //如果成員變量類型一樣,可以合并在一起寫,但是實(shí)際開發(fā)不這樣,分開比較好 @property NSString *name; @end注意:@property里的變量age如果沒有被提前聲明,那么也是可以運(yùn)行的,編譯器會(huì)自動(dòng)生成_age成員變量,xcode4.4版本之后有的。這樣生成的成員變量,在類聲明里是@private。若類聲明里存此成員變量,如果@property還是那么寫,就不會(huì)再自動(dòng)生成。
?@synthesize
只寫在實(shí)現(xiàn)里。可以自動(dòng)去類聲明里找@property,然后根據(jù)它去生成類的成員變量的setter和getter方法的實(shí)現(xiàn),并且會(huì)訪問這個(gè)成員變量
@synthesize age = _age;
?如果這樣寫,默認(rèn)會(huì)訪問age這個(gè)成員變量,如果沒有age,就會(huì)自動(dòng)生成@private類型的age變量,都是自動(dòng)存在類聲明里。
注意:xcode4.4之后,為了讓程序員把精力放在業(yè)務(wù)邏輯上,而不是無謂的垃圾代碼的書寫上,xcode變得越來越方便,做的東西也越多,現(xiàn)在可以省略類的成員變量的聲明,直接@property就可以自動(dòng)生成變量和配套的set與get方法的聲明。同樣,4.4之后,類的實(shí)現(xiàn)里,@synthesize也不用寫了。也就是說,set和get的實(shí)現(xiàn)不用寫。
意味著,現(xiàn)在的@property 聲明,類聲明里的@property默認(rèn)做兩個(gè)事情,即生成set和get的聲明,也生成set和get的實(shí)現(xiàn)。當(dāng)然,如果類聲明里沒有變量聲明,那么還要做第三個(gè)事情,自動(dòng)生成私有的成員變量。
Xcode原則就是:沒有,我替你生成,有我就直接用。
這里就可以解釋為什么蘋果建議類的成員變量前面加下劃線?
因?yàn)?#64;property 的新特性:自從 xcode4.4之后,@property 就獨(dú)攬了@synthesize 的功能,也就說,@proeprty 可以同時(shí)生成成員變量的 set,get 方法的聲明和實(shí)現(xiàn),兩個(gè)都能。默認(rèn)的情況下,set 和 get 方法的實(shí)現(xiàn),會(huì)去訪問下劃線的成員變量,故要求類的聲明里使用下劃線的變量命名方式命名成員變量。說到底:就是因?yàn)樾绿匦缘?#64;property自動(dòng)生成set,get方法的聲明和實(shí)現(xiàn),默認(rèn)訪問的都是前面帶下劃線的成員變量。
oc 里的 id 類型(萬能指針)
id 是一種類型
類型不能做變量名,好比 int? int;是錯(cuò)誤的,一個(gè)道理。
Id 是萬能指針
能指向(操縱)任何的 oc 對(duì)象,而且不能加*,只寫id就代表指針(因?yàn)?id內(nèi)部已經(jīng)包含*,見官方文檔)。
Person *p = [Person new];//傳統(tǒng)的操作人的對(duì)象,人類型指針p 指向人的對(duì)象萬能指針,id能指向 or 操作任何OC對(duì)象,只適合用在 oc 對(duì)象上
id d = [Person new];//id 指向人的對(duì)象id 的缺點(diǎn):
如果同樣是指向(調(diào)用)類不存在的對(duì)象方法,那么編譯器直接報(bào)錯(cuò)!不會(huì)弱語法了
千萬別加*
oc 的構(gòu)造方法和重寫?
構(gòu)造方法:用來初始化對(duì)象的方法,oc里是個(gè)對(duì)象方法,-開頭 ?-init
面向?qū)ο蟮恼Z言,都包含的東西---構(gòu)造方法,用和 c++類似的new 這個(gè)類方法創(chuàng)建對(duì)象,其實(shí)不好。
// Person *p = [Person new];不推薦這樣創(chuàng)建對(duì)象new 其實(shí)是類方法,是 NSObject 類的方法,可以創(chuàng)建對(duì)象,分配內(nèi)存,但是事實(shí)上,我們不常用,因?yàn)樘腊?#xff0c;做的事情很單調(diào),就是完整的創(chuàng)建一可用對(duì)象。
完整地創(chuàng)建一個(gè)可用的對(duì)象其實(shí)分兩步:
?1.分配存儲(chǔ)空間? +alloc
?2.初始化 -init
new 方法做這兩個(gè)事情,new 方法內(nèi)部,調(diào)用兩個(gè)方法(一個(gè)類方法,一個(gè)對(duì)象方法)完成這個(gè)步驟,細(xì)節(jié)為:
1.調(diào)用+alloc分配存儲(chǔ)空間
Person *p1 = [Person alloc];//此時(shí)對(duì)象不可用,沒有初始化,返回 id(oc 對(duì)象)2.調(diào)用-init進(jìn)行初始化
Person *p2 = [p1 init];反回 oc 對(duì)象(已經(jīng)初始化之后)本身說明 new 是兩個(gè)方法的聯(lián)合,開發(fā)不常用,比較死板,一般分兩步做,這樣后果是方便選擇。因?yàn)槌跏蓟灰欢ū仨毷?init對(duì)象方法初始化。。
兩步合并的簡(jiǎn)單寫法:掌握,開發(fā)常用這個(gè)寫法,從此不用 new 了。
Person *p4 = [[Person alloc] init];Oc的構(gòu)造方法就是-init 方法,用來初始化對(duì)象的方法。對(duì)象方法,每個(gè)對(duì)象內(nèi)部的成員變量默認(rèn)都初始化為0,
創(chuàng)建 person 對(duì)象,保證她的_age 默認(rèn)都是10,不是0,怎么做?
需要重寫 –init方法,覆蓋父類 –init方法
重寫構(gòu)造方法的目的:
為了讓對(duì)象創(chuàng)建出來,成員變量就會(huì)有一些固定的值
重寫構(gòu)造方法的注意點(diǎn)
1.先調(diào)用父類的構(gòu)造方法([super init])
2.再進(jìn)行子類內(nèi)部成員變量的初始化,和 c++類似。
Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int age; @endPerson.m #import "Person.h" @implementation Person // 重寫-init方法,其實(shí) id 有些類似 c++的模板的應(yīng)用。 //- (id)init //{ // 1、一定要先調(diào)用super的init方法:先初始化父類中聲明的一些成員變量和其他屬性self = [super init]; // 返回的是當(dāng)前oc對(duì)象,一定用 self接受,這里需要好好研究,先知道。 // 2.如果父類對(duì)象初始化成功,才有必要進(jìn)行接下來的初始化 // if (self != nil) // { // _age = 10; // } // // 3.返回一個(gè)已經(jīng)初始化完畢的oc對(duì)象 // return self; //}//綜合的寫法,熟練之后如下這樣寫: - (id)init {if ( self = [super init] ){ _age = 10;}return self; } @end
要求:
學(xué)生類的學(xué)生對(duì)象,初始化完畢之后,年齡都是10,學(xué)號(hào)都是1.還是重寫構(gòu)造方法-init
Student.h繼承 person 類 #import "Person.h" @interface Student : Person @property int no; @endStudent.m #import "Student.h" @implementation Student // 學(xué)生對(duì)象初始化完畢后,年齡就是10,學(xué)號(hào)就是1 - (id)init {if ( self = [super init] ){_no = 1;}return self; } @end
main.h #import <Foundation/Foundation.h> #import "Person.h" #import "Student.h" int main() { // 每個(gè)stu對(duì)象創(chuàng)建出來,他的_age都是10,學(xué)生學(xué)號(hào)都是1,isa 指向本身 每個(gè) p4對(duì)象創(chuàng)建出來,她的 _age 都是10,isa 指向本身類Person *p4 = [[Person alloc] init];Student *stu = [[Student alloc] init];return 0; }
student 繼承了 person ,而 person繼承了 NSObject,比如 student 對(duì)象內(nèi)部有三個(gè)成員變量,分別為: student 自己的_no,和繼承自父類 person 類的_age,還有 person 最開始就繼承的父類NSObject 的 isa指針,這個(gè)三個(gè)成員變量,都是 student 對(duì)象 stu 包含的!
?
因?yàn)閟tudent 類 創(chuàng)建 student 對(duì)象的時(shí)候,先進(jìn)入 student 類查找-init,(因?yàn)?oc 里規(guī)定,如果父類和子類有同名方法,子類對(duì)象優(yōu)先調(diào)用子類同名方法),然后 在 student 類里發(fā)現(xiàn)- (id)init方法,之后又發(fā)現(xiàn):
{if ( self = [super init] )這句話,那么編譯器會(huì)率先進(jìn)入到父類 person,因?yàn)?super 的作用{_no = 1;}return self;}然后先調(diào)用直接父類 person 的 –init,而 person 的-init為:
- (id)init{if ( self = [super init] )還是執(zhí)行到此,我們發(fā)現(xiàn)調(diào)試就進(jìn)不去了,因?yàn)?super 調(diào)用的是 NSObject,蘋果是不開源的,但是事實(shí)還是進(jìn)去偷著執(zhí)行 NSobject 的-init 方法,初始化isa 指針, 把 isa 初始化為指向student 類本身,記住是當(dāng)前的類,初始化完畢,程序執(zhí)行回到 person 類,繼續(xù)向下執(zhí)行_age=10。(同時(shí)student 的成員變量 age 變?yōu)?0){_age = 10;}return self;最后返回的 self 指向的是 當(dāng)前student 的對(duì)象}當(dāng)person的-init 調(diào)用完畢,最后才回到 子類student 類,繼續(xù)執(zhí)行 student 的-init, 執(zhí)行_no=1,繼承來的 isa 初始化為指向本身 student 類,這才初始化完畢。
person 對(duì)象初始化的時(shí)候,同理,先在本類查找初始化方法,發(fā)現(xiàn) super 語句,然后再去父類 NSObject 類 里查找-init方法,(這里先記住 self=[super init]的寫法,下來再深入),NSObject 做一件事,那就是初始化 isa,把 isa 指向 person 類本身,(指向當(dāng)前類,這個(gè)類是畢源的,看不到內(nèi)部代碼)然后回到 person類,_age=10。執(zhí)行完畢。
再看一看 student 對(duì)象,創(chuàng)建的時(shí)候,先初始化,同理在本類,然后 發(fā)現(xiàn) super,那么去父類 person 執(zhí)行-init,還是發(fā)現(xiàn) super,還是去 NSObject執(zhí)行-init,把 isa 指向 student 類本身,(當(dāng)前類不是 person,是 student 了)然后回到 person,_age=10.回到student,_no=1,執(zhí)行完畢,再回main 函數(shù),初始化,完畢。
oc構(gòu)造方法的自定義
?oc自定義構(gòu)造方法的規(guī)范
?1.一定是對(duì)象方法, 故一定以 - 開頭
?2.返回值一般是id類型
?3.方法名一般以initWith開頭
這讓我想起了,c++構(gòu)造函數(shù)的含參構(gòu)造和默認(rèn)構(gòu)造,和不帶參數(shù)的構(gòu)造,意義是類似的。其實(shí)就是帶參構(gòu)造。和 c++大同小異。
Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property NSString *name; @property int age; - (id)initWithName:(NSString *)name; - (id)initWithAge:(int)age; - (id)initWithName:(NSString *)name andAge:(int)age; @endPerson.m #import "Person.h" @implementation Person - (id)initWithName:(NSString *)name {if ( self = [super init] )固定寫法,記住{_name = name;}return self; } - (id)initWithAge:(int)age {if ( self = [super init] ){_age = age;}return self; } - (id)initWithName:(NSString *)name andAge:(int)age {if ( self = [super init] ){_name = name;_age = age;}return self; } @endStudent.h繼承 person 類 #import "Person.h" @interface Student : Person @property int no;//_no 是子類 student 自己的屬性 - (id)initWithNo:(int)no; - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no; @endstudent.m #import "Student.h" @implementation Student - (id)initWithNo:(int)no {if ( self = [super init] ){_no = no;}return self; } // 要理解和接受這個(gè)做法和思想: // 父類的屬性交給父類方法去處理,子類方法處理子類自己的屬性 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no { // 將name、age傳遞到父類方法中進(jìn)行初始化,no 在本類初始化 使用了自定義的構(gòu)造方法if ( self = [super initWithName:name andAge:age]){_no = no;}return self; } @endmain.m #import <Foundation/Foundation.h> #import "Person.h" #import "Student.h" int main(int argc, const char * argv[]) {@autoreleasepool {Student *p = [[Student alloc] initWithName:@"Jim" andAge:29 andNo:10];}return 0; }每個(gè)對(duì)象創(chuàng)建之后,都有一個(gè)默認(rèn)名,年齡,和學(xué)號(hào),但是每個(gè)人的結(jié)果不一樣。此時(shí),需要使用自定義構(gòu)造方法初始化。否則重寫構(gòu)造方法初始化的話(不帶參數(shù))導(dǎo)致名稱都是一樣的。不符合程序要求。
首先,創(chuàng)建 student 對(duì)象,初始化對(duì)象指針 p(指向?qū)ο?#xff09;,先在本類找 initWithName 方法,確實(shí)有,然后進(jìn)入執(zhí)行,將name和age(都是繼承來的屬性)傳到父類方法中進(jìn)行初始化:這樣分工明確(其實(shí)和 c++一樣的思路),自己做自己的事情,體現(xiàn)了良好的架構(gòu)思想,還有這樣做的好處是,如果我們都統(tǒng)一在子類初始化,那么一旦父類的成員變量名稱改變了,會(huì)導(dǎo)致子類的代碼出錯(cuò),需要修改,一旦工程較大,后果不堪設(shè)想,而分工明確,自己做自己的事情,把父類的成員讓父類去初始化,子類只管自己的,就能做到不變應(yīng)萬變。
?
總結(jié)
以上是生活随笔為你收集整理的objective-c 语法快速过(4)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给Macbook装系统的网址
- 下一篇: Object-C中方法