++ 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(二)