个性化阅读
专注于IT技术分析

Objective-C Foundation框架全解 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C复合对象解析

从之前的章节我们已经学完所有的Objective-C语言基础了,后面开始进入高级开发的内容,包括运行时、内存管理等。

这一章主要讨论Foundation框架,说到Foundation框架,又不得不说一下Cocoa和Cocoa Touch。首先这两个都是工具集,前者用于macOS开发,后者用于iOS开发,这两个工具集有一些相同的框架,Foundation框架就是其中之一,另外Core Data也是。

另外,macOS的UI开发使用的框架是AppKit,而iOS开发使用的UI框架是UIKit。

Foundation框架是OC编程的基本框架,除了提供OOP的基本特性之外,主要还提供了:

  • 一些列基本工具类,以及一些常用的数据结构。
  • 支持Unicode字符串、对象持久化和对象分发。
  • 日期和时间处理。
  • 异常和错误处理。
  • 文件处理。
  • URL加载系统。

当然还有其它功能,其它的后面还是详细讨论。顺便说下,Foundation框架提供的数据结构太少了,起码再提供个堆(heap)也好。

下面我们详细介绍以上提供的功能,其中一般来说,使用指定的类,只需要导入指定的头文件即可,例如使用NSString,那么就导入Foundation/NSString.h头文件,但是为了避免导入太多的类,直接导入Foundation/Foundation.h头文件即可。

数据结构

Foundation框架中提供的数据结构也就是两种:数组和散列表,数组又包括NSArray和NSMutableArray,散列表包括NSDictionary和NSMutableDictionary,以及NSSet和NSMutableSet。

使用的时候要注意其时间复杂度,否则有可能影响APP运行效率,关于数据结构和算法更多内容,可以在srcmini中搜索获取完整的教程。

NSArray和NSMutableArray

NSArray和它的子类NSMutableArray都是有序数组,前者是静态数组,元素不可变,后者是动态数组,元素可变。因而一般来说,NSArray是直接初始化,然后使用,除非有特殊的更改元素的需求(有提供方法),否则数组都是静态不变的。而NSMutableArray在之后的使用中可能会频繁更改元素,建议使用的时候考虑元素可变和不可变的因素。

初始化NSArray可以使用initWithObjects这样的静态方法,但是更简单的方式是使用数组字面量,如下:

NSArray *array = @[someObject, @"Hello, World!", @42];

@操作符将后面的东西转为对象,这也是常见的一种用法。

方法数组元素可以使用objectAtIndex:,更简单的方式是使用下标访问法:

id value = array[3];

下面是NSArray主要提供的功能说明:

  • 创建一个数组:使用静态方法,如array,arrayWtihArray,arrayWithObject等。
  • 初始化数组:init,initWithObjects等。
  • 数组查询:containsObject,objectAtIndex,ObjectAtIndexes等。
  • 查找元素索引:indexOfObject,indexOfObject:inRange等。
  • 给元素发送消息(每个元素执行指定操作):makeObjectsPerformSelector等。
  • 比较数组:isEqualToArray等。
  • 派生新的数组:如arrayByAddingObject。
  • 数组排序:如sortedArrayUsingFunction:context。

NSMutableArray是NSArray的子类,所以以上对NSMutableArray也适用。NSMutableArray额外提供对元素操作的功能:

  • removeAllObjects ——清空数组。
  • addObject——在数组的末尾插入一个给定的对象。
  • removeObjectAtIndex—用于删除特定索引中的对象
  • exchangeObjectAtIndex:withObjectAtIndex – 交换数组中的对象。
  • replaceObjectAtIndex:withObject – 用对象替换索引处的对象。

下面是一个使用示例:

#import <Foundation/Foundation.h>

int main() {
   NSArray *array = [[NSArray alloc]
   initWithObjects:@"string1", @"string2",@"string3",nil];
   NSString *string1 = [array objectAtIndex:0];
   NSLog(@"数组中下标0处的对象为 %@",string1);
   
   NSMutableArray *mutableArray = [[NSMutableArray alloc]init];
   [mutableArray addObject: @"string"];
   string1 = [mutableArray objectAtIndex:0];
   NSLog(@"mutableArray中下标0处的对象为 %@",string1); 
   return 0;
}

另外最新OC提供了泛型编程,可以在数组后面添加<Type>指定集合中的元素类型,类似于Java中的泛型。

遍历数组建议使用for-in循环,比block效率好。

NSDictionary和NSMutableDictionary

类似于上面的数组,字典也分可变和不可变两种,字典的元素的无序的,但是所有操作的时间效率都是最好的,当面向的数据不需要顺序的时候,优先使用字典。

字典中的每个元素为key-value键值对,使用方法初始化字典有点麻烦,如dictionaryWithObjects:forKeys:count,类似数组字面量使用@[],字典字面量使用@{},如:

NSDictionary *dictionary = @{
       @"anObject" : someObject,
    @"helloString" : @"Hello, World!",
    @"magicNumber" : @42,
         @"aValue" : someValue
};

要注意,字典中的key关键字也是一个对象,通常使用的是NSString对象。

