Foundation框架

转自:http://www.cnblogs.com/kenshincui/p/3885689.html#io

Foundation概述

为什么前面说的内容中新建一个类的时候我们都是选择Cocoa Class呢?Cocoa是什么呢?

Cocoa不是一种编程语言(它可以运行多种编程语言),它也不是一个开发工具(通过命令行我们仍然可以开发Cocoa程序),它是创建Mac OS X和IOS程序的原生面向对象API,为这两者应用提供了编程环境。

我们通常称为“Cocoa框架”,事实上Cocoa本身是一个框架的集合,它包含了众多子框架,其中最重要的要数“Foundation”和“UIKit”。前者是框架的基础,和界面无关,其中包含了大量常用的API;后者是基础的UI类库,以后我们在IOS开发中会经常用到。这两个框架在系统中的位置如下图:

Cocoa

其实所有的Mac OS X和IOS程序都是由大量的对象构成,而这些对象的根对象都是NSObject,NSObject就处在Foundation框架之中,具体的类结构如下:

Foundation1

Foundation2

Foundation3

通常我们会将他们分为几类:

  1. 值对象
  2. 集合
  3. 操作系统服务:文件系统、URL、进程通讯
  4. 通知
  5. 归档和序列化
  6. 表达式和条件判断
  7. Objective-C语言服务

UIKit主要用于界面构架,这里我们不妨也看一下它的类结构:

UIKit

常用结构体

在Foundation中定义了很多常用结构体类型来简化我们的日常开发,这些结构体完全采用Objective-C定义,和我们自己定义的结构体没有任何区别,之所以由框架为我们提供完全是为了简化我们的开发。常用的结构体有NSRange、NSPoint、NSSize、NSRect等

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>

/*NSRange表示一个范围*/
void test1(){
    NSRange rg={3,5};//第一参数是起始位置第二个参数是长度
    //NSRange rg;
    //rg.location=3;
    //rg.length=5;
    //NSRange rg={.location=3,.length=5};
    //常用下面的方式定义 NSRange rg2=NSMakeRange(3,5);//使用NSMakeRange定义一个NSRange 
    //打印NSRange可以使用Foundation中方法 NSLog(@"rg2 is %@", NSStringFromRange(rg2));//注意不能直接NSLog(@"rg2 is %@", rg2),因为rg2不是对象(准确的说%@是指针)而是结构体
}
/*NSPoint表示一个点*/
void test2(){
    NSPoint p=NSMakePoint(10, 15);//NSPoint其实就是CGPoint
    //这种方式比较常见 NSPoint p2=CGPointMake(10, 15);
    NSLog(NSStringFromPoint(p2));
}
/*NSSize表示大小*/
void test3(){
    NSSize s=NSMakeSize(10, 15);//NSSize其实就是CGSize
    //这种方式比较常见 CGSize s2=CGSizeMake(10, 15);
    NSLog(NSStringFromSize(s2));
}
/*NSRect表示一个矩形*/
void test4(){
    NSRect r=NSMakeRect(10, 5, 100, 200);//NSRect其实就是CGRect
    //这种方式比较常见 NSRect r2=CGRectMake(10, 5, 100, 200);
    NSLog(NSStringFromRect(r2));
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        test1();
        test2();
        test3();
        test4();
    } return 0;
}
可以看到对于常用结构体在Foundation框架中都有一个对应的make方法进行创建,这也是我们日后比较常用的操作;而且与之对应的还都有一个NSStringFromXX方法来进行字符串转换,方便我们调试。上面也提到NSSize其实就是CGSize,NSRect其实就是CGRect,我们可以通过查看代码进行确认,例如NSSize定义:

NSSize

继续查看CGSize的代码:

CGSize

日期

接下来熟悉一下Foundation框架中日期的操作

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>


int main(int argc, const char * argv[]) {
    
    NSDate *date1=[NSDate date];//获得当前日期
    NSLog(@"%@",date1); //结果:2014-07-16 07:25:28 +0000
    
    NSDate *date2=[NSDate dateWithTimeIntervalSinceNow:100];//在当前日期的基础上加上100秒,注意在ObjC中多数时间单位都是秒
    NSLog(@"%@",date2); //结果:2014-07-16 07:27:08 +0000
    
    NSDate *date3=[NSDate distantFuture];//随机获取一个将来的日期
    NSLog(@"%@",date3); //结果:4001-01-01 00:00:00 +0000
    
    NSTimeInterval time=[date2 timeIntervalSinceDate:date1];//日期之差,返回单位为秒
    NSLog(@"%f",time); //结果:100.008833
    
    NSDate *date5=[date1 earlierDate:date3];//返回比较早的日期
    NSLog(@"%@",date5); //结果:2014-07-16 07:25:28 +0000
    
    //日期格式化
    NSDateFormatter *formater1=[[NSDateFormatter alloc]init];
    formater1.dateFormat=@"yy-MM-dd HH:mm:ss";
    NSString *datestr1=[formater1 stringFromDate:date1];
    NSLog(@"%@",datestr1); //结果:14-07-16 15:25:28
    //字符串转化为日期
    NSDate *date6=[formater1 dateFromString:@"14-02-14 11:07:16"];
    NSLog(@"%@",date6); //结果:2014-02-14 03:07:16 +0000

    return 0;
}

