Objective-C语言入门

c++开发找实习,结果找到了WXG-iOS客户端开发,记录一下学习经历。

iOS开发基本还是使用Objective-C语言,该语言被认为是C语言的超集,赋予了C语言面向对象的能力,完全支持C/C++语言,但和C++语言的面向对象有很大不同,它是以消息机制为底的,比如可以面向向不包含该方法的对象发送该消息,可以通过编译,直到运行的时候才会报错。

1.OC对象的本质

OC语言结构
OC中万物来源于NSObject,很多类都是继承自它。它的本质在源码中可以看到

struct NSObject_IMPL {
	Class isa;
};
// 查看Class本质
typedef struct objc_class *Class;
我们发现Class其实就是一个指针,对象底层实现其实就是这个样子。

类结构图解
OC的类信息存放在哪里 OC对象主要可以分为三种

  • instance对象(实例对象)
  • class对象(类对象)
  • meta-class对象(元类对象)

instance对象
就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
instance对象在内存中存储的信息包括

  • isa指针
  • 其他成员变量

class对象
我们通过class方法或runtime方法得到一个class对象。class对象也就是类对象。
成员变量的值时存储在实例对象中的,因为只有当我们创建实例对象的时候才为成员变赋值。但是成员变量叫什么名字,是什么类型,只需要有一份就可以了。所以存储在class对象中。
每一个类在内存中有且只有一个class对象。可以通过打印内存地址证明
class对象在内存中存储的信息主要包括

  • isa指针
  • superclass指针
  • 类的属性信息(@property),类的成员变量信息(ivar)
  • 类的对象方法信息(instance method),类的协议信息(protocol)

元类对象 meta-class
每个类在内存中有且只有一个meta-class对象。
meta-class对象和class对象的内存结构是一样的,所以meta-class中也有类的属性信息,类的对象方法信息等成员变量,但是其中的值可能是空的。
在内存中存储的信息主要包括:

  • isa指针
  • superclass指针
  • 类的类方法的信息(class method)

关于isa、superclass

  1. instance的isa指向class
    当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用。
  2. class的isa指向meta-class
    当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用
  3. meta-class的isa指向基类的meta-class,基类的isa指向自己
    class的superclass指向父类的class,如果没有父类,superclass指针为nil
  4. meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class
  5. instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类
  6. class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类
    类间结构ISA指向

2.委托(delegate)

这是一种设计模式,就是某个对象指定另一个对象处理某些特定任务的设计模式。通俗来说,就是“某个对象”把要做的事情委托给“另一个对象”去做。iOS客户端开发中感觉这是一个特色,就像QT开发中的信号槽机制,好像也类似QT的信号槽机制,用于传值。

  • 比如:两个类之间的传值,类A调用类B的方法,类B在执行过程中遇到问题通知类A,这时候我们需要用到代理(Delegate)。
  • 又比如:控制器(Controller)与控制器(Controller)之间的传值,从C1跳转到C2,再从C2返回到C1时需要通知C1更新UI或者是做其它的事情,这时候我们就用到了代理(Delegate)传值。

委托与代理
托方通过某种方式把任务分派出去给代理方处理,而两者之间的联系便是协议。

比如view视图一般作为委托方,controller作为代理方,controller实现view中的具体流程,举个例子在登录流程中,view提供用户名和密码传递给controller,controller类里面具体实现和后台交互等的验证流程等。

在程序中:一般情况下
1.委托需要做的工作有:

  • 1.1定义协议与方法
  • 1.2声明委托变量
  • 1.3设置代理
  • 1.4通过委托变量调用委托方法

2.代理需要做的工作有:

  • 2.1遵循协议
  • 2.2实现委托方法

3. block

概述

闭包 = 一个函数「或指向函数的指针」+ 该函数执行的外部的上下文变量「也就是自由变量」;Block 是 Objective-C 对于闭包的实现。
其中,Block:

  • 可以嵌套定义,定义 Block 方法和定义函数方法相似
  • Block 可以定义在方法内部或外部
  • 只有调用 Block 时候,才会执行其{}体内的代码
  • 本质是对象,使代码高聚合

使用 clang 将 OC 代码转换为 C++ 文件查看 block 的方法:

  • 在命令行输入代码 clang -rewrite-objc 需要编译的OC文件.m
  • 这时查看当前的文件夹里 多了一个相同的名称的 .cpp 文件,在命令行输入 open main.cpp 查看文件

Block的定义与使用

1、无参数无返回值

//1,无参数,无返回值,声明和定义

void(^MyBlockOne)(void) = ^(void){
NSLog(@"无参数,无返回值");  
};  
MyBlockOne();//block的调用

2、有参数无返回值

//2,有参数,无返回值,声明和定义
void(^MyblockTwo)(int a) = ^(int a){
NSLog(@"@ = %d我就是block,有参数,无返回值",a);
};  
MyblockTwo(100);

