多线程,是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,进而提升整体处理性能。

一、进程与线程

1. 进程

关于进程,我们从两个角度出发来观察它。

1.1 系统角度

​ 具有一定独立功能的程序关于某个数据集合上的运行活动,是系统进行资源分配和调度的最小独立单位。

怎么理解上面这句话呢?

首先,进程是“动”的,不是静态的,程序躺在硬盘里,不是进程,进程是要“运行的”。
其次,具有独立功能,一个进程完成在运行的过程中,要完成一定功能。
最后,在某个数据集合上的处理,任何程序都在数据集合上进行数据的采集、处理、分析到给出人们想要的数据。

从上面,可以得出进程的三个特征:

特性:

  • 独立性:独立存在的实体,拥有自己独立资源和私有地址空间;
  • 动态性:进程是一个正在系统中活动指令集合,具有生命周期和各种状态;
  • 并发性:多个进程可在单处理器并发执行;
阅读全文 »

之前的Block系列文章,我们已经对Block的方方面面都作了阐述,但是针对内存管理,我们还有最后一个需要讨论的话题——循环引用。

本文将会针对循环引用做一个讨论,同时,将会对Block涉及的内存管理做一个总结。

本文源码–循环引用

一、循环引用

1.1 自循环引用

Block内调用对象,对象拥有Block,导致产生的双向强引用——循环引用。

对象自循环引用

阅读全文 »

在前几篇,针对Block截获变量的类型已经作了全部说明——包括基本类型和对象类型。

下面,我们介绍Block中常用的一个修饰符__block

本文源码—__block

一、_block的使用

在开发中,Block内部能直接修改全局变量或者static变量,而对auto变量,就不能。__block就用于在Block内部修改auto变量的值。

1
2
3
4
5
6
7
8
9
10
__block int age = 20;
__block BFPerson *person = [[BFPerson alloc] init];

void(^block)(void) = ^ {
age = 30;
person = [[BFPerson alloc] init];
NSLog(@"age is %d", age);
NSLog(@"person is %@", person);
};
block();

上面展示了,__block是如何修改auto变量的。

阅读全文 »

我们在针对Block的剖析在进一步加深,了解了Block如何截获基本类型,了解Block的类型和copy操作,下面我们开始进入Block的内存管理世界

Block的内存管理,主要针对捕获外部对象类型的auto变量。

1
2
3
4
5
6
BFPerson *person = [[BFPerson alloc] init];
person.age = 28;
void (^block)(void) = ^{
NSLog(@"age %d", person.age);
};
block();

根据Block捕获auto基本变型的规律,针对对象,仍然适用

  • auto变量捕获后,Block中变量的类型和变量原类型一致;

  • static变量捕获后,Block对应的变量是对应变量的指针类型;

那么,auto对象与基本类型在Block内部有什么区别呢。

我们将从两方面讨论:

  1. Block是如何捕获对象类型的?
  2. Block内部是如何管理对象类型的?
阅读全文 »

上篇文章讲述了Block对象如何捕获不同类型的变量,现在开始要追踪Block本身类型的变化,而且Block对象类型和捕获是有关联的。

一、类型

1.1 类型归纳

block类型

阅读全文 »

一、本质

如果用一句话概括,Block是一个将函数及其执行上下文封装起来的对象

1.1 clang说Block是个对象

  • 是对象:其内部第一个成员为isa指针;
  • 封装了函数调用:Block内代码块,封装了函数调用,调用Block,就是调用该封装的函数;
  • 执行上下文:Block还有一个描述Desc,该描述对象包含了Block的信息以及捕获变量的内存相关函数,及Block所在的环境上下文;

基于此,绘制了下图:

block本质

阅读全文 »

一、Block入门

Block是封装工作单元的对象,即可在任何时间执行的代码段。它们在本质上是可移植的匿名函数,可作为方法和函数的参数传入,或可从方法和函数中返回。Block本身具有一个已类型化的参数列表,且可能具有推断或声明的返回类型。您还可以将块赋值给变量,然后像调用函数一样调用它。