在数组中访问一个元素可以使用下标,如array[1]。在字典中访问元素可以使用objectForKey方法,同样也可以使用简单的方式:

id value = dictionary[@"helloString"];

字典遍历同样建议使用for-in循环,其中每个元素为key。

NSDictionary的重要方法如下:

  • alloc/initWithObjectsAndKeys——使用从指定的值和键集构造的条目初始化新分配的字典。
  • valueForKey——返回与给定键关联的值。
  • count——返回字典中的条目数。

NSMutableDictionary的重要方法如下:

  • removeAllObjects——清空其词条的字典。
  • removeObjectForKey——从字典中删除给定的键及其关联值。
  • setValue:forKey——将给定的键值对添加到字典中。

下面是字典的一个简单例子:

#import <Foundation/Foundation.h>

int main() {
   NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
   @"string1",@"key1", @"string2",@"key2",@"string3",@"key3",nil];
   NSString *string1 = [dictionary objectForKey:@"key1"];
   NSLog(@"key的对象,字典中的key1是 %@",string1);
   
   NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
   [mutableDictionary setValue:@"string" forKey:@"key1"];
   string1 = [mutableDictionary objectForKey:@"key1"];
   NSLog(@"key的对象,mutableDictionary 中的key1是 %@",string1); 
   
   [pool drain];
   return 0;
}

NSSet和NSMutableSet

集合和字典是类似的,同样是基于散列,也是无序的,只不过不需要额外提供键值,并且集合中的元素唯一。

NSSet的重要方法如下:

  • alloc/initWithObjects——用指定对象列表中的成员初始化一个新分配的集合。
  • allObjects——返回一个包含集合成员的数组,如果集合没有成员,则返回一个空数组。
  • count——返回集合中成员的数目。

NSMutableSet继承自NSSet,因此NSSet的所有实例方法在NSMutableSet中都是可用的。

NSMutableSet的重要方法如下:

  • removeAllObjects——清空其所有成员的集合。
  • addObject – 如果该对象还不是集合的一个成员,则添加到集合。
  • removeObject——从集合中移除给定的对象。

下面是集合的一个简单例子:

#import <Foundation/Foundation.h>

int main() {
   NSSet *set = [[NSSet alloc]
   initWithObjects:@"string1", @"string2",@"string3",nil];
   NSArray *setArray = [set allObjects];
   NSLog(@"集合对象 %@",setArray);
   
   NSMutableSet *mutableSet = [[NSMutableSet alloc]init];
   [mutableSet addObject:@"string1"];
   setArray = [mutableSet allObjects];
   NSLog(@"mutableSet的对象 %@",setArray);
   return 0;
}

文本和字符串

Foundation支持创建和处理Unicode字符字符串,使用正则表达式查找模式,并执行文本的自然语言分析。

在这一部分,Foundation提供的功能主要是以字符为基本单位进行相关的操作,提供的主要类如下:

字符串

  • NSString:一个静态的纯文本Unicode字符串对象。
  • NSMutableString:一个动态的纯文本Unicode字符串对象。

字符串和元数据

  • NSAttributedString:具有与其文本部分相关属性(如视觉样式、超链接或可访问性数据)的字符串。
  • NSMutableAttributedString:一个可变的字符串对象,它还包含与其文本内容的各个部分相关联的属性(如可视样式、超链接或可访问性数据)。

字符

  • NSCharacterSet:表示用于搜索操作的一组固定的Unicode字符值的对象。
  • NSMutableCharacterSet:表示用于搜索操作的一组可变Unicode字符值的对象。
  • unichar:类型为UTF-16代码单元。

自然语言处理

  • NSLinguisticTagger:分析自然语言文本,标记部分语音和词汇类,识别名称,进行词化,确定语言和脚本。

模式匹配

  • NSScanner:一种字符串解析器,用于扫描字符集中的子字符串或字符,以及十进制、十六进制和浮点表示法中的数值。
  • NSRegularExpression:应用于Unicode字符串的已编译正则表达式的不可变表示。

本地化

  • NSLocale:有关用于格式化数据以供表示的语言、文化和技术约定的信息。
  • NSLocalizedStringFromTable:返回指定表中字符串的本地化版本。

时间和日期

NSDate和NSDateFormatter类提供了日期和时间的特性。

NSDateFormatter是一个帮助类,它支持将NSDate轻松地转换为NSString,反之亦然。

下面是一个简单的示例,演示如何将NSDate转换为NSString并返回到NSDate。

#import <Foundation/Foundation.h>

int main() {
   NSDate *date= [NSDate date];
   NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
   [dateFormatter setDateFormat:@"yyyy-MM-dd"];
   
   NSString *dateString = [dateFormatter stringFromDate:date];
   NSLog(@"Current date is %@",dateString);
   NSDate *newDate = [dateFormatter dateFromString:dateString];
   NSLog(@"NewDate: %@",newDate);
   return 0;
}

正如我们在上面的程序中看到的,我们在NSDate的帮助下得到了当前的时间。

NSDateFormatter是负责转换格式的类。

