内存管理

历史:

手动保留释放(MRR):过去,开发人员会通过声明对他们创建的对象的所有权来确定是否将对象保留在内存中,并在不再需要该对象时放弃该对象。 MRR有一个参考计数系统,其中每个对象都有一个计数器,并且当其计数器降至零时将不复存在。

目前 :Swift使用ARC (自动参考计数)来使开发人员免于手动计数。 开发人员将变量定义为弱或强。 弱变量不会添加到计数器中,而声明它的对象无法保留它,而强变量则相反。

内部工作原理:

每当您创建类的新实例时,ARC都会留出内存来存储有关该特定实例的信息。 每当您不再需要该实例时,ARC就会释放内存并确保它不会占用任何不必要的空间。 因此,每当您编写代码并将类实例分配给属性,常量或变量时,它们都会对实例进行强引用。 强引用,牢牢把握实例,只要强引用仍然存在,就不允许释放。

保持循环和/或循环依赖:

当我们遇到ARC发生故障并且发生内存泄漏的情况时,我们将以保留周期结束。 当两个对象相互之间具有强引用且无法释放并释放其内存时,就会发生这种情况。 这会影响我们作为开发人员,因为由于高内存消耗,不良性能和崩溃,保留周期可能很危险。

这是ARC正常工作的示例。 当我们在命令行应用程序中运行此代码时,我们可以看到引用计数降至零。 我们来看一下正在发生的事情,我们实例化了两个对象sejan和angela,每个对象的引用计数均为1。然后我们将两个对象都设置为nil,可以看到对象sejan和angela已从内存中释放。正在打印。

但是,当我们添加另一行代码以表明Angela最好的朋友是Sejan时,会发生什么? 现在我们有一个循环依赖的问题! 因为我们的两个对象紧密耦合,所以发生了循环依赖。 维基百科指出, 循环依赖性还可以通过阻止某些非常原始的自动垃圾收集器(使用引用计数的垃圾收集器)释放未使用的对象来导致内存泄漏。

因此,现在我们将对象sejan和angela设置为nil,这些变量所指向的两个对象的引用计数都减少了1。因此,重新封装两个对象最初的引用计数均为2,实例化并互相引用。 ,然后将对象设置为nil,从而将它们的计数减少1,但是即使没有剩余的对象引用它们,它们的引用计数仍为1。

现在,我们创建了一个保留周期,以防止对象被释放!!! 如果这种情况在您的程序中的其他对象上持续发生,或者如果我们的程序运行了很长时间,则会导致内存泄漏内存泄漏是由于不正确的内存分配导致的资源泄漏,因为不再释放不再需要的内存。 在OOP中,当对象存储在内存中但无法被正在运行的代码访问时,可能会发生内存泄漏。

解决方案1:弱变量。 强引用会增加对象的引用计数,弱引用不会。 弱变量指出,如果没有其他对该对象的引用,则不要因为该引用而将对象保留在周围。 将引用声明为弱引用意味着我们可以使该对象消失,但也意味着必须始终将弱引用声明为可选! 这是因为如果弱引用指向消失的东西,则弱引用将变为nil。 我们的循环依赖关系不再阻止对象被释放。

如果要声明一个对象的引用而不增加该对象的引用计数,但是又不希望该对象一旦分配就为nil ,则可以创建一个无主引用,而不是引用。