3、有参数有返回值

//3,有参数,有返回值
int(^MyBlockThree)(int,int) = ^(int a,int b){    
  NSLog(@"%d我就是block,有参数,有返回值",a + b);
  returna + b; 
 };  
MyBlockThree(12,56);

4、无参数有返回值(很少用到)

//4,无参数,有返回值
int(^MyblockFour)(void) = ^{NSLog(@"无参数,有返回值");
        return45;
};
MyblockFour();

5、实际开发中常用typedef 定义Block
例如,用typedef定义一个block:

typedef int (^MyBlock)(int , int);

这时,MyBlock就成为了一种Block类型
在定义类的属性时可以这样:

@property (nonatomic,copy) MyBlock myBlockOne;

使用时:

self.myBlockOne = ^int (int ,int){
//TODO
}

Block与外界变量

1、截获自动变量(局部变量)值

(1)默认情况

对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的。也就是说block的自动变量截获只针对block内部使用的自动变量, 不使用则不截获, 因为截获的自动变量会存储于block的结构体内部, 会导致block体积变大。特别要注意的是默认情况下block只能访问不能修改局部变量的值。

int age = 10;
myBlock block = ^{
    NSLog(@"age = %d", age);
};
age = 18;
block();
输出结果:

age = 10

(2) __block 修饰的外部变量

对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的。block可以修改__block 修饰的外部变量的值。

__block int age = 10;
myBlock block = ^{
    NSLog(@"age = %d", age);
};
age = 18;
block();
输出为:

age = 18

为什么使用__block 修饰的外部变量的值就可以被block修改呢?

我们使用 clang 将 OC 代码转换为 C++ 文件:

clang -rewrite-objc 源代码文件名

便可揭开其真正面纱:

__block int val = 10;
转换成
__Block_byref_val_0 val = {
    0,
    &val,
    0,
    sizeof(__Block_byref_val_0),
    10
};

会发现一个局部变量加上__block修饰符后竟然跟block一样变成了一个__Block_byref_val_0结构体类型的自动变量实例!!!!

weakSelf和strongSelf

类似于c++中的shared_ptr和weak_ptr,用于解决循环引用问题。
1.使用__weak __typeof是在编译的时候,另外创建一个局部变量weak对象来操作self,引用计数不变。block 会将这个局部变量捕获为自己的属性,
访问这个属性,从而达到访问 self 的效果,因为他们的内存地址都是一样的。

2.因为weakSelf和self是两个变量,doSomething有可能就直接对self自身引用计数减到0了.
所以在[weakSelf doSomething]的时候,你很难控制这里self是否就会被释放了.weakSelf只能看着.

3.__strong __typeof在编译的时候,实际是对weakSelf的强引用.
指针连带关系self的引用计数会增加.但是你这个是在block里面,生命周期也只在当前block的作用域.
所以,当这个block结束, strongSelf随之也就被释放了.不会影响block外部的self的生命周期.

总结
在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。
如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。

4.property

Objective C中的proprety声明的具体操作如下:

@interface IntervalTimePair : NSObject
@property (nonatomic, copy) NSString *content;
@end
相当于:
@interface IntervalTimePair : NSObject
NSString * _content;
- (void)setContent:(NSString*)c;
- (NSString*)Content;
@end

所以真正的成员变量是_content,而Content其实是一个方法。重要!!!

property属性
作用:提供成员变量的访问方法的声明、控制成员变量的访问权限、控制多线程时成员变量的访问环境。
使用范围:property不但可以在interface,在协议protocol和类别category中也可以使用。

@property有两个对应的词,一个是 @synthesize,一个是 @dynamic。如果 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var;

synthesize 合成访问器方法,表示如果属性没有手动实现setter和getter方法,编译器会自动加上这两个方法。
作用:实现property所声明的方法的定义。
说直白就像是:property声明了一些成员变量的访问方法,synthesize则定义了由property声明的方法。
他们之前的对应关系是:property 声明方法 ->头文件中申明getter和setter方法 synthesize定义方法 -> m文件中实现getter和setter方法。

dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。假如一个属性被声明为 @dynamic var,而且你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

1、在头文件中:

 @property int count; 

等效于在头文件中声明2个方法:

 - (int)count;  
 -(void)setCount:(int)newCount;  

2、实现文件(.m)中

@synthesize count;  

等效于在实现文件(.m)中实现2个方法。

- (int)count  
 {  
     return count;  
 }  
-(void)setCount:(int)newCount  
 {  
    count = newCount;  
}  

在Xcode4.5及以后的版本中,可以省略@synthesize,编译器会自动帮你加上get 和 set 方法的实现,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做 _age的私有成员变量。

参考:
iOS底层原理总结 - 探寻OC对象的本质(底层原理系列文章)
OC源码分析之对象的创建(源码分析系列文章)
iOS Block 详解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值