可以根据可用的数据更改日期格式。例如,当我们想要在上面的例子中添加时间时,日期格式可以更改为@“yyyy-MM-dd:hh:mm:ss”

异常处理

异常处理在Objective-C中是可用的,带有基础类NSException。

异常处理通过以下块实现:

  • @try — 这个块尝试执行一组语句。
  • @catch — 这个块试图在try块中捕获异常。
  • @finally — 这个块包含一组总是执行的语句。
#import <Foundation/Foundation.h>

int main() {
   NSMutableArray *array = [[NSMutableArray alloc]init];        
   
   @try  {
      NSString *string = [array objectAtIndex:10];
   } @catch (NSException *exception) {
      NSLog(@"%@ ",exception.name);
      NSLog(@"Reason: %@ ",exception.reason);
   }
   
   @finally  {
      NSLog(@"@@finaly Always Executes");
   }
   return 0;
}

文件处理

文件处理在NSFileManager类的帮助下可用。这些例子不适用于在线编译器。

用于文件处理的方法

用于访问和操作文件的方法列表如下所示。在这里,我们必须将FilePath1、FilePath2和FilePath字符串替换为所需的完整文件路径,以获得所需的操作。

// 1、检查某个路径上是否存在文件
NSFileManager *fileManager = [NSFileManager defaultManager];

// 获取文件目录
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [directoryPaths objectAtIndex:0];

if ([fileManager fileExistsAtPath:@""] == YES) {
   NSLog(@"File exists");
}    

// 2、比较两个文件内容
if ([fileManager contentsEqualAtPath:@"FilePath1" andPath:@" FilePath2"]) {
   NSLog(@"Same content");
}

// 3、检查是否可写、可读和可执行
if ([fileManager isWritableFileAtPath:@"FilePath"]) {
   NSLog(@"isWritable");
}

if ([fileManager isReadableFileAtPath:@"FilePath"]) {
   NSLog(@"isReadable");
}

if ( [fileManager isExecutableFileAtPath:@"FilePath"]) {
   NSLog(@"is Executable");
}

// 4、移动文件
if([fileManager moveItemAtPath:@"FilePath1" 
   toPath:@"FilePath2" error:NULL]) {
      NSLog(@"Moved successfully");
   }

// 5、复制文件
if ([fileManager copyItemAtPath:@"FilePath1" 
   toPath:@"FilePath2"  error:NULL]) {
      NSLog(@"Copied successfully");
   }

// 6、删除文件
if ([fileManager removeItemAtPath:@"FilePath" error:NULL]) {
   NSLog(@"Removed successfully");
}

// 7、读取文件
NSData *data = [fileManager contentsAtPath:@"Path"];

// 8、写入文件
[fileManager createFileAtPath:@"" contents:data attributes:nil];

URL加载系统

在访问URL时,URL加载是很有用的,从互联网上获得的信息。它在下列各类的帮助下得到:

  • NSMutableURLRequest
  • NSURLConnection
  • NSURLCache
  • NSURLAuthenticationChallenge
  • NSURLCredential
  • NSURLProtectionSpace
  • NSURLResponse
  • NSURLDownload
  • NSURLSession

下面是一个简单的url加载示例,这不能在命令行上运行,我们需要创建Cocoa应用程序。

这可以通过在XCode中选择New,然后在出现的窗口的OS X应用程序部分中Project和select Cocoa Application来实现。

通过单击next完成步骤的顺序,你将被要求提供一个项目名称,你可以给它一个名称。

h头文件如下所示:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;

@end

AppDelegate.m更新文件如下:

#import "AppDelegate.h"

@interface SampleClass:NSObject<NSURLConnectionDelegate> {
   NSMutableData *_responseData;
}

- (void)initiateURLConnection;
@end

@implementation SampleClass
- (void)initiateURLConnection {
   
   // 创建请求.
   NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://date.jsontest.com"]];

   // 创建url连接和fire请求
   NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
   [conn start];
}

#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
   // 已收到响应,这是我们初始化你创建的实例变量的地方
   // 我们可以在didReceiveData方法中向它添加数据
   // 而且,每次重定向时都要调用此方法,以便重新初始化它
   // 也可以用来清理
   _responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
   // 将新数据附加到已声明的实例变量
   [_responseData appendData:data];
}

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
   willCacheResponse:(NSCachedURLResponse*)cachedResponse {
   // 返回nil,表示不需要为此连接存储缓存的响应
   return nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
   // 请求已经完成,数据已经收到
   // 现在可以解析实例变量中的内容了
   NSLog(@"%@",[[NSString alloc]initWithData:_responseData encoding:NSUTF8StringEncoding]);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
   // 由于某种原因,请求失败了!
   // 检查error
}
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass initiateURLConnection];
   // 在这里插入代码来初始化你的应用程序
}
@end

在上面的程序中,我们创建了一个简单的URL连接,它是JSON格式的时间,并显示时间。

赞(0)
未经允许不得转载:srcmini » Objective-C Foundation框架全解 – Objective-C开发教程

评论 抢沙发

评论前必须登录!