简述OC语言

对于一门语言的学习是需要时间领悟的,而对于一些原理性的问题,我们需要清楚其核心思想,知其然而知其所以然,这样才能有利于自己的后续发展。本文只是简述,没有面面具到(后续会持续更新)。


OC是在C语言的基础上加入了一些面向对象的特性(封装,继承,多态),OC完全兼容C语言,在代码中,可以混用C,甚至是C++代码(C++是在C语言的基础上开发的一种面向对象编程语言)。

抽象是面向对象的思想基础,抽象包括两个方面,一是过程抽象,二是数据抽象,抽象是一种思想,封装继承和多态是这种思想的实现。

封装

封装是把过程和数据包围起来,有限制的对数据的访问。

继承

继承是一种层次模型,允许和鼓励类的重用,继承性很好的解决了软件的可重用性问题。但是,不恰当地使用继承导致的最大的一个缺陷特征就是高耦合(有时候也是一种需求),恰当使用继承可以达到层级关系明显,功能划分清晰。

多态

其本质是子类通过覆盖或重载父类的方法,来使得对同一类对象同一方法的调用产生不同的结果。

消息传递

消息传递模型(Message Passing)是Objective-C语言的核心机制。在Objective-C中,没有方法调用这种说法,只有消息传递。在C++或Java中调用某个类的方法,在Objective-C中是给该类发送一个消息。在C++或Java里,类与类的行为方法之间的关系非常紧密,一个方法必定属于一个类,且于编译时就已经绑定在一起,所以你不可能调用一个类里没有的方法。而在Objective-C中就比较简单了,类和消息之间是松耦合的,方法调用只是向某个类发送一个消息,该类可以在运行时再确定怎么处理接受到的消息。也就是说,一个类不保证一定会响应接收到的消息,如果收到了一个无法处理的消息,那么程序就是简单报一个错。甚至你可以向一个值为nil的空对象发送消息,系统都不会出错或宕掉。这种设计本身也比较符合软件的隐喻。

动态性(Runtime)

Objective-C 是面相运行时的语言,它会尽可能的把编译和链接时要执行的逻辑延迟到运行时。使用Runtime可以按需要把消息重定向给合适的对象,交换方法的实现等等。 Runtime简称运行时,其中最主要的是消息机制,是一个主要使用 C 和汇编写的库,为 C 添加了面相对象的能力并创造了 Objective-C。。OC的函数调用称为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。 如:

[obj makeText];
objc_msgSend(obj,@selector(makeText));

