IOS學習筆記之Object-C(二)

++ Category ++分類(類擴展)
可以動態的爲已經存在的類添加新的方法(但不能添加成員變量);(Xcode中新建-Object-C file-選擇category;)[可以和頭文件寫在同一個文件中(一個文件中可有多個類)]
不需要創建子類;實現的方法的模塊化;

 //需要導入要擴展的類的頭文件;
#import “Student.h"
//類名後有一個()就代表着是一個分類;
//(..)中的內容就是分類的名稱;
@interface Student (addFound)
-(void)test2;//擴展的方法聲明
@end

使用場景:需求變更;對系統基礎類庫進行擴展;

++ protocol ++
概念:就是一系實現方法的列表,其中聲明的方法可以被任何類實現,這種模式稱爲代理(delegation)模式(同Java中的接口);
(在iOS和OS x開了中,採用了大量的代理模式來實現MVC中的View(UI控件)和Controller(控制器)的解耦,如按鈕監聽);
[命名規範 **Delegate,如ButtonDelegate;]
在頭文件中定義:

@class Button;
//<>代表實現了某個協議(類似於java中該接口繼承了另一個接口)
@protocol ButtonDelegate <NSObject>
-(void)onClick:(Button *)button;//一般規範要添加調用的對象
@end
@interface Button : NSObject
//定義一個按鈕的監聽器,不知道返回類型,用id代替,<ButtonDelegate>表示該協議是實現了ButtonDelegate
//還需要手動釋放內存
@property (nonatomic,retain) id<ButtonDelegate> delegate;
-(void)onClick;
@end

創建一個listener實現這個協議:

//#import “Button.h”//不用導入,但在.m文件中需導入的protocol文件
@protocol ButtonDelegate;//作用同@class
@interface OnClickListener : NSObject <ButtonDelegate>
-(void)onClick;
@end

並在觸發時調用:

@implementation Button
-(void)onClick{
    //按鈕被點擊了;
    //先判斷調用的對象是否實現了該方法
    if([_delegate respondsToSelector:@selector(onClick:)]){
        [_delegate onClick:self];
    }else{
        NSLog(@"未實現該方法");
    }
}

使用:

 //初始化一個按鈕
    Button *btn = [[[Button alloc] init] autorelease];
    //初始化一個按鈕監聽器
    OnClickListener *listener = [[[OnClickListener alloc] init] autorelease];
    //將監聽器添加到按鈕上
    btn.delegate  = listener;
    [btn onClick];

(原則誰觸發,傳入誰)在使用協議下的方法下,一般傳入調用的對象;如當某個按鈕點擊時,一般傳入該按鈕;
— 同java,可單獨定義多個協議,且一個類也有實現多個協議:

定義protocol文件:
@protocol Study <NSObject>

@required //必須實現的方法,雖然是必須實現,但是編譯器不會出錯,OC是弱語法的,對類型要求不嚴格
-(void)testStudy;
//若不寫,默認是@required
-(void)testStudy1;
@optional //可實現可不實現
-(void)testStudy2;
@end

一個類可同時實現多個protocol:

//同時實現兩個協議(相當於java中實現兩個接口)
@protocol Study,Learn;

@interface Student : NSObject<Study,Learn>

在對象調用實現的協議方法時,可先判斷是否實現:

void testProtocol(){
    Student *stu =[[[Student alloc] init] autorelease];
    //判斷student是否遵守了Study協議
    if ([stu conformsToProtocol:@protocol(Study)]) {
        NSLog(@"student是遵守了Study協議");
    }
    //判斷student是否實現了某個方法;
    if([stu respondsToSelector:@selector(testStudy)]){
        NSLog(@"student 實現了testStudy方法");
        [stu testStudy];
    }else{
        NSLog(@"student沒有實現testStudy方法");
    }
}

++ Block ++蘋果建議儘量多使用block,在多線程,異步任務,集合遍歷,集合排序,動畫轉場用的很多。[同java中的回調];
封裝了代碼,可以在任何時候調用執行;(類型於java中直接在使用的時候new一個onClickListenre)
Block可作爲函數參數或函數的返回值;而其本身可帶輸入參數的返回值。它和傳統的函數指針很類似;但有區別:block是inline(內聯函數),並默認情況下對局部變量是隻讀的。(可定義在方法內部和外部)
使用:

 //使用別名聲明一個帶兩個參數的block
typedef int(^MySum) (int,int);
void testBlock(){
    //第一種方式:直接定義;^是block的標誌,定義了一個block,接收兩個int類型的參數,並返回一個int類型;
    int (^Sum)(int,int) = ^(int a,int b){
        return a+b;
    };
    NSLog(@"sum is %i",Sum(10,11)) ;
    __block int c = 19;
    //第二種方式:使用聲明的block
    //可以訪問外部的成員,但不能修改(同java中接口中訪問外部變量用final)
    //若要訪問,外部的變量須用__block修飾
    MySum sum = ^(int a,int b){
        c = 20;
        NSLog(@"c is %i",c);
        return a+b;
    };
    NSLog(@"sum is %i",sum(10,31)) ;
}

