Tag:

ARC Swift教程

ARC的功能 每次通过init()创建新的类实例时, ARC每次都会分配一块内存来存储信息。 有关实例类型及其值的信息存储在内存中。 当不再需要类实例时,它将通过deinit()自动释放内存空间,以用于进一步的类实例存储和检索。 ARC跟踪当前引用的类实例的属性,常量和变量,以便将deinit()仅应用于那些未使用的实例。 ARC维护对这些类实例属性,常量和变量的“强大引用”,以在当前使用类实例时限制释放。 有关ARC工作原理的更多信息,请访问Apple开发人员文档 1内存管理 内存管理在您要编写的任何应用程序中都至关重要。 这是由于移动设备中的硬件限制。 1.1 MRR 过去, 可可开发人员负责整个MRR (手动保留版本)中的内存管理资源。 Vehicle * cloudCar = [[Vehicle Alloc ] int]; // .. NSString *模型= cloudCar.model; // .. [cloudCar 发布 ] alloc方法用于创建对象并声明所有权开销,而release用于释放所有所有权对象。 1.2自动参考计数(ARC) 2011年,Apple转向自动参考计数。 在大多数情况下,快速进行内存管理是可行的,并且我们对内存管理没有做任何事情。 当不再需要类实例时,ARC会自动冻结内存使用。 每次一个类都是实例时,ARC会为该实例分配一个内存。 这部分内存包含与实例类型相关的信息。 var cloudCar = Vehicle() 然后,如果不再需要该实例,则可以释放分配给其他对象的空间。 var cloudCar:车辆? cloudCar =车辆() cloudCar =零 当然,如果从内存中释放了cloudCar ,但您仍然使用它,则应用程序将崩溃。 💣🤗 […]

开始进行Swift编程,第7部分-初始化和反初始化,覆盖和引用计数

在上一篇文章中,我们讨论了结构,类,属性和方法。 开始进行Swift编程第6部分-结构,类,属性和方法 在上一篇文章中,我们介绍了函数,枚举和范围。 medium.com 它帮助我们弄清楚如何创建对象以及将类似的属性和方法组合在一起。 本系列的内容不会教您Apple提供的更具体的类,例如UIButton或更实际的URLSession。 它会教给您足够的知识,因此当您在自己的程序中看到这些类时,您将对如何开始使用它们有所了解。 因此,让我们深入研究这一课。 从最基本的意义上讲,类和结构的初始化是为类和结构提供值。 有时,我们希望类或结构在创建时具有默认值,而其他时候,我们想告诉类或结构其默认值是什么。 初始化Class和初始化Struct之间的区别是:Swift中的Struct有自己的默认初始化器 ,而Classes没有。 这是什么意思? 这意味着当我们创建结构时,我们不需要在Struct中包含init()方法,它会自动为您创建。 仅当创建类时未实例化该类的属性时,类才必须具有init()方法。 让我们看看我在说什么。 在myFullyInitializedClass我们可以使用 var myFirstClass = myFullyInitializedClass() 。 如果要使用myFirstClass.myFunction()调用函数,则它将返回整数1因为我们为该类设置了初始值。 在myNonInitializedClass ,我们需要传入给定的givenNumber来创建它,以便初始化该类的所有属性。 在这种情况下,我们只有一个属性,但是如果有更多属性,则必须传递所有默认值。 只需将init()方法想像为目前没有func关键字的函数即可。 其唯一目的是为类中的属性分配值。 当我们调用方法myFunction ,它将返回值2 。 在myStruct示例中,我们没有初始化程序,因为在后台为我们创建了默认初始化程序。 创建新结构时,我们使用var myThirdStruct = myStruct(firstNumber: 3) 。 不,我们没有创建3个结构,但我以这种方式命名,因此您可以看到类和结构的总体顺序。 我们可以调用myThirdStruct.myFunction ,该方法将返回3 。 如果我们要创建一个myStruct的新实例,而不传递第一个数字的默认值,则会收到错误消息。 因此,对于结构,您必须设置默认值或在调用它时传递一个默认值。 可以在类和结构中使用Optionals以满足初始化程序的要求。 假设您创建的类并不总是需要其所有属性。 我们可以将不需要的属性设置为立即可用。 通过使用可选值,我们不必包括初始化程序,但是,如进一步所示,我们需要强制展开可选值,以删除设置了我们值的Optional()包装器。 我知道我告诉过您不要使用! ,强制解包,操作员。 但是如果没有更多工具可供使用,那么现在就必须这样做。 不用担心那些新工具即将推出。 如果您确实解开了nil可选项,则程序将崩溃,并且Found nil while […]

Swift中的强引用,弱引用和无主引用