编译器执行上述转换。在objc_msgSend函数中,首先通过obj的isa指针找到obj对应的class。每个对象内部都默认有一个isa指针指向这个对象所使用的类。isa是对象中的隐藏指针,指向创建这个对象的类。在Class中先去cache中通过SEL查找对应函数method(cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若cache中未找到,再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。

OC的动态性的三方面

动态类型、动态绑定、动态加载(动态是因为 到运行时(runtime)才会做一些事情)

动态类型:就是id类型; 动态绑定:需要用到@selector/SEL,SEL并不是C里面的函数指针,,SEL变量只是一个整数,他是该方法的ID。我们是根据一个ID整数来查找方法,不仅方便,而且效率更高。 动态加载:就是根据需求动态地加载资源,在运行时加载新类。在运行时创建一个新类,只需要3步:

1、为 class pair分配存储空间 ,使用 objc_allocateClassPair函数 2、增加需要的方法使用class_addMethod函数,增加实例变量用class_addIvar 3 、用objc_registerClassPair函数注册这个类,以便它能被别人使用。

强大的Method Swizzling(方法交叉使用)

在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用Objective-C的动态特性,可以实现在运行时偷换selector对应的方法实现,达到给方法挂钩的目的。每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP类似函数指针,指向具体的Method实现。

用 method_exchangeImplementations 来交换2个方法中的IMP, 用 class_replaceMethod 来修改类, 用 method_setImplementation 来直接设置某个方法的IMP,归根结底,都是偷换了selector的IMP。

RunLoop

RunLoop是一让线程能随时处理事件但不退出的机制。 RunLoop的四个作用为:使程序一直运行接受用户输入;决定程序在何时应该处理哪些Event;调用解耦;节省CPU时间。 主线程的runloop默认是启动的。 Cocoa中的NSRunLoop类并不是线程安全的。 对其它线程来说,runloop默认是没有启动的。 Runloop在你要和线程有更多的交互时才需要,比如以下情况:

1.使用端口或自定义输入源来和其他线程通信;

2.使用线程的定时器;

3.Cocoa中使用任何performSelector...的方法;

4.使线程周期性工作;

事件响应链

对于IOS设备用户来说,操作设备的方式主要有三种:触摸屏幕、晃动设备、通过遥控设施控制设备。对应的事件类型有以下三种: 1、触屏事件(Touch Event) 2、运动事件(Motion Event) 3、远端控制事件(Remote-Control Event)

传递链:由系统向离用户最近的view传递。 响应链:由离用户最近的view向系统传递。

UIResponder是所有响应对象的基类,在UIResponder类中定义了处理上述各种事件的接口。我们熟悉的UIApplication、 UIViewController、UIWindow和所有继承自UIView的UIKit类都直接或间接的继承自UIResponder,所以它们的实例都是可以构成响应者链的响应者对象。 响应者链有以下特点: 1、响应者链通常是由视图(UIView)构成的; 2、一个视图的下一个响应者是它视图控制器(UIViewController)(如果有的话),然后再转给它的父视图(Super View); 3、视图控制器(如果有的话)的下一个响应者为其管理的视图的父视图; 4、单例的窗口(UIWindow)的内容视图将指向窗口本身作为它的下一个响应者,Cocoa Touch应用不像Cocoa应用,它只有一个UIWindow对象,因此整个响应者链要简单一点; 5、单例的应用(UIApplication)是一个响应者链的终点,它的下一个响应者指向nil,以结束整个循环。

生命周期

1、application didFinishLaunchingWithOptions:当应用程序启动时执行,应用程序启动入口,只在应用程序启动时执行一次。若用户直接启动,lauchOptions内无数据,若通过其他方式启动应用,lauchOptions包含对应方式的内容。 2、applicationWillResignActive:在应用程序将要由活动状态切换到非活动状态时候,要执行的委托调用,如 按下 home 按钮,返回主屏幕,或全屏之间切换应用程序等。 3、applicationDidEnterBackground:在应用程序已进入后台程序时,要执行的委托调用。 4、applicationWillEnterForeground:在应用程序将要进入前台时(被激活),要执行的委托调用,刚好与applicationWillResignActive 方法相对应。 5、applicationDidBecomeActive:在应用程序已被激活后,要执行的委托调用,刚好与applicationDidEnterBackground 方法相对应。 6、applicationWillTerminate:在应用程序要完全推出的时候,要执行的委托调用,这个需要要设置UIApplicationExitsOnSuspend的键值。

</br>

初次启动: iOS_didFinishLaunchingWithOptions iOS_applicationDidBecomeActive 按下home键: iOS_applicationWillResignActive iOS_applicationDidEnterBackground 点击程序图标进入: iOS_applicationWillEnterForeground iOS_applicationDidBecomeActive

当应用程序进入后台时,应该保存用户数据或状态信息,所有没写到磁盘的文件或信息,在进入后台时,最后都写到磁盘去,因为程序可能在后台被杀死。释放尽可能释放的内存。 - (void)applicationDidEnterBackground:(UIApplication *)application 方法有大概5秒的时间让你完成这些任务。如果超过时间还有未完成的任务,你的程序就会被终止而且从内存中清除。

如果还需要长时间的运行任务,可以在该方法中调用

[application beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"begin Background Task With Expiration Handler");
 }];

本文组织语言时参考的文章:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

身为程序猿,怎能不懂RegExp?

正则表达式是程序猿的好朋友。这体现在两个方面:一、在我们敲的代码里面,可以用正则表达式非常轻巧、灵便、快捷的完成字符串的操作,比如匹配、搜索、提取子串等。二、我...

2155
来自专栏Java开发者杂谈

分布式改造剧集2---DIY分布式锁

1647
来自专栏逸鹏说道

C# 温故而知新: 线程篇(三)下

结果计时器会一直滚动,因为a对象被锁住,除非完成Thread.Sleep(3000000)后才能进入到a共享区 ? 由于以上的问题,微软还是建议我们使用一个私有...

3766
来自专栏cmazxiaoma的架构师之路

【分布式架构之旅】Redis入门

2663
来自专栏LeoXu的博客

Flex笔记_验证用户输入

1152
来自专栏joycl

c#面试题汇总

下面的参考解答只是帮助大家理解,不用背,面试题、笔试题千变万化,不要梦想着把题覆盖了,下面的题是供大家查漏补缺用的,真正的把这些题搞懂了,才能“以不变应万变”。...

5361
来自专栏小樱的经验随笔

堆和栈的区别

一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量...

3639
来自专栏大内老A

一个通过JSONP跨域调用WCF REST服务的例子(以jQuery为例)

JSONP(JSON with Padding)可以看成是JSON的一种“使用模式”,用以解决“跨域访问”的问题,这篇简单的文章给出一个简单的例子用于模拟如何通...

2117
来自专栏LhWorld哥陪你聊算法

【Linux篇】--awk的使用

awk是一个强大的文本分析工具。相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。 简单来说awk就是把文件逐行的读入,(空格...

1442
来自专栏犀利豆的技术空间

徒手撸框架--实现 RPC 远程调用

微服务已经是每个互联网开发者必须掌握的一项技术。而 RPC 框架,是构成微服务最重要的组成部分之一。趁最近有时间。又看了看 dubbo 的源码。dubbo 为了...

1552

扫码关注云+社区

领取腾讯云代金券