字符串

不可变字符串

在ObjC中字符串操作要比在C语言中简单的多,在下面的例子中你将看到字符串的初始化、大小写转化、后缀前缀判断、字符串比较、字符串截取、字符串转换等,通过下面的例子我们基本可以掌握常用的字符串操作(注意这些内容虽然基本,但却是十分常用的操作,需要牢记):

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>


/**字符串操作*/
void test1(){
    char *str1="C string";//这是C语言创建的字符串
    NSString *str2=@"OC string";//ObjC字符串需要加@,并且这种方式创建的对象不需要自己释放内存

    //下面的创建方法都应该释放内存
    NSString *str3=[[NSString alloc] init];
    str3=@"OC string";
    NSString *str4=[[NSString alloc] initWithString:@"Objective-C string"];
    NSString *str5=[[NSString alloc] initWithFormat:@"age is %i,name is %.2f",19,1.72f];
    NSString *str6=[[NSString alloc] initWithUTF8String:"C string"];//C语言的字符串转换为ObjC字符串

    //以上方法都有对应静态方法(一般以string开头),不需要管理内存(系统静态方法一般都是自动释放)
    NSString *str7=[NSString stringWithString:@"Objective-C string"];
}
void test2(){
    NSLog(@"\"Hello world!\" to upper is %@",[@"Hello world!" uppercaseString]);
    //结果:"Hello world!" to upper is HELLO WORLD!
    NSLog(@"\"Hello world!\" to lowwer is %@",[@"Hello world!" lowercaseString]);
    //结果:"Hello world!" to lowwer is hello world!
     
    //首字母大写,其他字母小写
    NSLog(@"\"Hello world!\" to capitalize is %@",[@"Hello world!" capitalizedString]);
    //结果:"Hello world!" to capitalize is Hello World!
     
    BOOL result= [@"abc" isEqualToString:@"aBc"];
    NSLog(@"%i",result);
    //结果:0
    NSComparisonResult result2= [@"abc" compare:@"aBc"];//如果是[@"abc" caseInsensitiveCompare:@"aBc"]则忽略大小写比较
    if(result2==NSOrderedAscending){
        NSLog(@"left<right.");
    }else if(result2==NSOrderedDescending){
        NSLog(@"left>right.");
    }else if(result2==NSOrderedSame){
        NSLog(@"left=right.");
    }
    //结果:left>right.
}
void test3(){
    NSLog(@"has prefix ab? %i",[@"abcdef" hasPrefix:@"ab"]);
    //结果:has prefix ab? 1
    NSLog(@"has suffix ab? %i",[@"abcdef" hasSuffix:@"ef"]);
    //结果:has suffix ab? 1
    NSRange range=[@"abcdefabcdef" rangeOfString:@"cde"];//注意如果遇到cde则不再往后面搜索,如果从后面搜索或其他搜索方式可以设置第二个options参数
    if(range.location==NSNotFound){
        NSLog(@"not found.");
    }else{
        NSLog(@"range is %@",NSStringFromRange(range));
    }
    //结果:range is {2, 3}
}
//字符串分割
void test4(){
    NSLog(@"%@",[@"abcdef" substringFromIndex:3]);//从第三个索引开始(包括第三个索引对应的字符)截取到最后一位
    //结果:def
    NSLog(@"%@",[@"abcdef" substringToIndex:3]);从0开始截取到第三个索引(不包括第三个索引对应的字符)
    //结果:abc
    NSLog(@"%@",[@"abcdef" substringWithRange:NSMakeRange(2, 3)]);
    //结果:cde
    NSString *str1=@"12.abcd.3a";
    NSArray *array1=[str1 componentsSeparatedByString:@"."];//字符串分割
    NSLog(@"%@",array1);
     /*结果:
      (
         12,
         abcd,
         3a
      )
      */
 
}
//其他操作
void test5(){
    NSLog(@"%i",[@"12" intValue]);//类型转换
    //结果:12
    NSLog(@"%zi",[@"hello world,世界你好!" length]);//字符串长度注意不是字节数
    //结果:17
    NSLog(@"%c",[@"abc" characterAtIndex:0]);//取出制定位置的字符
    //结果:a
    const char *s=[@"abc" UTF8String];//转换为C语言字符串
    NSLog(@"%s",s);
    //结果:abc
}

int main(int argc, const char * argv[]) {
    test1();
    test2();
    test3();
    test4();
    test5();
    return 0;
}

注意:上面代码注释中提到的需要释放内存指的是在MRC下的情况,当然本质上在ARC下也需要释放,只是这部分代码编译器会自动创建。

扩展--文件操作

在ObjC中路径、文件读写等操作是利用字符串来完成的,这里通过几个简单的例子来演示(首先在桌面上新建一个test.txt文件,里面存储的内容是”hello world,世界你好!”)

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>


