日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ObjC: Foundation Kit

發布時間:2025/3/19 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ObjC: Foundation Kit 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Foundation Kit是什么?

你可以把它看作Java JDK中的java.lang包。不論是JavaME、JavaEE還是Android,各種變種Java環境,都擁有的基礎類庫,或者擁有它的一部分。

Foundation Kit在Mac OS X和iOS開發中都包含。是這兩個環境的最基礎ObjC類庫。比如,下面是Mac環境代碼一般會引用的頭文件:

#import <Cocoa/Cocoa.h>

Cocoa是Mac OS X環境下框架的統稱。

可以通過File>Open quickly打開這個頭文件,發現它又引用了三個頭文件:

#import <Foundation/Foundation.h>?
#import <AppKit/AppKit.h>?
#import <CoreData/CoreData.h>

其中AppKit是Mac OS X下面特定的類庫。CoreData是自動化ORMapping框架,用于數據庫和對象持久化的。

在iOS環境下,不使用Cocoa框架,而是Cocoa touch,一般會導入UIKit頭文件。那么可以推算出,在該頭文件中也導入了Foundation頭文件,是這樣的么?打開UIKit頭文件:

沒有發現,但是有UITouch頭文件,在該文件內部有:

#import <Foundation/Foundation.h>?
#import <CoreGraphics/CoreGraphics.h>?
#import <UIKit/UIKitDefines.h>

?

因此可知,Mac OS X和iOS都使用了Foundation基礎框架。該框架中有很多日后開發常用的API。以下就常用的類和結構做個介紹。

?

NSObjct

NSObject類,是ObjC類族中的根類。NSObject有一些高級特性支持,在靈活和高效開發中十分常用。

perform…方法和selector

selector是ObjC高級的語法特性,可看作C函數指針,或者Java反射API的Method類相關內容。看一下下面的代碼,讀者就應該能理解,首先我有個Book類:

#import <Foundation/Foundation.h>

@interface Book : NSObject {

}

-(void) printInformation;

@end

可以看到有個方法printInformation。一般調用該方法大致是這樣:

Book *book=[[Book alloc] init];?
[book printInformation];

如果使用selector和perform…方法可這樣調用:

Book *book=[[Book alloc] init];?
[book printInformation];

SEL method=@selector(printInformation);?
id object=book;?
[object performSelector:method];

這里,SEL是selector類型。方法可通過這種機制成為變量,傳遞到任意位置調用,可編寫極為靈活和復用性高的代碼。

這里調用的方法沒有參數傳遞,是最簡單的情況,下面演示一下帶參數的,修改Book類的方法:

#import <Foundation/Foundation.h>

@interface Book : NSObject {

}

-(void) printInformation:(NSString *)bookName;

@end

帶一個參數。那么上面的兩種調用方法的代碼將修改為:

Book *book=[[Book alloc] init];?
[book printInformation:@"Objective-C Tutorial"];

SEL method=@selector(printInformation:);?
id object=book;?
[object performSelector:method withObject:@"Objective-C Tutorial"];

如果多個參數呢?比如:

-(void) printInformation:(NSString *)bookName bookPrice:(NSString *)price;

?

那么:

Book *book=[[Book alloc] init];?
[book printInformation:@"Objective-C Tutorial" bookPrice:@"$17.00"];

SEL method=@selector(printInformation:bookPrice:);?
id object=book;?
[object performSelector:method withObject:@"Objective-C Tutorial" withObject:@"$17.00"];

再多的參數,直接這樣調用就不行了。需要借助NSInvocation類。具體實現就不展開說了。

perform…方法調用還有一個方便的機制,就是延時調用。可以看作一次性的timer。比如:

Book *book=[[Book alloc] init];?
[book printInformation:@"Objective-C Tutorial"];

SEL method=@selector(printInformation:);?
id object=book;?
[object performSelector:method withObject:@"Objective-C Tutorial" afterDelay:10];?
NSLog(@"view did load ok.");

可以看到多了個參數,afterDelay,參數值單位是秒。結果:

2011-05-19 15:27:56.930 iOSSimpleDemo[6793:207] Objective-C Tutorial?
2011-05-19?15:27:56.932?iOSSimpleDemo[6793:207] view did load ok.?
2011-05-19?15:28:06.931?iOSSimpleDemo[6793:207] Objective-C Tutorial

從日志可知,帶afterDelay參數的方法調用,將延時10秒鐘再執行。而主線程并不阻塞,而是繼續打印了后面的“view did load ok.”日志。這里的實現原理是,調用afterDelay參數的方法后,將該方法調用存入隊列,主線程在10秒后,再從隊列中取得它并調用。

判斷對象是否相等

這里涉及到兩個方法:

  • isEqual
  • hash

前者,比如:

BOOL isEqual=[book isEqual:book];?
NSLog(@"book is equals: %@",isEqual?@"yes":@"no");

和Java類似的,相等的對象,它們的hash值必須是相同的。這是因為,hash值將用于依賴hash值的集合元素定位,比如HashSet。hash值不同但相等的對象,將導致在集合中,比如HashSet放入多個。另外,如果自行設置hash值(默認是內存值),不能使用可能變化的值,比如你有個類,User,該類有個屬性,name,如果這個name是可改的,就不要用該屬性的hash值(字符串的hash值)作為User類的hash方法返回值。

?

獲取類對象

有時候,想知道需要得到Class的類對象,可以調用class方法:

NSLog(@"Book class: %@",[book class]);

有時候,想要知道超類,可以比如[book superclass]。

?

管理引用計數

方法比較多:

– retain? required method?
– release? required method?
– autorelease? required method?
– retainCount? required method

這里不細說了,到內存管理部分會詳細講的。

?

有關對象關系,行為等的測試

這些方法,在高級開發中常用。比如,判斷一個類型是不是屬于某個類型:

NSLog(@"book instance is kind of Class Book? %@",?
????????? [book isKindOfClass:[Book class]]?@"yes":@"no");

當然子類也是超類類型。比如:

NSLog(@"book instance is kind of Class Book? %@",?
????????? [book isKindOfClass:[NSObject class]]?@"yes":@"no");

以上兩個語句都會返回yes。

如果要求嚴格判斷一個實例是不是屬于一個類的,可:

NSLog(@"book instance is kind of Class Book? %@",?
????????? [book isMemberOfClass:[NSObject class]]?@"yes":@"no");

?

這里會返回no,因為book是Book類的實例,而不是嚴格意義上的NSObject類的實例。

另外,還有個高級的用法,就是判斷實例是不是代理類。即:

- (BOOL)isProxy

這里先要說說Foundation kit提供的代理類用法,即NSProxy。先寫個Book的代理類。頭文件:

#import <Foundation/Foundation.h>?
#import "Book.h"

@interface BookProxy : NSProxy {?
??? Book *book;?
}

-(id)init;

@property(nonatomic,retain) Book *book;

@end

實現:

#import "BookProxy.h"

@implementation BookProxy

@synthesize book;

-(id)init{?
??? return self;?
}