Swift依靠自动引用计数(ARC)通过在对象的强引用为零时释放对象的内存来管理对象的生命周期。 但是,当两个对象彼此保持强引用时,可能会发生强引用循环。 强烈 参考 强大的参考保护 ARC释放对象后,其保留计数增加1。 默认情况下,对类实例的引用是强的。 基本上,只要任何东西都强烈引用对象,就不会释放该对象。 如下面的示例所示,当流程是从父级到子级时,可以使用强引用。 当我们将对象设置为nil时,会同时调用instrument和player deinit方法。 强参考循环–内存泄漏 现在,我们将一个玩家数组添加到Instrument实例(第3行),并在初始化一个Player实例(第5行)时,将其添加到该乐器的玩家数组(第22行)。 当我们将实例设置为nil时,不会调用instrument和player的deinit方法。 当我们将乐器实例设置为nil时,ARC会检查是否有一个实例保留对其的强引用,并且由于存在一个播放器实例对其具有强引用,因此不会释放该对象( 强引用周期 ),这导致我们陷入所谓的内存泄漏 。 弱引用 弱引用不能防止对象被ARC释放(它不会将其保留计数增加1),并且始终是可选的 。 弱引用只是指向对象的指针,该指针不能保护对象免遭ARC释放。 当不再有对它的强引用时,该引用将被更改为nil。 我们可以使用弱引用以避免强引用周期和内存泄漏(第17行): 当Instrument设置为nil时,唯一引用该实例的实例是播放器实例,并且由于它是弱引用,因此ARC会释放Instrument实例。 多余的参考 无主引用类似于弱引用(ARC不会将其保留计数增加1),但是具有额外的好处,这是非可选的。 无主引用是非归零的。 这意味着当对象被释放时,它不会使指针归零。 正如我们在下面的示例中看到的那样,将弱引用(第17行)更改为无主​​引用,其结果与以前相同。 根据Apple的文档: 仅当确定引用始终引用尚未取消分配的实例时,才使用无主引用。 如果在释放该实例后尝试访问一个未拥有的引用的值,则会收到运行时错误。

自动引用计数 为了了解ARC,您需要了解一些基本知识。 首先,我想让您了解这些基础知识。 结构和枚举的实例按值传递 在这里,我们将string1存储在变量str1中 。 然后,我们将str1的值分配给str2在幕后,将str1的值复制并存储在str2中 。 这意味着将单独的值存储在str1和str2中 。 这些值相等,但是在内存中它们是不同的。 这就是通过价值传递的意义 。 将str1的值分配给str2时 ,它按值传递。 类的实例通过引用传递 当我们将person1分配给person2时 ,不会复制存储在person1中的值。 而是将存储在person1中的Person实例的引用分配给person2 。 这意味着person1和person2指向同一个Person实例。 内存中仅存在 Person 类的 一个实例 。 强引用(ARC计算引用 ) 当父对象引用子对象时,应使用强引用,而不是相反。 也就是说,子类不应强烈引用父类。 弱引用和无主引用(ARC不计算引用) 无主(值是强制性的):—将始终具有值,但不会由自己拥有 弱(值是可选的):-仅当其他人强烈引用该值时才具有值 只要有效的引用在其生命周期中的某个时刻变为零就使用弱引用。 相反,当您知道在初始化期间将其设置为零时,请使用无主引用。 弱引用不能永远是常量,因为它需要能够变异 弧 ARC的基本思想很简单。 它跟踪类实例,并确定何时可以安全地释放其监视的类实例。 它通过计算每个类实例的引用来实现。 在第一个图像中,我们创建了该人的两个实例,因此该处的引用计数为2。 在一秒钟后,我们将person1设为nil,因此引用计数递减并变为1,但是由于这个1 Person类仍然存在,即在内存中。 如果我们使person2也为零,则ARC将释放该人员实例占用的空间,因此该实例将不再可用。

ARC(iOS)