void test1(){
    //读取文件内容
    NSString *path=@"/Users/kenshincui/Desktop/test.txt";
    NSString *str1=[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    //注意上面也可以使用gb2312 gbk等,例如kCFStringEncodingGB_18030_2000,但是需要用CFStringConvertEncodingToNSStringEncoding转换
    NSLog(@"str1 is %@",str1);
    //结果:str1 is hello world,世界你好!

    
    
    
    //上面我们看到了读取文件,但并没有处理错误,当然在ObjC中可以@try @catch @finnally但通常我们并不那么做
    //由于我们的test.txt中有中文,所以使用下面的编码读取会报错,下面的代码演示了错误获取的过程
    NSError *error;
    NSString *str2=[NSString stringWithContentsOfFile:path encoding:kCFStringEncodingGB_18030_2000 error:&error];//注意这句话中的error变量是**error,就是指针的指针那就是指针的地址,由于error就是一个指针此处也就是error的地址&error,具体原因见下面补充
    if(error){
        NSLog(@"read error ,the error is %@",error);
    }else{
        NSLog(@"read success,the file content is %@",str2);
    }
    //结果:read error ,the error is Error Domain=NSCocoaErrorDomain Code=261 "The file couldn’t be opened using the specified text encoding." UserInfo=0x100109620 {NSFilePath=/Users/kenshincui/Desktop/test.txt, NSStringEncoding=1586}

    
    
    
    //读取文件内容还有一种方式就是利用URl,它除了可以读取本地文件还可以读取网络文件
    //NSURL *url=[NSURL URLWithString:@"file:///Users/kenshincui/Desktop/test.txt"];
    NSURL *url=[NSURL URLWithString:@"http://www.apple.com"];
    NSString *str3=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"str3 is %@",str3);
}
void test2(){
    //下面是文件写入
    NSString *path1=@"/Users/kenshincui/Desktop/test2.txt";
    NSError *error1;
    NSString *str11=@"hello world,世界你好!";
    [str11 writeToFile:path1 atomically:YES encoding:NSUTF8StringEncoding error:&error1];//automically代表一次性写入,如果写到中间出错了最后就全部不写入
    if(error1){
        NSLog(@"write fail,the error is %@",[error1 localizedDescription]);//调用localizedDescription是只打印关键错误信息
    }else{
        NSLog(@"write success!");
    }
    //结果:write success!
}
//路径操作
void test3(){
    NSMutableArray *marray=[NSMutableArray array];//可变数组
    [marray addObject:@"Users"];
    [marray addObject:@"KenshinCui"];
    [marray addObject:@"Desktop"];

    NSString *path=[NSString pathWithComponents:marray];
    NSLog(@"%@",path);//字符串拼接成路径
    //结果:Users/KenshinCui/Desktop

    NSLog(@"%@",[path pathComponents]);//路径分割成数组
    /*结果: 
     (
        Users,
        KenshinCui,
        Desktop
    )
    */

    NSLog(@"%i",[path isAbsolutePath]);//是否绝对路径(其实就是看字符串是否以“/”开头)
    //结果:0
    NSLog(@"%@",[path lastPathComponent]);//取得最后一个目录
    //结果:Desktop
    NSLog(@"%@",[path stringByDeletingLastPathComponent]);//删除最后一个目录,注意path本身是常量不会被修改,只是返回一个新字符串
    //结果:Users/KenshinCui
    NSLog(@"%@",[path stringByAppendingPathComponent:@"Documents"]);//路径拼接
    //结果:Users/KenshinCui/Desktop/Documents
}
 //扩展名操作
void test4(){
    NSString *path=@"Users/KenshinCui/Desktop/test.txt";
    NSLog(@"%@",[path pathExtension]);//取得扩展名,注意ObjC中扩展名不包括"."
    //结果:txt
    NSLog(@"%@",[path stringByDeletingPathExtension]);//删除扩展名,注意包含"."
    //结果:Users/KenshinCui/Desktop/test
    NSLog(@"%@",[@"Users/KenshinCui/Desktop/test" stringByAppendingPathExtension:@"mp3"]);//添加扩展名
    //结果:Users/KenshinCui/Desktop/test.mp3
}

int main(int argc, const char * argv[]) {
    test1();
    test2();
    test3();
    test4();
    return 0;
}

注意:在上面的例子中我们用到了可变数组,下面会专门介绍。

可变字符串

我们知道在字符串操作过程中我们经常希望改变原来的字符串,当然这在C语言中实现比较复杂,但是ObjC为我们提供了新的可变字符串类NSMutableString,它是NSString的子类。

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>


int main(int argc, const char * argv[]) {
    
    /*可变字符串,注意NSMutableString是NSString子类*/
    //注意虽然initWithCapacity分配字符串大小,但是不是绝对的不可以超过此范围,声明此变量对性能有好处
    NSMutableString *str1= [[NSMutableString alloc] initWithCapacity:10];
    [str1 setString:@"hello"];//设置字符串
    NSLog(@"%@",str1);
    //结果:hello

    [str1 appendString:@",world!"];//追加字符串
    NSLog(@"%@",str1);
    //结果:hello,world!

    [str1 appendFormat:@"我的年龄是%i。dear,I love you.",18];
    NSLog(@"%@",str1);
    //结果:hello,world!我的年龄是18。dear,I love you.
    
    //替换字符串
    NSRange range=[str1 rangeOfString:@"dear"];
    [str1 replaceCharactersInRange:range withString:@"Honey"];
    NSLog(@"%@",str1);
    //结果:hello,world!我的年龄是18。Honey,I love you.
    
    //插入字符串
    [str1 insertString:@"My name is Kenshin." atIndex:12];
    NSLog(@"%@",str1);
    //结果:hello,world!My name is Kenshin.我的年龄是18。Honey,I love you.
    
    //删除指定字符串
    [str1 deleteCharactersInRange:[str1 rangeOfString:@"My name is Kenshin."]];//删除指定范围的字符串
    NSLog(@"%@",str1);
    //结果:hello,world!我的年龄是18。Honey,I love you.
    
    return 0;
}

