OC学习笔记

OC学习笔记

  • NSLog
%@ 对象
%d, %i 整数
%u   无符整形
%f 浮点/双字
%x, %X 二进制整数
%o 八进制整数
%zu size_t
%p 指针
%e   浮点/双字 (科学计算)
%g   浮点/双字
%s C 字符串
%.*s Pascal字符串
%c 字符
%C unichar
%lld 64位长整数(long long)
%llu   无符64位长整数
%Lf 64位双字

NSLog定义在NSObjCRuntime.h中,如下所示:
void NSLog(NSString *format, …);

NSLog (@”this is a test”);
NSLog (@”string is :%@”, string);
NSLog (@”x=%d, y=%d”, 10, 20);

但是下面的写法是不行的:
int i = 12345;
NSLog( @”%@”, i );

原因是, %@需要显示对象,而int i明显不是一个对象,要想正确显示,要写成:
int i = 12345;
NSLog( @”%d”, i );

  • NSString

    常用实例化方法

    –使用格式创建字符串-------------
    + (id)stringWithFormat:(NSString *)format…
    - (id)initWithFormat:(NSString *)format…

    [NSString stringWithString:(nonnull NSString *)]

    [NSString stringWithCString:“new String” enconding: NSACIIStringEncoding];

    –NSRange的定义
    typedef struct _NSRange
    {
    unsigned int location;
    unsigned int length;
    }NSRange;

    NSMakeRange函数
    --这个函数比较特殊 返回一个NSRange的对象。
    NSMakeRanger(unsigned int location,unsigned int length);

    计算字符串长度
    - (unsigned int)length;

    1、连接
    - (NSString *)stringByAppendingString:(NSString *)string;
    - (NSString *)stringByAppendingFormat:(NSString *)format…;
    例如:
    NSString *str1 = @“hello”;
    NSString *str2 = @“world”;
    NSString *str3 = [str1 stringByAppendingString:str2];
    NSString *str4 = [str2 stringByAppendingFormat:@“%d…%d”,10,20];

    2、追加字符串
    NSMutableString
    + (void)appendString:(NSString *)string;
    - (void)appendFormat:(NSString *)format…;
    例如:
    NSMutableString string = [NSMutableString string];

    3、插入字符串
    NSMutableString
    + (void)insertString:(NSString *)string atIndex:(unsigned)index;
    从index位置插入字符串
    例如:
    NSMutableString *string = [NSMutableString stringWithString:@“Mac X”];

    4、删除字符串
    NSMutableString
    + (void)deleteCharactersInRange:(NSRange)range;
    例如:
    NSMutableString *string = [NSMutableString stringWithString:@“Mac os”];
    [string deleteCharactersInRange:NSMakeRanger(0,1)];

    5、字符串比较
    NSString
    - (BOOL)isEqualToString:(NSString *)string;
    6、比较前置串和后置串
    NSString
    - (BOOL)hasPrefix:(NSString *)string;
    - (BOOL)hasSuffix:(NSString *)string;

    7、字符串检索
    NSString
    //如果找到就返回范围,否则NSRange的location项被设置为NSNotFound
    - (NSRange)rangeOfString:(NSString *)subString;
    - (NSRange)rangeOfString:(NSString *)subString option:(unsigned)mask;
    - (NSRange)rangeOfString:(NSString *)subString option:(unsigned)mask range:(NSRange)range;
    -----mask常用选项列表
    NSCaseInsensitiveSearch 不区分字母大小写
    NSLiteralSearch 对字符串进行字节单位的比较,一般可提高检索速度
    NSBackwardsSearch 从范围的末尾开始检索
    NSAnchoredSearch 仅检索制定范围的前部。忽略字符串中间的检索字符

    8、截取字符串
    NSString
    - (NSString *)substringToIndex:(unsigned)index; //返回字符串开头至index位的字符串 不包含索引位
    - (NSString *)substringFromIndex:(unsigned)index; //返回字符串第index位至末尾的字符串 包含索引位
    - (NSString *)substringWithRange:(NSRange)range; //返回字符串中范围range内的字符串 包含索引位

    9、读取文本文件
    NSString
    + (id)stringWithContentsOfFile:(NSString *)path usedEncoding:(NSStringEncoding *)enc error:(NSError **)error //自动释放内存

    - (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error

    10、输出文本文件
    NSString
    - (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error
    //参数 atomically 暂时将文件保存到辅助文件中
    //path
    The file to which to write the receiver. If path contains a tilde (~) character, you must expand it withstringByExpandingTildeInPath before invoking this method.

  • Category

分类(Category)是OC中的特有语法,它是表示一个指向分类的结构体的指针。原则上它只能增加方法,不能增加成员(实例)变量。具体原因看源码组成:

Category
Category 是表示一个指向分类的结构体的指针,其定义如下:
typedef struct objc_category *Category;
struct objc_category {
  char *category_name                          OBJC2_UNAVAILABLE; // 分类名
  char *class_name                             OBJC2_UNAVAILABLE; // 分类所属的类名
  struct objc_method_list *instance_methods    OBJC2_UNAVAILABLE; // 实例方法列表
  struct objc_method_list *class_methods       OBJC2_UNAVAILABLE; // 类方法列表
  struct objc_protocol_list *protocols         OBJC2_UNAVAILABLE; // 分类所实现的协议列表
}

没有属性列表

1.分类是用于给原有类添加方法的,因为分类的结构体指针中,没有属性列表,只有方法列表。所以< 原则上讲它只能添加方法, 不能添加属性(成员变量),实际上可以通过其它方式添加属性> ;
2.分类中的可以写@property, 但不会生成setter/getter方法, 也不会生成实现以及私有的成员变量(编译时会报警告);
3.可以在分类中访问原有类中.h中的属性;
4.如果分类中有和原有类同名的方法, 会优先调用分类中的方法, 就是说会忽略原有类的方法。所以同名方法调用的优先级为 分类 > 本类 > 父类。因此在开发中尽量不要覆盖原有类;
5.如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定;编译器会执行最后一个参与编译的分类中的方法。

写法

@interface 待扩展的类(分类的名称)
-(void) method;
@end

@implementation 待扩展的名称(分类的名称)
-(void) method{

}
@end
  • Extension

类扩展

@interface XXX ()
//私有属性
//私有方法(如果不实现,编译时会报警,Method definition for 'XXX' not found)
@end

类扩展即可以声明成员变量又可以声明方法。

类扩展可以定义在.m文件中,这种扩展方式中定义的变量都是私有的,也可以定义在.h文件中,这样定义的代码就是共有的,类扩展在.m文件中声明私有方法是非常好的方式。

类扩展中添加的新方法,一定要实现。category中没有这种限制。

  • 协议

协议实际上就是定义了一组方法,然后让其他类去实现这些方法。是多个类共享一个方法列表.协议中列出的类没有响应的实现,由其他类来实现。

协议的定义格式为:

/*
协议的定义格式为:

         @protocol  协议名  <父协议>       

                方法

         @end
*/
@protocol FoodProtocol <NSObject>

/*
 在方法声明的时候,可以有两个关键字去限制是否让遵循该协议的类去实现此方法
 @required   标注的方法为必须实现的方法(默认)
 @option     标注的方法为可选实现的

 */


@optional
- (void)sayHello;

@required
- (void)sendFood:(BOOL)flag;

@end

  • NSArray 等集合类型只能存储对象。——对象
  • NSNumber 可以将基础数据类型转化为对象。——基础数据类型 ➡️ 对象
  • NSValue 可以将结构类型转化为对象。——结构 ➡️ 对象

NSValue 方法

+ (NSValue *)valueWithPoint:(NSPoint)point;
+ (NSValue *)valueWithSize:(NSSize)size;
+ (NSValue *)valueWithRect:(NSRect)rect;
+ (NSValue *)valueWithEdgeInsets:(NSEdgeInsets)insets NS_AVAILABLE(10_10, 8_0);

CGPoint

// NSPoint 
NSPoint somePoint = NSMakePoint(100, 100);
NSValue *point = [NSValue valueWithPoint:somePoint];

// CGPoint
NSValue *myPointValue = [NSValue valueWithPoint:CGPointMake(10, 10)];
CGPoint point = [myPointValue pointValue];

CGSize

// 大小
NSValue *mySizeValue = [NSValue valueWithSize:CGSizeMake(375, 664)];
CGSize size = [mySizeValue sizeValue];

CGRect

// 矩形区域
NSValue *myRectValue = [NSValue valueWithRect:CGRectMake(0, 0, 375, 664)];
CGRect rect = [myRectValue rectValue];

NSRange

// 范围
NSValue *myRangeValue = [NSValue valueWithRange:NSMakeRange(0, 10)];
NSRange range = [myRangeValue rangeValue];

结构体

// 对自定义的结构体封包、解包
struct WXpoint {
    float a;
    float b;
};

struct WXpoint p = {10,50};

// 封包
NSValue *pointvalue1 = [NSValue value:&p
  withObjCType:@encode(struct WXpoint)];

// 解包
struct WXpoint p2;
[pointvalue1 getValue:&p2];

NSNumber

创建NSNumber对象:

numberWithBool:

numberWithChar:
numberWithDouble:
numberWithFloat:
numberWithInt:
numberWithInteger:
numberWithLong:
numberWithLongLong:
numberWithShort:
numberWithUnsignedChar:
numberWithUnsignedInt:
numberWithUnsignedInteger:
numberWithUnsignedLong:
numberWithUnsignedLongLong:
numberWithUnsignedShort:
访问值:

boolValue
charValue
decimalValue
doubleValue
floatValue
intValue
integerValue
longLongValue
longValue
shortValue
unsignedCharValue
unsignedIntegerValue
unsignedIntValue
unsignedLongLongValue
unsignedLongValue
unsignedShortValue

比较两个对象的大小:

- (NSComparisonResult)compare:(NSNumber *)aNumber

[intNumber compare:myNumber]

两个数进行比较大小,

如果值恒等于 NSOrderedAscending 表示intNumber小于myNumber

NSOrderedSame表示相等

NSOrderedDecending表示前一个大于后一个。

比较的是对象中存储的数据:

- (BOOL)isEqualToNumber:(NSNumber *)aNumber
NSNumber *num2 = [[NSNumber alloc] initWithFloat:10.5];

//isEqualToNumber: 比较的是对象中存储的数据

BOOL isEqual = [num1 isEqualToNumber:num2];

NSLog(@"isEqual=%d", isEqual);

类型信息:

- (const char *)objCType
  • NSArray

    构造

    [NSArray arrayWithObjects:]

    [NSArray arrayWithArray:]

    长度

    arr.count;

    下标

    [arr objectAtIndex:3];

    返回元素下标

    [arr indexOfObject:@“xxx”];

    是否存在

    [arr coutainsObject:@“xxx”];

    NSArray简化形式:
    //用简化的方式,来定义和访问数组元素
        //1)用简化的方式,定义数组
        //格式: @[ 数组元素 ]
        NSArray *arr = @[@"1",@"one",@"3",@4,@"ONE"];
        NSLog(@"arr = %@",arr);
        
        NSString *str =[arr objectAtIndex:2];
        NSLog(@"%@",str);
        
        //2)用简化的方式访问数组元素
        str = arr[1];   //C语言形式的数组元素访问
        NSLog(@"%@",str);
    
    NSArray的遍历:
    //定义一个数组
        NSArray *arr = @[@"one",@"two",@"three",@"four"];
        
        //对数组进行遍历
        
        //1) 普通的方式,通过下标访问
        for (int i=0; i<arr.count; i++) {
            NSLog(@"-> %@",arr[i]);
        }
        
        //2) 快速枚举法 for循环的增强形式
        for (NSString * str in arr) {
             NSLog(@"---> %@",str);
        }
        
    
        //3) 使用block的方式,进行访问
        //                               数组元素            元素下标     是否停止
        //stop:YES  会停止, stop:NO 不会停止
        [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            
            if(idx == 2){
            
                *stop = YES;  //停止  // break;
                
            }else{
            
               NSLog(@"idx = %ld,obj = %@",idx,obj);
            }
            
            
        }];
    

读写文件

NSArray读写文件:
  • 写入

      NSArray *array = [NSArray     arrayWithObjects:@"one",@"zbz",@"cgx",@"sb",@"cjk",@"senni", nil];
     //把NSArray 中的内容,写入到文件中
      //arr.plist 一种特殊的文件格式
      BOOL isWrite =  [array writeToFile:@"/xxx" atomically:YES];
      
      if(isWrite){
           
             NSLog(@"写入成功");
        }
    
  • 读取

      //从文件中,读取一个数组信息
      NSArray *readArr = [NSArray arrayWithContentsOfFile:@"xxx"];
      
      NSLog(@"readArr = %@",readArr);
    
NSArray与字符串:
  • 把数组拼接成为字符串

     //定义一个数组
     NSArray *arr = @[@1,@2,@3,@4];  
     //1)需求: 把数组中的元素用 "-" 连接起来
      //  [数组 componentsJoinedByString @"分隔符"];
      // 1-2-3-4
      NSString *str = [arr componentsJoinedByString:@"-"];
      NSLog(@"str = %@",str);
    
  • 把字符串拆分为数组

   //2) 给一个字符串,分割成一个数组
   // 400-800-12580   //取得 400    12580    800
   NSString *str2 = @"400-800-12580";
   NSArray *arr2 = [str2 componentsSeparatedByString:@"-"];
   NSLog(@"%@",[arr2 firstObject]);
   NSLog(@"%@",[arr2 lastObject]);
   NSLog(@"%@",arr2[1]);
  • NSMutableArray

//添加元素
[array1 addObject:@“A”];
NSMutableArray * arr = [[NSMutableArray alloc] initWithObjects:@“1”,@“2”,@“3”, nil];
[array1 addObjectsFromArray:arr];//把数组元素添加到尾部

//删除数组中所有元素
[array removeAllObjects];

//删除数组中最后一个元素
[array removeLastObject];

//删除指定的元素
[array removeObject:@“A”];

//删除指定下标的元素
[array removeObjectAtIndex:2];

//删除指定下标的元素
[array removeObjectIdenticalTo:NSMA]

//修改数据
[array replaceObjectAtIndex:2 withObject:@“H”];

//交换元素的位置
[array exchangeObjectAtIndex:0 withObjectAtIndex:1];

  • NSDictionary

    NSDictionary是不可变的,一旦初始化完成,里面的内容无法修改

    NSDictionary的作用:通过一个key,可以找到对应的value

    NSDictionary的特点:

    • 必须是以key-value的方式来存储,同事key不能重复
    • 存储的数据是无序的
    • 可以根据key快速获取value
NSDictionary的创建
NSDictionary *dict1 = [NSDictionary dictionary];
NSDictionary *dict2 = [NSDictionary dictionaryWithObject:@"zs" forKey:@"name"];
NSDictionary *dict3 = [NSDictionary dictionaryWithObjects:@[@"zs"] forKeys:@[@"name"]];
NSDictionary *dict4 = [NSDictionary dictionaryWithContentsOfFile:nil];
NSDictionary *dict5 = @{@"name":@"zs", @"age":@18};
获取元素
dict1[@"name"];
[dict1 objectForKey:@"name"];
获取键值对的数量
NSInteger count = dict1.count;
遍历
for (NSString *key in dict5) {
    // 使用这种方法遍历,取出的是key,value还需要自己去取
    NSLog(@"%@-%@",key, dict5[key]);
}

[dict5 enumerateKeysAndObjectsUsingBlock:^(NSString * key, id  _Nonnull obj, BOOL * _Nonnull stop) {
    
}];
文件操作
[dict5 writeToFile:@"路径" atomically:YES];

NSDictionary *dict7 = [NSDictionary dictionaryWithContentsOfFile:@"路径"];
  • setObject for key 可改可增,等效于直接赋值
// 赋值替换键值对
	- (void)setValue:(id)value forKey:(id <NSCopying>)key;
  - (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
  // 等效于setObject:forKey:,支持中括号下标格式(dictionary[key]=)赋值替换。
  • addEntries & setDictionary

    // 从otherDictionary追加entries到当前Dictionary
    
    * (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
      // 等效于先removeAllObjects后addObjectsFromArray;setDictionary类似于对retain propery的赋值(setter)。
    * (void)setDictionary:(NSDictionary *)otherDictionary;
    
  • removeObject

    // 删除指定key的键值对
    
    - (void)removeObjectForKey:(id)aKey;
      // 删除指定key数组对应的键值对
    - (void)removeObjectsForKeys:(NSArray *)keyArray;
      // 删除清空所有键值对
    - (void)removeAllObjects;
    
  • NSSet

  1. set集合中一种
  2. set是无序(不像array那样有顺序),例如:元素分别是@“1”, @“2”, @“3”,实际显示时,可能是@“1”, @“3”, @“2”,或@“2”, @“3”, @"1"这样无序的
  3. set中元素是不可重复的

基本操作和转换

// 1 个数
NSInteger count = set001.count; // 方法1 点语法
//NSInteger count = [set001 count]; // 方法2 中括号法
NSLog(@"count = %ld", count);

// 2 转换成array
// set转换成array
NSArray *array = set001.allObjects;
NSLog(@"array = %@", array);
// array转换成set
NSSet *set002 = [NSSet setWithArray:@[@"1", @"3", @"7"]];
NSLog(@"set002 = %@", set002);

// 3 获取任意一对象
NSString *string = set002.anyObject;
NSLog(@"anyObj :%@", string);

比较操作

// 比较
// 1 判断两个set是否相等
BOOL isEqual = [set001 isEqualToSet:set002];
if (isEqual)
{
	NSLog(@"set001 等于 set002");
}
else
{
	NSLog(@"set001 不等于 set002");
}

// 2 判断 setA 是否是 setB 的子集
BOOL isSub = [set002 isSubsetOfSet:set001];
if (isSub)
{
	NSLog(@"set002 是 set001 的子集");
}
else
{
	NSLog(@"set002 不是 set001 的子集");
}

// 3 判断两个set是否有交集
BOOL isIntersets = [set002 intersectsSet:set001];
if (isIntersets)
{
	NSLog(@"set002 与 set001 有交集");
}
else
{
	NSLog(@"set002 与 set001 无交集");
}

// 4 是否包含某个对象
BOOL isContains = [set002 containsObject:@"8"];
if (isContains)
{
	NSLog(@"set002 包含 8");
}
else
{
	NSLog(@"set002 不包含 8");
}

//异或
// 去掉相同的元素,即set003 去掉与 set001 中相同的元素,保留不同的元素
[set003 minusSet:set001];
NSLog(@"set003 = %@", set003);
  • NSMutableSet
// 添加元素
// 方法1 添加单个元素
[set003 addObject:@"000"];
NSLog(@"set003 = %@", set003);
 
// 方法2 从指定数组中添加多个元素
NSArray *array003 = @[@"111", @"222"];
[set003 addObjectsFromArray:array003];
NSLog(@"set003 = %@", set003);
 
// 方法3 从指定set中添加多个元素
[set003 intersectsSet:set002];
NSLog(@"set003 = %@", set003);

// 删除元素
// 1 删除批定指定
[set003 removeObject:@"111"];
NSLog(@"set003 = %@", set003);
 
// 2 删除所有元素
[set003 removeAllObjects];
NSLog(@"set003 = %@", set003);
// 重新初始化set值
[set003 setSet:set002];
NSLog(@"set003 = %@", set003);
  • block
    • basic syntax

    Declare:

     void (^simpleBlock)(void);
    

    With no arguments and no return value

    simpleBlock = ^{
    	...
    }
    

    Same as (explicit assign the return type and arguments are voids)

     void (^simpleBlock)(void) = ^{
            NSLog(@"This is a block");
        };
    

    Invoke block

    simpleBlock();
    
    • Block with return type and arguments

       double (^multiplyTwoValues)(double, double);
      

    Example:

        ^ (double firstValue, double secondValue) {
            return firstValue * secondValue;
        }
            double (^multiplyTwoValues)(double, double) =
                                  ^(double firstValue, double secondValue) {
                                      return firstValue * secondValue;
                                  };
     
        double result = multiplyTwoValues(2,4);
     
        NSLog(@"The result is %f", result);
    
    • Capture values from the Enclosing Scope

    As well as containing executable code, a block also has the ability to capture state from its enclosing scope.

    If you declare a block literal from within a method, for example, it’s possible to capture any of the values accessible within the scope of that method, like this:

Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked, like this:

    int anInteger = 42;
 
    void (^testBlock)(void) = ^{
        NSLog(@"Integer is: %i", anInteger);
    };
 
    anInteger = 84;
 
    testBlock();

the value captured by the block is unaffected. This means that the log output would still show:

Integer is: 42

It also means that the block cannot change the value of the original variable, or even the captured value (it’s captured as a const variable).

The complier will report error if attempting to change the value

Use __block Variables to Share Storage
Pass Block as arguments to methods or functions
Use Type Definitions to Simplify Block Syntax

If you need to define more than one block with the same signature, you might like to define your own type for that signature.

As an example, you can define a type for a simple block with no arguments or return value, like this:

typedef void (^XYZSimpleBlock)(void);

You can then use your custom type for method parameters or when creating block variables:

    XYZSimpleBlock anotherBlock = ^{
        ...
    };

​ Specify copy as the property attribute since needs to be copied to keep track of its state outside of the original scope.

  • Avoid Strong Reference Cycles when Capturing self

If you need to capture self in a block, such as when defining a callback block, it’s important to consider the memory management implications.

Blocks maintain strong references to any captured objects, including self, which means that it’s easy to end up with a strong reference cycle if, for example, an object maintains a copy property for a block that captures self:

@interface XYZBlockKeeper : NSObject
@property (copy) void (^block)(void);
@end


@implementation XYZBlockKeeper
- (void)configureBlock {
    self.block = ^{
        [self doSomething];    // capturing a strong reference to self
                               // creates a strong reference cycle
    };
}
...
@end

The compiler will warn you for a simple example like this, but a more complex example might involve multiple strong references between objects to create the cycle, making it more difficult to diagnose.

To avoid this problem, it’s best practice to capture a weak reference to self, like this:

- (void)configureBlock {
    XYZBlockKeeper * __weak weakSelf = self;
    self.block = ^{
        [weakSelf doSomething];   // capture the weak reference
                                  // to avoid the reference cycle
    }
}

By capturing the weak pointer to self, the block won’t maintain a strong relationship back to the XYZBlockKeeper object. If that object is deallocated before the block is called, the weakSelf pointer will simply be set to nil.

NSOperation and NSOperationQueue
// schedule task on main queue:
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperation:operation];
 
// schedule task on background queue:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
GCD
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    NSLog(@"Block for asynchronous execution");
});

