美文网首页转载
iOS基础之OC的特性

iOS基础之OC的特性

作者: ValienZh | 来源:发表于2016-05-13 17:02 被阅读122次

1. ObjC一般要点

  1. OC中所有对象类型的变量都必须加上"*",在ObjC中对象其实就是一个指针.
  2. ObjC中使用[Object method]方式来进行方法调用,本质其实就是向object发送method消息.
  3. ObjC中方法分为静态方法和动态方法,动态方法就是对象方法,静态方法就是类方法.简单区别是静态方法不能使用对象实例属性,一般做工具方法.
  4. 公共成员(public)的调用可以使用"->"操作符.
  5. 成员变量和属性: 通常一个成员的访问不会直接通过成员变量 而是通过属性暴露给外界.ObjC中实现属性就是通过setter和getter方法来实现.

成员属性的声明方式:

  1. 如果只声明一个属性@property a : 编译器会使用"_a"作为属性的成员变量 .
    (如果没有手动定义则系统会自动生成一个私有的成员变量_a; 如果已经定义了成员变量_a则系统使用定义的这个;注意:如果此时定义的成员变量是a,则此时系统依旧会自动生成一个成员变量_a,它跟自定义成员变量a没有任何关系);
  2. 如果声明一个属性@property a,且仅使用@synthesize a进行声明,过程中没有指定使用的成员变量,此时编译器会使用"a"作为属性的成员变量;
    如果使用的是@synthesize a=_a声明情况下:
    如果定义了成员变量a,则使用这个自定义的;如果没有定义则会自动生成一个私有的成员变量a; 如果定义了的是 _a,没有任何关系;
  3. 如果声明了一个@property a,使用@synthesize a = _a 实现; 这个过程已经指定了使用的成员变量, 此时会使用指定的成员变量作为属性变量_a.

@synthesize实际的意义就是 自动生成属性的setter和getter方法。是不是很绕?所幸苹果在iOS6之后只需@property声明就可自动生成setter和getter.

声明属性相对于@synthesize,还可以使用@dynamic关键字,这表示告诉编译器不自动生成setter和getter方法.避免编译期间的警告;
然后根据需要自己实现存取方法或是 在运行时动态绑定(主要用于在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行时的动态生成子类属性)如果你不是使用Core Data,那么忽略他吧.

自定义构造方法

-(instance)initWithName:(NSString*) name age:(int)age {
    if(self = [super init]) { //继承父类的初始设置
        self.name = name; // 这里就写对象本身实例时初始属性设置.
        self.age = age; 
    }
    return self ;
}

description方法

在C#中每个类都有一个ToString()方法, JAVA中叫toString(), 都是用于打印一个对象的信息;在ObjC中这个方法叫做description.默认输出类名和地址. 重写此方法用于调试;(注意:不能在此方法中打印输出self,死循环)

-(NSString *)description{
    return [NSString stringWithFormat:@"{name:%@,age:%i}",self.name,self.age];
}

OC中的多继承

多继承是从多个直接基类派生 类的能力,可以更加直接为应用程序建模;

而ObjC不支持多继承,这是由于消息机制中名字查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题;

不过我们可以使用间接实现多继承的目的:
三种方法: 代理,类别和消息转发.

1. 代理和协议

委托是ObjC中最常见的一种回调机制

2.类别

用分类直接添加方法,运行时添加实例变量

3. 消息转发:

当向someObject发送消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runtime system并不会立即报错崩溃,而是依次执行以下步骤:

4196_130528172246_1.png
  1. 动态方法解析: 向当前类发送resolveInstanceMethod:信号, 检查是否动态向该类添加了方法.(@dynamic);
  2. 快速消息转发: 检测该类是否实现了forwardingTargetForSelector:方法 ,如果实现就调用; 若该方法返回值对象非nil或非self, 则向该返回对象 重新发送消息.
  • 标准消息转发: runtime发送methodSignatureForSelector:消息获取Selector对应的方法签名. 返回值非空则通过forwardInvocation:转发消息,返回值为空就会向当前对象发送doesNotRecognizeSelector:消息崩溃退出;

利用上述的过程的2,3两步完成消息转发的两种方式,下面具体说明:

3.1 快速消息转发

实现很简单,只需重写- (instances)forwardingTargetForSelector:(SEL)aSelector,就可以让A类调用B类的方法,从而实现多继承的目的:

//例. Teacher类实现 将消息转发给Doctor,
-(instances)forwardingTargetForSelector:(SEL)aSelector {
    Doctor *doctor = [[Doctor alloc] init];
    if([doctor respondsToSelector:aSelector]) {
        return doctor;
    }
    return nil;
}