数组

不可变数组

下面将演示常用的数组操作:初始化、数组对象的方法执行、数组元素的遍历、在原有数组基础上产生新数组、数组排序等

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"


void test1(){
    //NSArray长度不可变所以初始化的时候就赋值,并且最后以nil结尾
    //此外需要注意NSArray不能存放C语言的基础类型
    NSObject *obj=[[NSObject alloc]init];
    //NSArray *array1=[[NSArray alloc] initWithObjects:@"abc",obj,@"cde",@"opq", nil];
    NSArray *array1=[NSArray arrayWithObjects:@"abc",obj,@"cde",@"opq",@25, nil];
    NSLog(@"%zi",array1.count);//数组长度,结果:5
    NSLog(@"%i",[array1 containsObject:@"cde"]);//是否包含某个对象,结果:1
    NSLog(@"%@",[array1 lastObject]);//最后一个对象,结果:25
    NSLog(@"%zi",[array1 indexOfObject:@"abc"]);//对象所在的位置:0
    
    Person *person1=[Person personWithName:@"Kenshin"];
    Person *person2=[Person personWithName:@"Kaoru"];
    Person *person3=[Person personWithName:@"Rosa"];
    NSArray *array2=[[NSArray alloc]initWithObjects:person1,person2,person3, nil];
    [array2 makeObjectsPerformSelector:@selector(showMessage:) withObject:@"Hello,world!"];//执行所有元素的showMessage方法,后面的参数最多只能有一个
    /*结果:
     My name is Kenshin,the infomation is "Hello,world!".
     My name is Kaoru,the infomation is "Hello,world!".
     My name is Rosa,the infomation is "Hello,world!".
     */
}
//数组的遍历
void test2(){
    NSObject *obj=[[NSObject alloc]init];
    NSArray *array=[[NSArray alloc] initWithObjects:@"abc",obj,@"cde",@"opq",@25, nil];
    //方法1
    for(int i=0,len=array.count;i<len;++i){
        NSLog(@"method1:index %i is %@",i,[array objectAtIndex:i]);
    }
    /*结果:
     method1:index 0 is abc
     method1:index 1 is <NSObject: 0x100106de0>
     method1:index 2 is cde
     method1:index 3 is opq
     method1:index 4 is 25
     */
    
    
    //方法2
    for(id obj in array){
        NSLog(@"method2:index %zi is %@",[array indexOfObject:obj],obj);
    }
    /*结果:
     method2:index 0 is abc
     method2:index 1 is <NSObject: 0x100602f00>
     method2:index 2 is cde
     method2:index 3 is opq
     method2:index 4 is 25
     */
    
    
    //方法3,利用代码块方法
    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"method3:index %zi is %@",idx,obj);
        if(idx==2){//当idx=2时设置*stop为YES停止遍历
            *stop=YES;
        }
    }];
    /*结果:
     method3:index 0 is abc
     method3:index 1 is <NSObject: 0x100106de0>
     method3:index 2 is cde
     */
    
    
    //方法4,利用迭代器
    //NSEnumerator *enumerator= [array objectEnumerator];//获得一个迭代器
    NSEnumerator *enumerator=[array reverseObjectEnumerator];//获取一个反向迭代器
    //NSLog(@"all:%@",[enumerator allObjects]);//获取所有迭代对象,注意调用完此方法迭代器就遍历完了,下面的nextObject就没有值了
    id obj2=nil;
    while (obj2=[enumerator nextObject]) {
        NSLog(@"method4:%@",obj2);
    }
    /*结果:
     method4:25
     method4:opq
     method4:cde
     method4:<NSObject: 0x100106de0>
     method4:abc
     */
}
//数组派生出新的数组
void test3(){
    NSArray *array=[NSArray arrayWithObjects:@"1",@"2",@"3", nil];
    NSArray *array2=[array arrayByAddingObject:@"4"];//注意此时array并没有变
    NSLog(@"%@",array2);
    /*结果:
     (
         1,
         2,
         3,
         4
     )
     */
    
    
    NSLog(@"%@",[array2 arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"5",@"6", nil]]);//追加形成新的数组
    /*结果:
     (
         1,
         2,
         3,
         4,
         5,
         6
     )
     */
    
    
    NSLog(@"%@",[array2 subarrayWithRange:NSMakeRange(1, 3)]);//根据一定范围取得生成一个新的数组
    /*结果:
     (
         2,
         3,
         4
     )
     */
    
    
    NSLog(@"%@",[array componentsJoinedByString:@","]);//数组连接,形成一个字符串
    //结果:1,2,3
    
    //读写文件
    NSString *path=@"/Users/KenshinCui/Desktop/array.xml";
    [array writeToFile:path atomically:YES];
    NSArray *array3=[NSArray arrayWithContentsOfFile:path];
    NSLog(@"%@",array3);
    /*结果:
     (
         1,
         2,
         3
     )
     */
}
//数组排序
void test4(){
    //方法1,使用自带的比较器
    NSArray *array=[NSArray arrayWithObjects:@"3",@"1",@"2", nil];
    NSArray *array2= [array sortedArrayUsingSelector:@selector(compare:)];
    NSLog(@"%@",array2);
    /*结果:
     (
         1,
         2,
         3
     )
     */
    
    
    //方法2,自己定义比较器
    Person *person1=[Person personWithName:@"Kenshin"];
    Person *person2=[Person personWithName:@"Kaoru"];
    Person *person3=[Person personWithName:@"Rosa"];
    NSArray *array3=[NSArray arrayWithObjects:person1,person2,person3, nil];
    NSArray *array4=[array3 sortedArrayUsingSelector:@selector(comparePerson:)];
    NSLog(@"%@",array4);
    /*结果:
     (
         "name=Kaoru",
         "name=Kenshin",
         "name=Rosa"
     )
     */
    
    
    //方法3使用代码块
    NSArray *array5=[array3 sortedArrayUsingComparator:^NSComparisonResult(Person *obj1, Person *obj2) {
        return [obj2.name compare:obj1.name];//降序
    }];
    NSLog(@"%@",array5);
    /*结果:
     (
         "name=Rosa",
         "name=Kenshin",
         "name=Kaoru"
     )
     */
    
    
    //方法4 通过描述器定义排序规则
    Person *person4=[Person personWithName:@"Jack"];
    Person *person5=[Person personWithName:@"Jerry"];
    Person *person6=[Person personWithName:@"Tom"];
    Person *person7=[Person personWithName:@"Terry"];
    NSArray *array6=[NSArray arrayWithObjects:person4,person5,person6,person7, nil];
    //定义一个排序描述
    NSSortDescriptor *personName=[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    NSSortDescriptor *accountBalance=[NSSortDescriptor sortDescriptorWithKey:@"account.balance" ascending:YES];
    NSArray *des=[NSArray arrayWithObjects:personName,accountBalance, nil];//先按照person的name排序再按照account的balance排序
    NSArray *array7=[array6 sortedArrayUsingDescriptors:des];
    NSLog(@"%@",array7);
    /*结果:
     (
         "name=Jack",
         "name=Jerry",
         "name=Terry",
         "name=Tom"
     )
     */
}

int main(int argc, const char * argv[]) {
    test1();
    test2();
    test3();
    test4();
    return 0;
}

需要注意几点:

  • NSArray中只能存放对象,不能存放基本数据类型,通常我们可以通过在基本数据类型前加@进行转换;
  • 数组中的元素后面必须加nil以表示数据结束;
  • makeObjectsPerformSelector执行数组中对象的方法,其参数最多只能有一个;
  • 上面数组操作中无论是数组的追加、删除、截取都没有改变原来的数组,只是产生了新的数组而已;
  • 对象的比较除了使用系统自带的方法,我们可以通过自定义比较器的方法来实现;

可变数组

下面看一下可变数组的内容:

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"


void test1(){
    Person *person1=[Person personWithName:@"Kenshin"];
    Person *person2=[Person personWithName:@"Kaoru"];
    Person *person3=[Person personWithName:@"Rosa"];
    NSMutableArray *array1=[NSMutableArray arrayWithObjects:person1,person2,person3, nil];
    NSLog(@"%@",array1);
    /*结果:
     (
         "name=Kenshin",
         "name=Kaoru",
         "name=Rosa"
     )
     */
    
    Person *person4=[Person personWithName:@"Jack"];//此时person4的retainCount为1
    [array1 addObject:person4];//添加一个元素,此时person4的retainCount为2
    NSLog(@"%@",array1);
    /*结果:
     (
         "name=Kenshin",
         "name=Kaoru",
         "name=Rosa",
         "name=Jack"
     )
     */
    
    [array1 removeObject:person3];//删除一个元素
    NSLog(@"%@",array1);
    /*结果:
     (
         "name=Kenshin",
         "name=Kaoru",
         "name=Jack"
     )
     */
    
    [array1 removeLastObject];//删除最后一个元素,//此时person4的retainCount为1
    NSLog(@"%@",array1);
    /*结果:
     (
         "name=Kenshin",
         "name=Kaoru"
     )
     */
    
    [array1 removeAllObjects];//删除所以元素
    
    //注意当往数组中添加一个元素时会retain因此计数器+1,当从数组中移除一个元素时会release因此计数器-1
    //当NSMutalbeArray对象release的时候会依次调用每一个对象的release
}
void test2(){
    NSMutableArray *array1=[NSMutableArray arrayWithObjects:@"1",@"3",@"2", nil];
    NSLog(@"%@",array1);
    /*结果:
     (
         1,
         3,
         2
     )
     */
    
    NSArray *array2= [array1 sortedArrayUsingSelector:@selector(compare:)];//注意这个方法没有修改array1
    NSLog(@"%@",array1);
    /*结果:
     (
         1,
         3,
         2
     )
     */
    
    NSLog(@"%@",array2);
    /*结果:
     (
         1,
         2,
         3
     )
     */
    [array1 sortUsingSelector:@selector(compare:)];//这个方法会修改array1
    NSLog(@"%@",array1);
    /*结果:
     (
         1,
         2,
         3
     )
     */
    
}

int main(int argc, const char * argv[]) {
    
    test1();
    
    test2();
    
    return 0;
}
  • 可变数组中的元素后面必须加nil以表示数据结束;
  • 往一个可变数组中添加一个对象,此时这个对象的引用计数器会加1,当这个对象从可变数组中移除其引用计数器减1。同时当整个数组销毁之后会依次调用每个对象的releaes方法。
  • 在不可变数组中无论对数组怎么排序,原来的数组顺序都不会改变,但是在可变数组中如果使用sortUsingSelector:排序原来的数组顺序就发生了变化。

 

字典

字典在我们日常开发中也是比较常用的,通过下面的代码我们看一下在ObjC中的字典的常用操作:初始化、遍历、排序

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>


void test1(){
    NSDictionary *dic1=[NSDictionary dictionaryWithObject:@"1" forKey:@"a"];
    NSLog(@"%@",dic1);
    /*结果:
     {
        a = 1;
     }
     */
    
    //常用的方式
    NSDictionary *dic2=[NSDictionary dictionaryWithObjectsAndKeys:
                        @"1",@"a",
                        @"2",@"b",
                        @"3",@"c",
                        nil];
    NSLog(@"%@",dic2);
    /*结果:
     {
         a = 1;
         b = 2;
         c = 3;
     }
     */
    
    
    NSDictionary *dic3=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1",@"2", nil] forKeys:[NSArray arrayWithObjects:@"a",@"b", nil]];
    NSLog(@"%@",dic3);
    /*结果:
     {
         a = 1;
         b = 2;
     }
     */
    
    
    //更简单的方式
    NSDictionary *dic4=@{@"1":@"a",@"2":@"b",@"3":@"c"};
    NSLog(@"%@",dic4);
    /*结果:
     {
         1 = a;
         2 = b;
         3 = c;
     }
     */
}
void test2(){
    NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:
                        @"1",@"a",
                        @"2",@"b",
                        @"3",@"c",
                        @"2",@"d",
                        nil];
    NSLog(@"%zi",[dic1 count]); //结果:4
    NSLog(@"%@",[dic1 valueForKey:@"b"]);//根据键取得值,结果:2
    NSLog(@"%@",dic1[@"b"]);//还可以这样读取,结果:2
    NSLog(@"%@,%@",[dic1 allKeys],[dic1 allValues]);
    /*结果:
     (
         d,
         b,
         c,
         a
     ),(
         2,
         2,
         3,
         1
     )

     */
    
    NSLog(@"%@",[dic1 objectsForKeys:[NSArray arrayWithObjects:@"a",@"e" , nil]notFoundMarker:@"not fount"]);//后面一个参数notFoundMarker是如果找不到对应的key用什么值代替
    /*结果:
     (
         1,
         "not fount"
     )
     */
}
void test3(){
    NSDictionary *dic1=[NSDictionary dictionaryWithObjectsAndKeys:
                        @"1",@"a",
                        @"2",@"b",
                        @"3",@"c",
                        @"2",@"d",
                        nil];
    //遍历1
    for (id key in dic1) {//注意对于字典for遍历循环的是key
        NSLog(@"%@=%@",key,[dic1 objectForKey:key]);
    }
    /*结果:
     d=2
     b=2
     c=3
     a=1
     */
    
    //遍历2
    NSEnumerator *enumerator=[dic1 keyEnumerator];//还有值的迭代器[dic1 objectEnumerator]
    id key=nil;
    while (key=[enumerator nextObject]) {
        NSLog(@"%@=%@",key,[dic1 objectForKey:key]);
        
    }
    /*结果:
     d=2
     b=2
     c=3
     a=1
     */
    
    //遍历3
    [dic1 enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        NSLog(@"%@=%@",key,obj);
    }];
    /*结果:
     d=2
     b=2
     c=3
     a=1
     */
}