實現按鈕監聽:
在button.h中:

//定義一個block別名格式: 返回類型 (^名字)(參數)
typedef void (^ButtonBlock)(Button *);
@property (nonatomic,assign) ButtonBlock listener;

在button.m中在onClick中方法中調用:
_listener(self);
使用:

Button *btn = [[[Button alloc] init] autorelease];
    btn.listener = ^(Button *btn){
        NSLog(@"listener onclick %@",btn);
    };
    [btn onClick];

和指針函數的區別:

 int sumFound(int a,int b){
    return a+b;
}
void  testBlockAndPoint(){
    //定義了Sum這種block類型
    typedef int (^Sum)(int,int);
    //定義了sump這種指針類型
    typedef int  (*SumP)(int,int);
    //定義了一block變量
    Sum sum = ^(int a,int b){
        return a+b;
    };
    NSLog(@"block sum 和%i",sum(1,2));
    //指針函數指向實現的方法
    SumP p = sumFound;
    NSLog(@"point sum %i",p(2,3));
}

++OC 相關基礎類 ++
都位於Foundation(類似於java中的lang包,java中有基礎類都有對應的類)

結構體 +:位於Foundation/NSRange下

 typedef struct _NSRange {
    NSUInteger location;
    NSUInteger length;
} NSRange;

這個結構體表示事物的一個範圍,通常是字符串裏的字符範圍或集合裏的元素範圍;location(該範圍的起始位置)length(該範圍內元素的個數)。
三種創建方式:
*逐個賦值;
*聚合賦值NSRange range={3,4};
*Foundation提供的一個快捷函數:NSRange range = NSMakeRange(8, 10);

 //直接全部打印,但不能直接使用rang,需使用NSString轉換
    NSLog(@"%@",NSStringFromRange(range));
    NSPoint p;
    p.x = 20;
    p.y = 37;
    NSLog(@"%@",NSStringFromPoint(p));

常用結構體:NSSize,NSPoint,NSRange,NSRect;
(都有對應的生成方法 NSMake***(..) ;打印方法 NSStringFrom***(.) ;繪製類生成方法 CG***Make(..)方法;)

++ 字符串+
NSString:不可變(同java中的String);
指向指針的指針,將原變量的地址作參數傳入函數中,可修改傳入的原變量的值;

 void testStringFromFile(){
    //從文件中讀取字符串
//    NSString *path =@"/Users/sionfan/work/ddd.txt";
    //另一種讀取文件的方式url
    NSURL *path = [NSURL URLWithString:@"file:///Users/sionfan/work/ddd.txt"];
    //定義一個錯誤變量,傳入,若有值,則有錯誤信息;
    NSError *error;
    //指定字符串編碼UTF8;
    NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];//此處要對傳入的error賦值,則要把error的地址傳入才能對其賦值;(參數是指向指針的指針)
    if (error==nil) {
        //沒有錯誤信息,則文件讀取成功
        NSLog(@"讀取文件成功str:%@",str);
    }else{
        NSLog(@"讀取文件失敗:%@",error);
    }
    //也可以讀取網頁;
    NSURL *urlPath = [NSURL URLWithString:@"http://www.baidu.com"];
    NSError *httpError;
    //讀取URL
    NSString *str2 = [NSString stringWithContentsOfURL:urlPath encoding:NSUTF8StringEncoding error:&httpError];
    NSLog(@"讀取網頁成功str:%@",str2);
}
/**參數是指向指針的指針,傳入str的地址&str,就可對傳入的原變量進行修改;*/
void testModofyStr(NSString **str){
    *str = @"this is 修改後的str";
}
+(void)testString{
    //C中的字符串
    char *str = "this is a C string";
    //1.這種方式創建的方式不需要自己釋放內存
    NSString *str1 = @"this is a OC string";
    //2.這種方式需要手動釋放內存
    NSString *str2 = [[NSString alloc] init];
    str2 = @"this is a OC init string";
    //3.同上,直接帶參數創建
    NSString *str3 = [[NSString alloc] initWithString:@"this is initwith Stirng"];
    //4.不帶@,將C的的字符串轉換成OC的字符串;
    NSString *str4 = [[NSString alloc] initWithUTF8String:"this is c string"];
    //5.帶格式符的字符串
    NSString *str5 = [[NSString alloc] initWithFormat:@"my age is %i,and height is %.2f",18,1.87];
    //上面對應的方法都是自己創建的,需要手動釋放內存;在NSString都有如下對應的靜態方法,可不用手動釋放內存;
    //此處可能存在兩個錯誤,1.上面自己創建的對象未釋放,會內存泄露;2,後面用靜態方法創建的對象自己已經釋放,再手動釋放會造成野指針錯誤
    str5 = [NSString stringWithString:@"this is static string"];
//    [str5 release];
    NSLog(@"%s\n,%@\n,%@\n,%@\n,%@\n,%@\n",str,str1,str2,str3,str4,str5);
    testStringFromFile();
    //傳入str的地址,可在執行完函數後修改原變量的值
    testModofyStr(&str5);
    NSLog(@"%@",str5);
}