虽然消息可以动态转发传递,但是编译器的静态检查不通过,需要给Teacher声明要调用的方法,但是Teacher没有实现,那么该如何声明呢? 下面有两种方式解决:

  1. 声明方法-类别: 给Teacher添加分类,在其中声明operator方法.
  2. 导入Doctor头文件, 进行类型强转: 告诉编译器去Doctor中找operator方法的声明,并在调用时强转类型:
Teacher *teacher = [[Teacher alloc]init]; 
 [(Doctor *)teacher operate]; 
3.2 标准消息转发

标准消息转发是重写 methodSignatureForSelector: 和 forwardInvocation:两个方法即可。

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector   
{   
    NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];   
    if (signature==nil) {   
        signature = [someObj methodSignatureForSelector:aSelector];   
    }   
    NSUInteger argCount = [signature numberOfArguments];   
    for (NSInteger i=0 ; i
    }   
       
    return signature;   
}   
   
- (void)forwardInvocation:(NSInvocation *)anInvocation   
{   
    SEL seletor = [anInvocation selector];   
    if ([someObj respondsToSelector:seletor]) {   
        [anInvocation invokeWithTarget:someObj];   
    }   
       
}   

两种消息转发方式比较:
快速消息转发: 简单快速,但是仅能转发给一个对象. 标准消息转发:复杂,转发可控,可以实现多对象转发.


多态

  • 多态: 不同对象以自己的方式响应相同的消息.
  • 目的: 简化编程接口,容许在类与类之间重用一些习惯性的命名,而不用为每一个新加的函数想一个新名字.
  • 原理:每个类都属于该类的名字空间,类定义中的名字和类定义外的名字不冲突. 动态绑定.

多态的具体实现:
在ObjC中是通过一个叫做selector的选取器实现的,在Object-C中selector有两个意思:

  1. 当给对象的源码消息时,用来指方法的名字;
  2. 在源码编译后代替方法名的唯一标识;

选取器特点:所有同名的方法拥有同样的选取器. 而所有选取器都各不相同;

  1. SEL和@selector区别:选择器的类型是SEL.而 @selector指示符是用来引用选择器的, 它返回类型是SEL.
    • 例:SEL response; response = @selector(load:)
    • 通过字符串来得到选取器:responseSEL = NSSelectorFromString(@"loadDataForTableView:");
    • 通过选择器转换来得到方法名: NSString *methodName = NSStringFromSelector(responseSEL);
  2. 方法和选取器: 选取器确定的是方法名,不是方法的实现, 这是多态和动态绑定的基础.它使得向不同对象发送相同的消息成为现实.
  3. 方法返回值和参数类型: 消息机制是通过选取器找到方法的返回值类型和参数类型. 因此: 动态绑定需要同名方法的实现 拥有相同返回值类型和相同的参数类型;否则,运行时可能出现找不到对应方法的错误.(有一个例外,虽然同名静态方法和实例方法拥有相同的选取器,但是它们可以有不同的参数类型和返回值类型。)

相关文章

  • iOS基础之OC的特性

    1. ObjC一般要点 OC中所有对象类型的变量都必须加上"*",在ObjC中对象其实就是一个指针. ObjC中使...

  • 面试技巧攻克(2)-Objective-C语言

    面试技术攻克(1)-iOS开发基础 面试技巧攻克(3)-OC高级特性 面试技巧攻克(4)-iOS中对象间通信机制 ...

  • iOS10新特性整理

    apple关于iOS10新特性介绍 iOS10新特性个人总结iOS9.3~iOS10 API的变化 (OC 加入:...

  • iOS基础 - oc的三大特性

    封装、继承、多态 oc是面向对象的程序设计语言,而面向对象的三大特征:封装、继承、多态。 封装 没有绝对的封装,只...

  • OC基础特性

    一、分类(Category) 问题1:你用分类都做了哪些事情? 声明私有方法 分解体积庞大的类文件 把Framew...

  • 技术在于交流,知识在于收集(一)

    收集的一些iOS开发技术博客与牛人共同进步 iOS基础: OC语法基础 OC代码规范 从零学习iOS开发的15条建...

  • 面试技巧攻克-OC高级特性

    作者:iOS大蝠 一、runtime机制 1、什么是runtime? runtime是OC的重要特性,使得OC语言...

  • 面试题之 OC

    OC语言的特性? ①OC 语言是 C 语言的一个超集,在 C 的基础上添加了面向对象的特性;②OC 语言与 Jav...

  • 第一章:熟悉OC

    OC语言特性:-1. OC是在C的语言基础上添加了面向对象特性。 -2. OC与C++,JAVA等面向对象的语言类...

  • 关于iOS

    //iOS一般用oc写,也可以用swift写.目前oc还是主流,swift是未来趋势. OC的理解与特性 OC作为...

网友评论

    本文标题:iOS基础之OC的特性

    本文链接:https://www.haomeiwen.com/subject/raaprttx.html