- (void)forwardInvocation:(NSInvocation *)anInvocation{?
??? [anInvocation setTarget:book];?
????
??? NSLog(@"call proxy instance …");?
??? [anInvocation invoke];?
??? NSLog(@"call proxy instance ok.");?
????
??? return;?
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{?
??? return [book methodSignatureForSelector:aSelector];?
}

@end

調用:

BookProxy *bookProxy=[[BookProxy alloc]init];?
bookProxy.book=book;

book=(Book *)bookProxy;?
[book printInformation:@"Objective-C Tutorial"];

NSLog(@"Book class: %@",[book class]);?
NSLog(@"book instance is kind of Class Book? %@",?
????? [book isKindOfClass:[NSObject class]]?@"yes":@"no");

這里要注意的是,NSProxy類沒有init方法(是NSObject類才有),需要自己寫一個。從BookProxy到Book要做一次強制轉型。之后,使用上就是透明代理了。isKindOfClass會返回yes。isMemberOfClass會返回no。但是,怎么區分是子類還是代理類呢?就用到這個了:

- (BOOL)isProxy

行為,英文是behavior,是動作嘛,一般指的就是方法。有時候,需要判斷一個對象,是否能對一個selector做出回應。比如:

SEL method=@selector(printInformation:);?
id object=book;?
[object performSelector:method withObject:@"Objective-C Tutorial" afterDelay:10];?
NSLog(@"view did load ok.");

NSLog(@"book has this selector: %@",[book respondsToSelector:method]?@"yes":@"no");

這里打印的是yes。

有的時候,想判斷某個實例是否實現了某個協議,可以:

NSLog(@"book implement NSObject protocol: %@",?
?????????[book conformsToProtocol:@protocol(NSObject)]?@"yes":@"no");

還有一些方法,可以查看NSObject類reference學習。

?

常用的結構體

結構體是C提供的一種數據類型。在ObjC中也常使用。比如:

  • NSRange
  • NSPoint
  • NSSize
  • NSRect

以NSRange為例:

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

上面代碼是從NSRange頭文件中找到的。

可以用三種方式為結構體賦值。比如:

NSRange range;?
range.location=17;?
range.length=4;

還可以:

NSRange range={17,4};

或者:

NSRange range=NSMakeRange(17, 4);

第三種是比較常用的方式,因為是通過函數調用,可在各種情況下使用。

使用結構體作為數據類型而不是ObjC對象,是從性能上的考慮。后者在動態分配內存上代價較大。

?

NSString

NSString類似Java中的String類,提供了很多便利的對字符串操作的方法。字符串操作在開發中是十分常用的。

?

如何創建字符串

最普通的創建字符串的方式是:

@"hello"

我測試了一下這個:

NSLog(@"print string hash, instance1: %i, instance2: %i",?
????????? [@"hello" hash],[@"hello" hash]);

日志顯示:

print string hash, instance1: -1553534663, instance2: -1553534663

這說明什么呢?兩次創建的對象,是內存中同一個實例。這和Java中的String實例化原理是相同的。即系統要保持一個字符串池。當聲明的字符串在池中已存在了,就只提供一個指向存在字符串的指針。這也是為什么字符串是不可修改對象的原因之一。

字符串還提供了stringWithFormat方法創建可插入參數的字符串:

NSString *content=[NSString stringWithFormat:@"用戶姓名:%@",@"張三"];

這里使用的是類方法,而不是實例方法。可以將這個方法看作簡單工廠模式。

?

字符串長度

得到字符串長度,是常見的操作:

unsigned int length=[content length];

?

字符串的相等

有的時候,需要判斷兩個NSString字符串是否相等。這里有兩個概念:

  • 對象不一樣,但是他們的字符值是一樣的
  • 對象是同一個,即在內存中同一個區域

這個概念在各種面向對象語言中應該都有。我拿Java舉例子,比如:

String s="hello";

這個語義上和:

NSString *s=@"hello";

是一樣的。即查找字符串內存池,看是否有包含相同字符串的對象,如果有,就不重復創建,而是引用池中的字符串對象。因此,用上面語法,用不同變量名創建多個相同字符串的變量,它們字符串值一樣,而且,hash值也一樣,即在內存中也是同一個對象。

但是Java如果:

String s=new String("hello");

就是強制創建新的對象,那么字符串值一樣,但是內存上不是同一個對象,因為這樣創建不使用字符串池。

問題來了,ObjC怎么寫出這樣的語句?我沒有找到。應該是有的吧。

如果在ObjC中判斷兩個字符串是不是相同的對象,用==即可。如果是判斷字符串值是否相等:

NSString *s=@"hello";?
[s isEqualToString:@"hello"];

建議使用isEqualToString針對字符串值是否相等時使用,而不是==,因為不排除有情況是內存中不是相同對象,但字符串值是相同的情況。

?

字符串的排序

字符串排序,比如按照首字母排序,兩個字符串,比較誰應該排在前面。這時要用到:

- (NSComparisonResult)compare:(NSString *)aString

比如:

NSString *s1=@"Apple";?
NSString *s2=@"Google";?
NSComparisonResult result=[s1 compare:s2];

switch (result) {?
??? case NSOrderedSame:?
??????? NSLog(@"is same string");?
??????? break;?
??? case NSOrderedAscending:?
??????? NSLog(@"ascending");?
??????? break;?
??? case NSOrderedDescending:?
??????? NSLog(@"descending");?
??????? break;?
??? default:?
??????? break;?
}

?

結果是:

ascending

也就是說s1和s2之間的順序是升序,即s1應該排在前面。

另外,可以使用這個方法:

- (NSComparisonResult)compare:(NSString *)aString options:(NSStringCompareOptions)mask

進行特殊的大小比較,mask確定特殊比較的類型:

  • 大小寫敏感
  • 大小寫不敏感
  • 數字排序,這個要特別說一下,數字和文字有不同,比如1和9,1排在9前面,無論是字符還是數字都沒問題。如果100和99,字符比較就會出現100在99之前的問題

?

是否包含子字符串

經常要用到這樣的字符串功能,判斷字符串:

  • - (BOOL)hasPrefix:(NSString *)aString,是否某個字符串開始的
  • - (BOOL)hasSuffix:(NSString *)aString,是否某個字符串結束的
  • - (NSRange)rangeOfString:(NSString *)aString,字符串中是否有子字符串,如果有返回NSRange結構體,包含起始位置和長度,如沒有,range.location==NSNotFound

NSMutableString

可變字符串。NSString是不可變的,類似Java的String;NSMutableString類似Java的StringBuffer。

具體方法使用,見Reference。

?

使用集合

?

NSArray

NSArray是最常用的集合類型。它類似Java中的ArrayList,但是又有所區別,就是一旦創建就不能再改變。

NSArray有兩個限制:

  • 不能存儲C語言的基本數據類型,比如int、float、enum、struct等
  • 不能存儲nil對象

比較常用的創建NSArray實例的方法是:

+ (id)arrayWithObjects:(id)firstObj, …

其他的看Reference吧。

獲取NSArray的元素數:

- (NSUInteger)count

從指定的位置,比如第2個下標獲取元素,要用到這個:

- (id)objectAtIndex:(NSUInteger)index

結合上面的count方法,可以對NSArray做循環迭代了。

?

NSMutableArray

這個類,允許添加和刪除元素。

添加:

- (void)addObject:(id)anObject

刪除:

- (void)removeObject:(id)anObject

或者根據下標刪除:

- (void)removeObjectAtIndex:(NSUInteger)index

?

NSEnumerator

在Java中有迭代器Iterator,在ObjC中類似功能的類是NSEnumerator。比如:

NSArray *array=[NSArray arrayWithObjects:@"h1",@"h2",nil];?
NSEnumerator *enumerator=[array objectEnumerator];?
NSString *string;?
while (string=[enumerator nextObject]) {?
??? NSLog(@"element: %@",string);?
}

?

快速枚舉

很類似Java中的:

for (String s:array) {?
????
}

?

ObjC提供了這樣的語法支持:

NSArray *array=[NSArray arrayWithObjects:@"h1",@"h2",nil];

for (NSString *string in array) {?
??? NSLog(@"element: %@",string);?
}

?

NSSet和NSMutableSet

類似Java中的HashSet。NSSet是不可變的,而NSMutableSet是可變的。使用和NSArray類似。

?

NSDictionary和NSMutableDictionary

類似Java中的HashMap。

可通過:

- (id)initWithObjectsAndKeys:(id)firstObject , …

初始化帶鍵值對的NSDictionary。比如:

NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:?
??? @"value1", @"key1", @"value2", @"key2", nil];