​ 插入符号 (^) 是用作块的语法标记。块的参数、返回值和正文(即执行的代码)存在其他类似的语法约定。

​ Block共享局部作用域的数据。Block的这项特征非常有用,因为如果您实现一个方法,并且该方法定义一个块,则该块可以访问该方法的局部变量和参数(包括堆栈变量),以及函数和全局变量(包括实例变量)。这种访问是只读的,但如果使用 __block 修饰符声明变量,则可在Block内更改其值。即使包含有块的方法或函数已返回,并且其局部作用范围已销毁,但是只要存在对该块的引用,局部变量仍作为块对象的一部分继续存在。

​ 作为方法或函数参数时,Block可用作回调。被调用时,方法或函数执行部分工作,并在适当时刻,通过Block回调正在调用的代码,以从中请求附加信息,或获取程序特定行为。Block使调用方在调用时能够提供回调代码。Block从相同的词法作用范围内采集数据(就像宿主方法或函数所做的那样),而非将所需数据打包在“关联”结构中。由于Block代码无需在单独的方法或函数中实现,您的实施代码会更简单且更容易理解。

阅读全文 »

本文是Objective-C系列的第12篇,主要讲述了关联对象的底层结构和使用。

一、为什么需要关联对象?

1. Category能添加成员变量吗?

我们在Objective-C(十)Category中讲过,Category能添加协议、方法、属性等,参考下面的结构体。

1
2
3
4
5
6
7
8
9
10
//from objc-runtime-new.h
struct category_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
....
};

既然可以添加属性,那是不是可以添加成员变量呢?

答案是:不可以

阅读全文 »

本文是Objective-C系列的第11篇,主要讲述了及loadinitialize两个特殊方法的相关特性及其底层的实现。

一、常用知识点

在讲述之前,我们先把该两个方法常用到的一些知识点先列出。

image-20181211200612904

阅读全文 »

本文是Objective-C系列的第10篇,主要讲述了category的实现原理和相关特性。

一、概述

1.1 category简介

category是Objective-C 2.0之后添加的语言特性,分类、类别其实都是指的category。category的主要作用是为已经存在的类添加方法。

可以把类的实现分开在几个不同的文件里面。这样做有几个显而易见的好处。

  • 把不同的功能组织到不同的category里,减少单个文件的体积,且易于维护;
  • 可以由多个开发者共同完成一个类;
  • 可以按需加载想要的category;
  • 声明私有方法;

不过除了apple推荐的使用场景,还衍生出了category的其他几个使用场景:

  1. 模拟多继承(另外可以模拟多继承的还有protocol)
  2. 把framework的私有方法公开
阅读全文 »

本文是Objective-C系列的第9篇,主要讲述了KVO的底层实现,以及KVC的使用及KVC中调用流程。

一、概述

KVO全称Key Value Observing,是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。由于KVO的实现机制,只针对属性才会发生作用,一般继承自NSObject的对象都默认支持KVO

KVONSNotificationCenter都是iOS中观察者模式的一种实现。区别在于,相对于被观察者和观察者之间的关系,KVO是一对一的,而不是一对多的。KVO对被监听对象无侵入性,不需要修改其内部代码即可实现监听。

KVO可以监听单个属性的变化,也可以监听集合对象的变化。通过KVCmutableArrayValueForKey:等方法获得代理对象,当代理对象的内部对象发生改变时,会回调KVO监听的方法。集合对象包含NSArrayNSSet

阅读全文 »

本文是Objective-C系列的第8篇,主要讲述OC对象的底层结构,以及分类:实例对象、类对象、元类对象。

在上一篇Objective-C(七)对象内存分析分析后,我们得知了一个类在内存中的存储。

但是,我们只分析了类的成员变量和属性,我们知道,一个OC对象,还包括方法、协议等极其重要的信息,那么它们在哪里,又是如何存储,如何用的呢?

本篇在此进一步分析Objective-C类体系的分类及其在内存中的完整分布。

为此,我们先要进行一些准备工作。

阅读全文 »