Objective-C 基础

2017-12-07  本文已影响0人  ChenME

iOS常用存储方式:

  1. XML属性列表(plist)归档;
  2. Preference(偏好设置);
  3. NSKeyedArchiver 归档(NSCoding);
  4. SQLite3(数据库);
  5. Core Data;

应用沙盒

Documents
Library / Caches
Library / Preferences
tmp


实例变量修饰符

-- public protect(默认) private
本类 可以 可以 可以
子类 可以 可以 不可以
其他类 可以 不可以 不可以

package 如果在其他包中访问就是 private 的,如果在当前代码所在的包中访问就是 public 的。


关键字

  1. @ property (编译器指令):在 xcode4.4 之前,可以使用 @property 来代替 getter/setter 方法的声明;在 xcode4.4 之后,同时可以代替 getter/setter 方法的声明和实现;

@ property 的修饰符:

  1. readonly :只读(即只生成 getter 方法)
  2. readwrite :可读可写(即生成 getter 方法,也生成 setter 方法,默认
  3. getter=[方法名] :修改 getter 方法的方法名;
  4. setter=[方法名:] :修改 setter 方法的方法名;
  5. retain :自动生成 setter 方法内存管理代码(参见内存管理中的第二点);
  6. assign :不会帮我们生成生成 setter 方法的内存管理代码(默认);
  7. atomic :性能低(单线程,默认
  8. nonatomic :性能高(多线程,在 iOS 开发中基本都使用 nonatomic
  9. strong :在ARC中,用于OC对象,相当于MRC中的 retain
  10. weak :在ARC中,用于OC对象,相当于MRC中的 assign
  11. copy :一般用在字符串后面,可以防止外界修改内部的数据;
  1. @synthesize [参数名 = 属性名] (编译器指令):代替 getter/setter 方法的实现;在 xcode4.4 之后可以使用 @proerty 代替;

动态数据类型( idinstancetype

isKindOfClass: // 判断当前对象是否是指定类的对象,或者是指定类子类的对象
inMemberOfClass: // 判断当前对象是否是指定类的对象

idinstancetype 的区别

  1. id 在编译的时候不能判断对象的真实类型,而 instancetype 可以;(注意:在自定义构造方法时,尽量使用 instancetype
  2. id 可以用来定义变量、可以作为形参、可以作为返回值,而 instancetype 只能用来作为返回值;

构造方法

- (instancetype)init{
    if(self = [super init]){
        // 要实现的代码
    }
    return self;
}

类的启动过程

只要程序启动就会将所有类的代码加载到内存中,放到代码区

  1. +(void)load 方法会在当前类被加载到内存的时候调用,有且仅会调用一次;

在继承关系中,会先调用父类的 +(void)load 方法,再调用子类的 +(void)load 方法;

  1. +(void)initialize 方法会在当前类第一次被使用的时候调用(创建类的时候),该方法在整个程序的运行过程中只会被调用一次;

+(void)load 方法一样,如果存在继承关系,会先调用父类的 +(void)initialize 方法,再调用子类的 +(void)initialize 方法;


内存管理

  1. ARC:-> Automatic(自动) Reference(引用) Counting(计数),不需要程序员管理内存,编译器会在适当的地方添加 release/retain 等代码;

OC 中的 ARC 和 Jave 中的垃圾回收机制不太一样,Java 中的垃圾回收时系统干的,而 OC 中的 ARC 是编译器干的;

  1. MRC:-> Manul(手动) Reference(引用) Counting(计数),所有对象的内容都需要我们手动管理,需要程序员自己编写 release/retain 等代码;
-(void) setRoom:(Room *)room{
    if(_room != room){

        // 先释放掉原来的 Room 引用计数器( -1 )
        [_room release];
        
        // 对新的 Room 引用计数器 +1,同时进行赋值操作
        _room = [room retain];
    }
}

ARC

  1. ARC 的判断准则:只要没有强指针指(默认情况下,所有的指针都是强指针)向对象,对象就会被释放。
  2. 强指针、弱指针的表示方法:
__strong Person *p1 = [[Person alloc] init]; // 强指针
__weak Person *p2 = [[Person alloc] init]; // 弱指针

在ARC中保存对象不要使用 assign,要使用 weakassign 是专门用于保存基本数据类型的,如果保存对象用 weak
strong :在ARC中,用于OC对象,相当于MRC中的 retain
weak :在ARC中,用于OC对象,相当于MRC中的 assign
assign :在ARC中,用于保存基本数据类型,跟MRC中的 assign 一样;


Category

  1. 作用:
  1. 使用:
// 声明(在 .h 文件中)
@interface ClassName (CategoryName)
// 需要扩充的方法的声明
@end

// 实现(在 .m 文件中)
@implementation ClassName (CategoryName)
// 需要扩充的方法的实现
@end
  1. 注意事项:

Block

  1. block 的定义:
// block 的定义
// 返回值类型 (^block变量名)(形参列表) = ^返回值类型 (形参列表){};
  1. block 的定义、赋值以及调用示例:
// 1. 定义一个block:
// int -> 代表 block 将来保存的代码有一个 int 类型的返回值;
// (^sumBlock) -> 代表 sumBlock 是一个 block 变量,可以用于保存一段 block 代码;
// (int, int) -> 代表 block 将来保存的代码需要两个 int 类型的参数;
int (^sumBlock) (int, int);

// 2. 给 block 赋值:
// int -> 表示返回值类型为 int,可省略
// ^ -> 代表是一个 block 代码块;
// (int num1, int num2) -> 代表需要两个 int 类型的形参,形参名分别为 num1 和 num2;
sumBlock = ^int (int num1, int num2){
    // 想要封装的代码段 ... ...
    return num1 + num2;
};

// 3. 调用 block:
int sum = sumBlock(1, 2);
NSLog(@"sum = %i", sum);
  1. Block 与 typedef 的结合使用:
typedef int (^calculate)(int, int); // 给 block 起一个别名叫 calculte
void useBlock1(){
    
    calculate sumBlock = ^(int value1, int value2){
        return value1 + value2;
    };
    NSLog(@"sum = %i", sumBlock(20, 10));
    
    calculate minusBlock = ^(int value1, int value2){
        return value1 - value2;
    };
    NSLog(@"minus = %i", minusBlock(20, 10));
}
  1. 注意事项:
void announcementsOfBlock(){
    // 1. block 中可以访问外面的变量;
    int a = 10;
    void (^blockTest)() = ^void (){
        NSLog(@"a = %i",a); // 输出结果 a = 10
    };
    blockTest();
}
void announcementsOfBlock(){    
    // 2. block 中可以定义和外面同名的变量,并且如果如此定义了,在 block 中访问的是 block 的变量
    int a = 10;
    void (^blockTest)() = ^void{
        int  a = 20;
        NSLog(@"a = %i",a); // 输出结果 a = 20
    };
    blockTest();
}
void announcementsOfBlock(){
    // 3. 默认情况下,不可以在 block 中修改外面的值;
    int a = 10;
    void (^blockTest)() = ^(){
        // a = 20; // 此处会编译失败
    };
    blockTest();
}
void announcementsOfBlock(){
    // 4. 如果想在 block 中修改外面的变量,需要在声明变量时加上 __block
    // 在不加 __block 时,在 block 块中访问外面的变量 a 时,是把 a 的值作为参数传入到 block 块中
    // 在加上 __block 时,在 block 块中访问外面的变量 a 时,是把 a 的地址作为参数传入到 block 块中
    __block int a = 10;
    void (^blockTest)() = ^{
         a = 20;
    };
    blockTest();
    NSLog(@"a = %i",a); // 输出结果 a = 20
}

协议(protocol)

  1. 语法格式:
// 例如下面一个运动的协议
@protocol SportProtocol <NSObject>
// 方法的声明列表
- (void)playFootball;
- (void)playBasketball;
- (void)playBaseball;
@end
  1. 特点:
  1. 协议中的关键字:

注意: @required@optional 仅仅是用于程序员之间的交流,并不能严格的控制某一个遵守该协议的类必须要实现该方法,因为即使不实现,也不会报错,只会抱一个警告。


copy相关

  1. 如果是浅拷贝,那么系统就会对原来的对象进行 retain

持续更新中... ...


上一篇 下一篇

猜你喜欢

热点阅读