void test4(){
    NSMutableDictionary *dic=[NSMutableDictionary dictionaryWithObjectsAndKeys:@"1",@"a",
                              @"2",@"b",
                              @"3",@"c",
                              @"2",@"d",
                            nil];
    [dic removeObjectForKey:@"b"];
    NSLog(@"%@",dic);
    /*结果:
     {
         a = 1;
         c = 3;
         d = 2;
     }
     */
    
    [dic addEntriesFromDictionary:@{@"e":@"7",@"f":@"6"}];
    NSLog(@"%@",dic);
    /*结果:
     {
         a = 1;
         c = 3;
         d = 2;
         e = 7;
         f = 6;
     }
     */
    
    [dic setValue:@"5" forKey:@"a"];
    NSLog(@"%@",dic);
    /*结果:
     {
         a = 5;
         c = 3;
         d = 2;
         e = 7;
         f = 6;
     }
     */
     
    
    //注意,一个字典的key或value添加到字典中时计数器+1;字典释放时调用key或value的release一次,计数器-1
}


int main(int argc, const char * argv[]) {
    test1();
    test2();
    test3();
    test4();
    return 0;
}

注意:同数组一样,不管是可变字典还是不可变字典初始化元素后面必须加上nil以表示结束。

文件操作

在今天的最后一节内容中让我们看一下Foundation中文件操作,下面将以一个例子进行说明:

//
//  main.m
//  FoundationFramework
//
//  Created by Kenshin Cui on 14-2-16.
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#import <Foundation/Foundation.h>

/*目录操作*/
void test1(){
    //文件管理器是专门用于文件管理的类
    NSFileManager *manager=[NSFileManager defaultManager];
    
    //获得当前程序所在目录(当然可以改变)
    NSString *currentPath=[manager currentDirectoryPath];
    NSLog(@"current path is :%@",currentPath);
    //结果:/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug
    
    //创建目录
    NSString *myPath=@"/Users/kenshincui/Desktop/myDocument";
    BOOL result= [manager createDirectoryAtPath:myPath withIntermediateDirectories:YES attributes:nil error:nil];
    if(result==NO){
        NSLog(@"Couldn't create directory!");
    }
    
    //目录重命名,如果需要删除目录只要调用removeItemAtPath:<#(NSString *)#> error:<#(NSError **)#>
    NSError *error;
    NSString *newPath=@"/Users/kenshincui/Desktop/myNewDocument";
    if([manager moveItemAtPath:myPath toPath:newPath error:&error]==NO){
        NSLog(@"Rename directory failed!Error infomation is:%@",error);
    }
    
    //改变当前目录
    if([manager changeCurrentDirectoryPath:newPath]==NO){
        NSLog(@"Change current directory failed!");
    }
    NSLog(@"current path is :%@",[manager currentDirectoryPath]);
    //结果:current path is :/Users/kenshincui/Desktop/myNewDocument
    
    //遍历整个目录
    NSString *path;
    NSDirectoryEnumerator *directoryEnumerator= [manager enumeratorAtPath:newPath];
    while (path=[directoryEnumerator nextObject]) {
        NSLog(@"%@",path);
    }
    /*结果:
     documents
     est.txt
    */
    
    //或者这样遍历
    NSArray *paths= [manager contentsOfDirectoryAtPath:newPath error:nil];
    NSObject *p;
    for (p in paths) {
        NSLog(@"%@",p);
    }
    /*结果:
     documents
     est.txt
     */
}