NSMutableDictionary增加了:

- (void)setObject:(id)anObject forKey:(id)aKey

可加入新的鍵值對。和刪除鍵值對:

- (void)removeObjectForKey:(id)aKey

?

各種數值

上面提到了,C語言的基本數據類型是不能存儲到集合里的。需要將這些數據類型封裝到對象中才能放入。遺憾的是,ObjC不像Java或者.net,提供了自動裝箱和拆箱的功能,即編程語言支持自動將基本型包裝成對象,或者相反的操作。ObjC提供了手動的方式。下面介紹一下。

NSNumber

NSNumber提供了很多類似這樣的類方法:

+ (NSNumber *)numberWithInt:(int)value

用來將數值型基本數據類型包裝成ObjC對象。比如,把int型包裝成ObjC的實例:

NSNumber *number=[NSNumber numberWithInt:24];

這個number已經是ObjC對象了,可以放置到集合中去了。

反過來:

int n=[number intValue];

?

NSValue

NSNumber只能包裝數值。NSValue可以包裝任意類型數值,比如將結構體包裝放入到集合中。

下面示例將NSRange結構體放入到NSArray中:

NSRange numberRange={10,29};?
NSValue *value=[NSValue valueWithRange:numberRange];?
NSArray *array=[NSArray arrayWithObjects:@"h1",value,nil];