Swift使用自动引用计数 (ARC)来跟踪和管理应用程序的内存使用情况。 引用计数仅适用于类的实例。 结构和枚举是值类型,而不是引用类型,并且不通过引用存储和传递。 在本教程中,我将解释: ARC如何工作以及如何简化内存管理? 什么是强引用,弱引用和无所有权? 什么是强参考周期,它如何导致内存泄漏和问题? 如何避免闭包和委托中的强刷新周期? ARC如何工作? 每当创建类的实例时,ARC都会分配内存块来存储有关该实例的信息,并且当不需要类实例时,ARC会通过从内存中删除该实例来释放内存。 现在,ARC可以跟踪/计算引用该实例的变量,常量或属性的数量。 如果count为零,则ARC从内存中删除该实例。 如果实例的引用仍然存在,ARC会将其保留在内存中。 注意:我们不必显式删除实例或担心内存管理。 ARC为我们做到了。 强参考: 默认情况下,每个引用都是强引用,直到使用显式弱引用或无所有权引用为止。 引用被称为“强引用”,因为它在该实例上保持坚挺,并且只要该强引用仍然存在,就不允许对其进行重新分配。 为了理解弱点和无主点,我们需要了解一个常见的未知问题,即强参考周期。 现在给约翰分配一个公寓,让我们说右图所示的unit4A。 约翰也是unit4A的租户。 这将创建一个强大的参考周期,即使将john和unit4A设置为nil,人实例和单元实例的参考计数也将为1,并且ARC将无法执行任何操作,并且会发生内存泄漏。 将john设置为nil并将unit4A设置为nil后,将删除var链接,但由于发生了强烈的引用循环,因此仍然不会调用deinit。 现在,我们已经清楚地了解了这个问题(如果不能再阅读2-3次,然后在Playground中尝试一下,看看是否调用了deinit),那么我们现在就可以解决它。 因此,现在是讨论弱者和无主者的好时机: 使用类类型的属性时,Swift提供了两种解决强引用周期的方法:弱引用和无主引用。 弱引用和无主引用使引用周期中的一个实例可以引用另一个实例, 而无需对其进行严格控制。 然后,这些实例可以相互引用,而无需创建强大的引用周期。 当另一个实例的生存期较短时(即,另一个实例可以首先被释放时),请使用弱引用。 在上面的“ Apartment示例中,对于公寓来说,在其生命周期的某个时候不能有任何租户是合适的,因此在这种情况下,弱引用是打破引用周期的一种适当方法。 相反,当另一个实例具有相同的生存期或更长的生存期时,请使用无主引用。 因此,在上面的示例中,可以将Apartment的租户声明为弱者,因为租户的生存期比Apartment短,即Apartment可以拥有一个租户,并且该公寓的生活可能是空的。 在使用弱解决强引用循环的同时,确定哪个实例将是短命的(这也取决于设计和要求)。 如果您仍然有疑问,请再次阅读此行: “当另一个实例具有相同的生存期或更长的生存期时,将使用一个无主引用。” 封闭的强大参考周期: 如果将闭包分配给类实例的属性,并且闭包的主体捕获该实例,则也会发生强引用循环。 由于闭包的主体访问实例的属性(例如self.someProperty ,或者闭包在实例上调用方法self.someMethod()例如self.someMethod() ,可能会发生这种捕获。 在任何一种情况下,这些访问都会导致闭包“捕获” self ,从而创建一个强大的参考周期。 之所以会发生这种强烈的引用循环,是因为像类一样,闭包是引用类型。 将闭包分配给属性时,就是在分配对该闭包的引用 。 本质上,这是与上述相同的问题-两个强引用使彼此保持生命。 但是,这次不是两个类实例,而是一个彼此保持生命的类实例和一个闭包。 HTMLElement类定义了一个名为asHTML的惰性属性。 此属性引用将name和text组合为HTML字符串片段的闭包。 asHTML属性的类型为() -> […]

ARC如何快速工作

在开始示例之前,我想分享一些方法,通过在实例上调用它们,实例的保留计数增加或减少。 我将向您展示自动引用计数工作的示例。 这里的示例从Owner类开始。 其中具有存储的属性,即名称。 下一个代码段定义了Owner?类型的三个变量。 您已经创建了一个新的Owner实例,并将其分配给owner1变量: 现在,已将新所有者实例分配给owner1变量,现在从owner1到新Owner实例都有很强的引用。 因此实例引用计数将为1。 如果将同一Owner实例分配给另外两个变量,即owner2,owner3。 建立了对该所有者实例的两个更强引用: 现在,对该单个Owner实例有3个强引用。 如果要取消分配Owner实例,则需要删除对该实例的强引用。 注意:当实例引用计数达到零时,该实例将从内存中取消分配。

Swift中的强周期/保持周期

在进入“ 强/保留周期”问题之前,让我们非常简要地了解如何使用ARC管理对象内存。 ARC是XCode为我们提供的用于自动内存管理的编译时功能。 它代表自动参考计数。 简单来说,只有强引用计数变为“ 零 ”时,ARC才会释放对象 根据ARC内存管理,对象可以是带变量的strong, weak or unowned引用类型之一,将进一步讨论它们,目前,如果对象在let语句之前没有任何关键字,则默认情况下它将具有很强的参考意义。 let name = String() // name variable has a strong reference to instance of String 让我们用代码来理解, 上面的代码片段声明了一个名为Employee的类,其name, empid & title Empid name, empid & title为ivars。在第19行,我们创建了Employee类的实例jack ,并传递了所有employee的详细信息,因此jack变量具有对object的强引用。 根据ARC,具有至少一个强引用的内存管理对象将不会被释放/释放。 在第20行,我们取消了对对象jack的引用,该对象又释放或释放了它所引用的对象,这就是在释放对象之前如何调用Employee类的deinit()函数,正如我们看到的Employee: Jack removed.日志Employee: Jack removed. 我们先将参考添加到变量jack然后再将其取消。 “Where did the deinit log “ Employee: Jack removed ” go […]