/*文件操作*/
void test2(){
    NSFileManager *manager=[NSFileManager defaultManager];
    NSString *filePath=@"/Users/kenshincui/Desktop/myNewDocument/test.txt";
    NSString *filePath2=@"/Users/kenshincui/Desktop/test.txt";
    NSString *newPath=@"/Users/kenshincui/Desktop/myNewDocument/test2.txt";
    
    //判断文件是否存在,这个方法也可以判断目录是否存在,这要后面的参数设置位YES
    if ([manager fileExistsAtPath:filePath isDirectory:NO]) {
        NSLog(@"File exists!");
    }
    
    //文件是否可读
    if([manager isReadableFileAtPath:filePath]){
        NSLog(@"File is readable!");
    }
    
    //判断两个文件内容是否相等
    if ([manager contentsEqualAtPath:filePath andPath:filePath2]) {
        NSLog(@"file1 equals file2");
    }
    
    //文件重命名,方法类似于目录重命名
    if (![manager moveItemAtPath:filePath toPath:newPath error:nil]) {
        NSLog(@"Rename file1 failed!");
    }
    
    //文件拷贝
    NSString *filePath3=@"/Users/kenshincui/Desktop/test3.txt";
    if(![manager copyItemAtPath:newPath toPath:filePath3 error:nil]){
        NSLog(@"Copy failed!");
    }
    
    //读取文件属性
    NSDictionary *attributes;
    if ((attributes=[manager attributesOfItemAtPath:newPath error:nil])==nil) {
        NSLog(@"Read attributes failed!");
    }
    for (NSObject *key in attributes) {
        NSLog(@"%@=%@",key,attributes[key]);
    }
    /*结果:
         NSFileOwnerAccountID=501
         NSFileHFSTypeCode=0
         NSFileSystemFileNumber=1781953
         NSFileExtensionHidden=0
         NSFileSystemNumber=16777218
         NSFileSize=27
         NSFileGroupOwnerAccountID=20
         NSFileOwnerAccountName=kenshincui
         NSFileCreationDate=2014-07-28 11:47:58 +0000
         NSFilePosixPermissions=420
         NSFileHFSCreatorCode=0
         NSFileType=NSFileTypeRegular
         NSFileExtendedAttributes={
         "com.apple.TextEncoding" = <7574662d 383b3133 34323137 393834>;
         }
         NSFileGroupOwnerAccountName=staff
         NSFileReferenceCount=1
         NSFileModificationDate=2014-07-28 11:47:58 +0000
     */
    
    //删除文件
    [manager removeItemAtPath:newPath error:nil];
    
}
//文件操作--文件内容操作(NSData,非结构化字节流对象,有缓冲区管理机制,可用于网络传输)
void test3(){
    NSFileManager *manager=[NSFileManager defaultManager];
    NSString *filePath=@"/Users/kenshincui/Desktop/myNewDocument/test2.txt";
    NSData *data=[manager contentsAtPath:filePath];
    NSLog(@"%@",data);//存储的是二进制字节流
    //结果:<68656c6c 6f20776f 726c642c e4b896e7 958ce4bd a0e5a5bd efbc81>
    
    //NSData转化成字符串
    NSString *str1=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@",str1);
    //结果:hello world,世界你好!
    
    //字符串转化成NSData
    NSString *str2=@"Kenshin";
    NSData *data2=[str2 dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%@",data2);
    
    //当然一般如果仅仅是简单读取文件内容,直接用户NSString方法即可
    NSString *content=[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",content);
    //结果:hello world,世界你好!
    
}
//文件操作--细粒度控制文件,文件操作柄
void test4(){
    NSFileManager *manager=[NSFileManager defaultManager];
    NSString *filePath=@"/Users/kenshincui/Desktop/myNewDocument/test2.txt";
    
    //以只读方式打开文件
    NSFileHandle *fileHandle=[NSFileHandle fileHandleForReadingAtPath:filePath];//注意这个方法返回类型为instancetype,也就是说对于上面的NSFileHandle它的返回类型也是NSFileHandle
    NSData *data= [fileHandle readDataToEndOfFile];//完整读取文件
    NSString *newPath=@"/Users/kenshincui/Desktop/test4.txt";
    [manager createFileAtPath:newPath contents:nil attributes:nil];
    NSFileHandle *fileHandle2=[NSFileHandle fileHandleForWritingAtPath:newPath];//以可写方式打开文件
    [fileHandle2 writeData:data];//写入文件内容
    
    [fileHandle2 closeFile];//关闭文件

    
    //定位到指定位置,默认在文件开头
    [fileHandle seekToFileOffset:12];
    NSData *data2= [fileHandle readDataToEndOfFile];
    NSLog(@"data2=%@",[[NSString alloc]initWithData:data2 encoding:NSUTF8StringEncoding]);
    //结果:data2=世界你好!
    
    [fileHandle seekToFileOffset:6];
    NSData *data3=[fileHandle readDataOfLength:5];
    NSLog(@"data3=%@",[[NSString alloc]initWithData:data3 encoding:NSUTF8StringEncoding]);
    //结果:data3=world
    
    [fileHandle closeFile];
    
}

//文件路径
void test5(){
    NSString *filePath=@"/Users/kenshincui/Desktop/myDocument";
    NSString *filePath2=@"/Users/kenshincui/Desktop/test.txt";

    //临时文件所在目录
    NSString *path=NSTemporaryDirectory();
    NSLog(@"temporary directory is :%@",path);
    //结果:/var/folders/h6/lss6gncs509c2pgzgty3wd_40000gn/T/

    NSString *lastComponent= [filePath lastPathComponent];
    NSLog(@"%@",lastComponent); //结果:myDocument
    
    NSLog(@"%@",[filePath stringByDeletingLastPathComponent]);
    //结果:/Users/kenshincui/Desktop
    NSLog(@"%@",[filePath stringByAppendingPathComponent:@"Pictrues"]);
    //结果:/Users/kenshincui/Desktop/myDocument/Pictrues
    NSLog(@"%@",[filePath2 pathExtension]);
    //结果:txt
    
    [[filePath pathComponents] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"%i=%@",idx,obj);
    }];
    /*结果:
     0=/
     1=Users
     2=kenshincui
     3=Desktop
     4=myDocument
     */
    
    
}