NSSting *str = @“345”;345沒有名字,只有一個指針str指向存儲了345字符串的這塊地址;
+字符串導出+

 NSString *str = @"this is a export str";
    //若文件不存在,會自動創建
    //但若文件夾不存在,會自動報錯
    NSString *path =@"/Users/sionfan/work1/ddda.txt";
    NSError *error;
    //atomically,原子性操作(先創建一個臨時文件,將文件一點點到這個臨時文件中,再拷貝到目標文件中);非原子性操作:直接向文件中寫入;(優先考慮原子性操作,可考慮寫入安全)
    [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
    if (error) {
        //獲取本地重要錯誤信息,類似於java的e.getMessage()
        NSLog(@"寫入失敗:%@", [error localizedDescription]);
    }else{
        NSLog(@"寫入成功");
    }
}

++ String相關方法 +

uppercaseString: 全部轉成大寫
lowercaseString:全部轉成小寫
capitalizedString:只是首字母轉成大寫
[@”abc” isEqualToString:@“Abc”]:比較兩個字符串內容是否相同(相同返回1)
[@”abc” compare:@“Abc”]:比較字符串大小;(返回一個枚舉值:三個值:NSOrderedAscending = -1L(右邊的大), NSOrderedSame(相同), NSOrderedDescending(左邊大))
[@”abc” caseInsensitiveCompare: @“Abc”]:忽略大小寫比較,返回值同上;
[str hasPrefix:@“stu”]:str是否以stu開頭;
[str hasSuffix:@“.jsp”]:str是否以.jsp結尾;
[str rangeOfString:@“stu”]:查看stu在str的位置和長度;返回一個NSRang的結構體(用NSStringFromRang打印),未找到返回NSNotFound(NSIntegerMax);if(range==NSNotFound)未找到;
(同java,若有多個相同的字符,則只返回第一個位);
[另帶同名方法,帶參數:options(指定搜索選項,如搜索順序等):range :(指定一個範圍進行搜索)]
[str substringFromIndex:2]:從index = 2開始截取末尾;
[str substringToIndex:2]:從開頭截取到index=2處;
[str substringWithRange:NSMakeRange(2, 4)]:從index=2開始截取4個字符;
[str componentsSeparatedByString:@“.”]:以.分組(同java是split方法);返回NSArray;
[NSString pathWithComponents:paths]:將一個(NSMutableArray *paths)數組拼成一個路徑
[str pathComponents]:將一個路徑分解成一個數組;
[path isAbsolutePath]:表示一個路徑是否是絕對路徑(實際上就是判斷開始位置有無/)
[path stringByDeletingLastPathComponent]:返回刪掉最後一個目錄後的路徑;
[path stringByAppendingPathComponent:@“work”]:在路徑最後拼接一個目錄,並返回拼接後的路徑
[path pathExtension]:返回一個文件路徑該文件的擴展名(就是.後的內容);
[str stringByDeletingPathExtension]:刪掉擴展名;
[str stringByAppendingPathExtension:@“html”]):拼接一個擴展名(自動加.);
[str stringByAppendingFormat:@“%i”,2]):拼接一個帶格式符的字符串
[str intValue]:將內容是int類型的string轉成int(同java中String.valueOf),另外double,float都有對應的方法;
[str length]:返回字符串的字符個數
[str characterAtIndex: 6]:返回index=6處的字符
[str UTF8String]:將一個OC的字符串轉成一個C的字符串;

++ NSMutableString +可變長字符串(同java中StringBuilder),是NSString的子類,其父類的方法都可用;
[一般對象中帶有 Mutable ,就表示是一個可變的對象]

 //長度可變,可先在初始化時指定容量大小,就會預先分配10個字數的存儲空間,效率高一些;
    NSMutableString *ms = [[NSMutableString alloc] initWithCapacity:10];
    //設置字符串內容
    [ms setString:@"1234"];
    //直接拼接
    [ms appendString:@"567"];
    //拼接帶佔位符的字符串
    [ms appendFormat:@"age is %i",23];
    //替換指定位置和長度的字符串,一般與rangeOfString全用進行文本替換
    [ms replaceCharactersInRange:NSMakeRange(2, 2) withString:@"eed"];
    //在index=3的位置插入指定的字符串
    [ms insertString:@"insert" atIndex:3];
    //刪除指定位置和長度的字符串
    [ms deleteCharactersInRange:NSMakeRange(3, 2)];
    NSLog(@"%@",ms);
//    [ms release];

博客地址:IOS學習筆記之Object-C(二)

發佈了46 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章