這里使用的方法valueWithRange,是NSValue為常用結構體提供的便利方法。如果是自己定義的結構體呢?

比如在頭文件中定義了struct:

typedef struct{?
??? NSString *name;?
??? int rank;?
}User;

?

在代碼中創建集合,通過NSValue包裝結構體存入集合,并且從集合中取出結構體:

User user={@"張三",2};?
NSValue *userValue=[NSValue valueWithBytes:&user objCType:@encode(User)];?
NSArray *myArray=[NSArray arrayWithObjects:@"h1",userValue,nil];

userValue=[myArray objectAtIndex:1];?
[userValue getValue:&user];?
NSLog(@"用戶姓名:?%@",user.name);

?

NSNull

nil有特殊含義,因此不能在集合中保存。那么,如果需要存入空的內容,怎么辦呢?

見下面代碼:

NSRange numberRange={10,29};?
NSValue *value=[NSValue valueWithRange:numberRange];?
NSArray *array=[NSArray arrayWithObjects:[NSNull null],value,nil];

那么,檢查是否為null,可以直接用:

if ([array objectAtIndex:0]==[NSNull null]) {?
??? NSLog(@"element is null.");?
}

?

NSDate

在Java里有java.util.Date類,在ObjC中對應的是NSDate。寫個最簡單的示例:

NSDate *date=[NSDate date];?
NSLog(@"time:?%@",date);

將打印出:

time: 2011-05-26 11:44:37 +0800

date方法將返回表示當前時間的NSDate對象。

下面的方法:

- (id)initWithTimeIntervalSinceNow:(NSTimeInterval)seconds

可返回當前時間間隔秒數的日期對象。

下面的方法:

+ (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date

返回和指定日期對象間隔時間的日期對象。

下面方法:

- (BOOL)isEqualToDate:(NSDate *)anotherDate

判斷日期是否相等。

下面方法:

- (NSDate *)earlierDate:(NSDate *)anotherDate

返回更早的日期對象。

- (NSComparisonResult)compare:(NSDate *)anotherDate

比較日期大小。類似NSString的compare方法。

- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate

返回日期之間間隔的秒數。

?

NSData

在C語言中,經常將數據緩沖區作為參數傳遞給函數。這時需要將緩沖區的指針傳遞給函數。如果是動態分配的緩沖區,那么還要考慮何時釋放內存。

在ObjC中,可以使用NSData簡化緩沖區的使用方式。比如:

char *s="hello everyone";?
NSData *data=[NSData dataWithBytes:s length:strlen(s)+1];?
NSLog(@"data: %s",[data bytes]);

這里char *s不是動態分配內存的,這里只是演示一下,通過NSData的類方法,可以將s的字節數組復制到NSData中。NSData是ObjC的類實例,有內存管理機制,這里按照ObjC內存管理原則應該是已經autorelease了的。

總結

以上是生活随笔為你收集整理的ObjC: Foundation Kit的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。