//文件操作--NSURL
void test6(){
    NSURL *url=[NSURL URLWithString:@"http://developer.apple.com"];
    NSString *str1=[NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"%@",str1);
}

//文件操作--NSBundle,程序包,一般用于获取Resource中的资源(当然由于当前并非IOS应用没有程序包,只是表示当前程序运行路径)
//在ios中经常用于读取应用程序中的资源文件,如图片、声音、视频等
void test7(){
    //在程序包所在目录创建一个文件
    NSFileManager *manager=[NSFileManager defaultManager];
    NSString *currentPath=[manager currentDirectoryPath];
    NSLog(@"current path is :%@",currentPath);
    //结果:current path is :/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug
    NSString *filePath=[currentPath stringByAppendingPathComponent:@"test.txt"];
    [manager createFileAtPath:filePath contents:[@"Hello,world!" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
    
    
    //利用NSBundle在程序包所在目录查找对应的文件
    NSBundle *bundle=[NSBundle mainBundle];//主要操作程序包所在目录
    //如果有test.txt则返回路径,否则返回nil
    NSString *path=[bundle pathForResource:@"test" ofType:@"txt"];//也可以写成:[bundle pathForResource:@"instructions.txt" ofType:nil];
    NSLog(@"%@",path);
    //结果:/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug/test.txt
    NSLog(@"%@",[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]);
    //结果:Hello,world!
    
    //假设我们在程序运行创建一个Resources目录,并且其中新建pic.jpg,那么用下面的方法获得这个文件完整路径
    NSString *path1= [bundle pathForResource:@"pic" ofType:@"jpg" inDirectory:@"Resources"];
    NSLog(@"%@",path1);
    //结果:/Users/kenshincui/Library/Developer/Xcode/DerivedData/FoundationFramework-awxjohcpgsqcpsanqofqogwbqgbx/Build/Products/Debug/Resources/pic.jpg
}

int main(int argc,char *argv[]){

    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值