block变量捕获

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UVQbVpGf-1663849691223)(OC学习笔记.assets/image-20210812145437599.png)]

block的底层结构-block的本质探索

写个简单的block,其中block内部使用了block外部的age变量:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
      
        int age = 20;

        void (^block)(int, int) =  ^(int a , int b){
            NSLog(@"this is a block! -- %d", age);
        };
        block(10, 10);
    }
    return 0;
}

c++代码

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 

        int age = 20;
        //block底层定义
        void (*block)(int, int) = ((void (*)(int, int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age));
        //block底层调用
        ((void (*)(__block_impl *, int, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 10, 10);
    }
    return 0;
}

NSUserDefault

//保存
- (void)saveValue:(NSString *)value forKey:(NSString *)key
{
    [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
}

//读取
- (void)readValueforKey:(NSString *)key
{
    [[NSUserDefaults standardUserDefaults] objectForKey:key];
}

NSUserDefault只能保存特定类型的对象:NSData, NSString, NSNumber, NSDate, NSArray, NSDictionary。如果想要存储其它类型,需要将打包成NSData类型。

如果保存其他类型的对象,会报错

在运行时,您可以使用NSUserDefaults对象从用户的默认数据库中读取应用程序使用的默认值。 NSUserDefaults缓存信息,以避免每次需要默认值时都打开用户的默认数据库。 它以周期性间隔自动调用的同步方法使内存中的缓存与用户的默认数据库保持同步,而不是即时写入的,为了防止在写完NSUserDefaults后程序退出导致的数据丢失,可以在写入数据后使用synchronize强制立即将数据写入磁盘:

[mySettingData synchronize];

NSUserDefaults类提供了访问常见类型(如浮点数,双精度,整数,布尔值和URL)的便利方法。 一个默认对象必须是一个属性列表,即一个实例(或用于集合,实例的组合):NSData,NSString,NSNumber,NSDate,NSArray或NSDictionary。 如果要存储任何其他类型的对象,通常需要将其归档以创建NSData实例。 下面是一个使用NSData的示例:

- (id)initWithCoder:(NSCoder *)coder  {
     if(self = [super init]) {
        // your code
        self._firstName = [coderdecode ObjectForKey:@"_firstName"];          
        self._lastName = [coderdecode ObjectForKey:@"_lastName"];     
     }
       return self; 
 }  

- (void)encodeWithCoder:(NSCoder *)coder  {
    // your code
    [coderencode Object:_firstNameforKey:@"_firstName"];      
    [coderencode Object:_lastNameforKey:@"_lastName"];     
 }

 BusinessCard *bc = [[BusinessCard alloc] init]; 
 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSData *udObject = [NSKeyedArchiverarchivedDataWithRootObject:bc];  // 将对象转换成NSData
[udsetObject:udObjectforKey:@"myBusinessCard"]; 
 udObject = nil; 
 udObject = [udobjectForKey:@"myBusinessCard"];
// 将NSData转换成对象
bc = [NSKeyedUnarchiverunarchiveObjectWithData:udObject] ;

All in all

单例模式,延迟写入(需要手动持久化)

[ud setxxx: forkey:];
[ud xxxForKey:];

NSFileManager

程序目录

目录: NSHomeDirectory() ,目录结构为:

—Documents/

—“YourAppName.app”

—Library/

—自己创建的文件夹 或 “自己创建的文件”

—tmp/

查询程序目录
[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

等价于

NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *string=[paths objectAtIndex:0];

tmp 目录我们可以在里面写入一些程序运行时需要用得数据,里面写入得数据在程序退出后会没有。

NSTemporaryDirectory()

实例化

NSFileManager defaultManager

创建文件夹

NSString *myDirectory = [documentDirectory stringByAppendingPathComponent:@"test"];

BOOL bj = [fileManage createDirectoryAtPath:myDirectory withIntermediateDirectories:YES attributes:nil error:&error];

取得一个目录下得所有文件名:(如上面的myDirectory)可用

NSArray *file = [fileManager subpathsOfDirectoryAtPath: myDirectory error:nil];

或

NSArray *files = [fileManager subpathsAtPath: myDirectory ];

或

NSArray *files=[fileManager contentsOfDirectoryAtPath:documentDirectory error:&error];


读取文件

NSData *data = [fileManger contentsAtPath:myFilePath];//myFilePath是包含完整路径的文件名

或直接用NSData 的类方法:

NSData *data = [NSData dataWithContentOfPath:myFilePath];

保存文件

可以用 NSFileManager的

- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
或 NSData 的

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;

- (BOOL)writeToFile:(NSString *)path options:(NSUInteger)writeOptionsMask error:(NSError **)errorPtr;

移动文件:

if ([fileMgr moveItemAtPath:filePath toPath:filePath2 error:&error] != YES)

删除文件:

if ([fileMgr removeItemAtPath:filePath2 error:&error] != YES)
获取图片或者资源
获取文本:

NSFileManager *fileManager=[NSFileManager defaultManager];

NSData *data=[fileManager contentsAtPath:@"/Developer/Documentation/wxWidgets/docs/lgpl.txt"];

NSString *string=[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"%@",string);

获取图片:

NSData *myData=[fileManager contentsAtPath:@"/Users/ruby/Desktop/Photo1.jpg"];

UIImage *myImage=[UIImage imageWithData:myData];

imageView.image=myImage;

所有可用的method(略读)

1)创建一个File Manager:

- init   如果你打算使用delegate,你应该使用init方法创建一个fileManager

+defaultManager

2)发现文件夹内容:

– contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:

– contentsOfDirectoryAtPath:error:

– enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:

– enumeratorAtPath:

– mountedVolumeURLsIncludingResourceValuesForKeys:options:

– subpathsOfDirectoryAtPath:error:

– subpathsAtPath:

3)创建和删除items:

– createDirectoryAtURL:withIntermediateDirectories:attributes:error:

– createDirectoryAtPath:withIntermediateDirectories:attributes:error:

– createFileAtPath:contents:attributes:

– removeItemAtURL:error:

– removeItemAtPath:error:

– replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:

4)移动和拷贝 Items

– copyItemAtURL:toURL:error:

– copyItemAtPath:toPath:error:

– moveItemAtURL:toURL:error:

– moveItemAtPath:toPath:error:

5)Determining Access to Files

– fileExistsAtPath:

– fileExistsAtPath:isDirectory:

– isReadableFileAtPath:

– isWritableFileAtPath:

– isExecutableFileAtPath:

– isDeletableFileAtPath:

6)Getting and Setting Attributes

– componentsToDisplayForPath:

– displayNameAtPath:

– attributesOfItemAtPath:error:

– attributesOfFileSystemForPath:error:

– setAttributes:ofItemAtPath:error:

7)Getting and Comparing File Contents

– contentsAtPath:

– contentsEqualAtPath:andPath:

8)Converting File Paths to Strings

– fileSystemRepresentationWithPath:

– stringWithFileSystemRepresentation:length:

9)Managing the Delegate

– setDelegate:

– delegate

10)Managing the Current Directory

– changeCurrentDirectoryPath:

– currentDirectoryPath

NSFileManagerDelegate Protocol Reference:

Moving an Item

– fileManager:shouldMoveItemAtURL:toURL:

– fileManager:shouldMoveItemAtPath:toPath:

– fileManager:shouldProceedAfterError:movingItemAtURL:toURL:

– fileManager:shouldProceedAfterError:movingItemAtPath:toPath:

Copying an Item

– fileManager:shouldCopyItemAtURL:toURL:

– fileManager:shouldCopyItemAtPath:toPath:

– fileManager:shouldProceedAfterError:copyingItemAtURL:toURL:

– fileManager:shouldProceedAfterError:copyingItemAtPath:toPath:

Removing an Item

– fileManager:shouldRemoveItemAtURL:

– fileManager:shouldRemoveItemAtPath:

– fileManager:shouldProceedAfterError:removingItemAtURL:

– fileManager:shouldProceedAfterError:removingItemAtPath:

Linking an Item

– fileManager:shouldLinkItemAtURL:toURL:

– fileManager:shouldLinkItemAtPath:toPath:

– fileManager:shouldProceedAfterError:linkingItemAtURL:toURL:

– fileManager:shouldProceedAfterError:linkingItemAtPath:toPath:

NSFileHandler

对于读写文件,NSFileManager只可以读写字符串类型的文件,而NSFileHandler是文件描述符的封装类,可以读写文件(图片、设备、网络接口)、套接字、管道和设备。

    //沙盒所在的根目录
    NSString *homeDirectory = NSHomeDirectory();
    NSLog(@"path:%@", homeDirectory);
    
    //应用程序路径
    NSString*appPath = [[NSBundle mainBundle] resourcePath];
    NSLog(@"path:%@", appPath);
    
    //document目录
    NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPaths = [docPaths objectAtIndex:0];
    NSLog(@"path:%@", documentPaths);
    
    //Cache目录
    NSArray *cacPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [cacPaths objectAtIndex:0];
    NSLog(@"%@", cachePath);
    
    //获取Library目录
    NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libraryPath = [libPaths objectAtIndex:0];
    NSLog(@"%@", libraryPath);
    
    //获取Tmp目录
    NSString *tmpDir = NSTemporaryDirectory();
    NSLog(@"%@", tmpDir);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值