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 ,但您仍然使用它,则应用程序将崩溃。 💣🤗 […]

分析iOS应用中的内存使用情况

自2007年以来,iPhone的结构或配置都发生了翻天覆地的变化。 内存(RAM)在2018年从128 MB增长到4GB,而存储从4 GB增长到256 GB。 然而,无论我们使用哪种操作系统,在为任何智能手机应用程序开发时,内存仍然是一个值得关注的领域。 在开发适用于iOS应用程序的日志记录框架时,主要基于内存管理,我想到了多个问题: 我的框架使用了多少内存? 我是否在主存储器中保留了太多数据? 是否有内存泄漏? 客户端应用程序是否会由于RAM利用率高而因压力负载而崩溃? iOS中的垃圾收集如何工作? 是否有类似于Java中的GC的GC? 让我们讨论每个问题并解决它们。 我的框架使用了多少内存? 我是否在主存储器中保留了太多数据? 方法1 当我们调试任何iOS应用程序时,XCode会在调试会话中提供CPU,内存,磁盘和网络的使用指标。 要打开,请在左侧窗格中选择Debug Navigator(option)选项。 单击每个参数后,主屏幕将显示详细报告。 这是内存报告的样子: 尽管此报告看起来非常有趣且内容丰富,但它具有误导性并且缺乏详细的内存中断信息。 我们将在后面的部分中看到。 如果您注意到此屏幕右上方有一个小按钮,上面写着“仪器中的配置文件”。 点击那个。 它将打开“乐器”应用程序,该应用程序显示有关应用程序如何使用内存的更好,更详细的视图。 我们稍后会在博客中详细介绍Instruments应用。 方法2 我们也可以选择以Profile模式构建应用程序: 仪器应用会打开,询问我们配置iOS应用所需的方式。 根据需求,有许多选项可供选择。 对于内存使用情况,我们可以选择分配(详细显示内存使用情况)或泄漏(显示内存使用情况与泄漏) 在下一个屏幕上,单击“记录”按钮以开始分析和使用情况。 仪器 如维基百科所述: Instruments(以前的Xray)是应用程序性能分析器和可视化工具,集成在Xcode 3.0和更高版本的Xcode中。 我们可以使用上述两种方法之一查看Instruments中的内存使用情况。 屏幕将如下所示: 让我们尝试了解此屏幕的主要组成部分: 该图顶部显示实时内存使用情况。 默认情况下,显示“所有堆”和匿名VM的组合内存使用情况。 您可以通过单击旁边的+号来选择显示其他图形。 下表中有多列对我们来说非常重要。 类别定义了内存的使用位置 永久字节定义了应用当前在内存中保留的字节数。 这在定义我们当前使用的内存量方面很有用。 #Persistent传达了多个持久对象。 这些对象总共消耗了上一列中显示的字节。 #Transient传达了该应用先前保存但现在已释放的对象数。 它们不再被我们的应用程序引用。 在确定内存使用情况时,这可能并不重要,但可以概述应用程序过去如何使用内存。 总字节数是一个令人误解的数字,将持久性和暂时性字节合并在一起。 仅当您想知道自应用程序运行以来使用了多少内存时,这才有用。 […]

Swift中的内存问题

对于开发本机iOS应用程序的任何人来说,管理内存都是重要且必要的,如果您使用的是Apple的新编程语言Swift,则仍然如此。 我在最近的项目中遇到并解决了一些内存问题。 一点历史 内存是指在设备上存储信息所涉及的所有硬件。 您的iPhone有两种主要的数据存储方式:1.磁盘2.随机存取存储器(RAM)。 在iPhone上运行应用程序时,包含所有可执行指令的文件将被加载到RAM中。 同时,系统将占用一部分RAM,称为堆。 在该目录下,我们的类的所有实例都将在应用程序运行时运行。 当我们谈论内存管理时,我们指的是管理堆内存的过程。 这意味着管理堆上对象的生命周期,并确保在不再需要这些对象时将其释放,以便可以重用内存。 在Objective-C中,除了Int,CGRect等原语外,所有内容都是对象,因此将在堆上分配。 在Swift中,引用类型是在堆上分配的,而值类型不是。 管理堆内存非常重要,因为对象可能很大,而我们的应用程序只能从系统中获取这么多的内存。 内存不足会导致iOS应用运行缓慢,并最终导致应用崩溃。 尽管如今,由于我们的设备变得越来越强大,看到RAM过载变得越来越少了,但成为一个良好的内存公民总是很重要的。 Objective-C从未像Java这样的语言实现垃圾回收。 那时,我们需要进一步了解内存处理。 理解分配,复制,保留的含义以及如何平衡这些操作与相反的操作(如发布)至关重要。 基本规则是:无论何时创建对象,您都拥有它并负责释放它。 为什么泄漏可能很危险? 想象一下在init内创建通知时开始监听的对象。 它对此做出反应,将内容保存到数据库,播放视频或将事件发布到分析引擎。 由于需要平衡对象,因此我们在释放对象时在deinit内停止监听通知。 这不仅会增加应用程序的内存占用 ,而且还会带来不必要的副作用和崩溃。 如果这些物体泄漏会怎样? 它永远不会消亡,永远不会停止收听通知。 每次发布通知时,对象都会对此做出反应。 如果用户重复执行再次创建对象的操作,则将存在多个实例。 所有这些实例都响应通知并相互介入,在这种情况下, 崩溃将是最好的事情🙂 多个泄漏的对象对应用程序通知做出反应,更改了数据库,UI,破坏了应用程序的整个状态 在Swift中 ,当一个对象强烈引用另一个对象时,它会将其保存在内存中。 当我说对象时,基本上就是引用类型,类。 结构和枚举是值类型。 无法仅使用值类型创建保留周期。 在捕获和存储值类型(结构和枚举)时,没有诸如引用之类的东西。 尽管值可以保存对对象的引用,但值是复制而不是引用的。 当一个对象与第二个对象具有强关联时,它便拥有它。 第二个对象将保持活动状态,直到被释放。 这被称为S trong参考 。 只有将属性设置为nil时,第二个对象才会被销毁。 视图控制器泄漏 视图控制器或自定义视图在加载视图时可能立即开始泄漏。 之后,可能会发生一百万件事,但是通过此简单的测试,您可以确保viewDidLoad不会泄漏。 反初始化 一种方法是确保调用`deinit`。 当Deinit被调用时 指向对象的最后一个指针将被删除,并且内存 分配给它的将被清除。 使用打印或调试模式检查是否 从每个视图控制器中调用`deinit`; […]

Apple SpriteKit物理内存泄漏与解决方案

最近在创建游戏时,我注意到我正在缓慢地泄漏内存……每2分钟大约1到1.5MB。 开始我长时间的潜入我的代码以查找罪魁祸首。 我能够将它从概要分析和多个注释掉的代码部分中缩小到一行代码。 testSprite.physicsBody = SKPhysicsBody.init(rectangleOf:CGSize(宽度:200,高度:20)) 什么? 什至这是怎么可能的,我所做的只是为一个小方形精灵创建一个PhysicsBody。 我创建了一个新的空白项目,并使用了相同的封闭方法… 发生相同的内存泄漏。 如果我注释掉创建physicsBody的话,就不会发生内存泄漏。 这让我回想起我第一次遇到SpriteKit的内存泄漏的问题,该错误是“ view.showsPhysics = true”,但是这次我没有打开内存,所以我有些困惑。 我必须更深入地剖析配置文件,以便深入了解这一点。 运行分配工具,我可以标记时间范围或“ Generations”,以查看在一段时间内有多少内存泄漏。 请记住,在此之前我所做的所有事情都是在屏幕上轻按一次以创建单个testSprite,而在配置过程中的其余时间中从未触摸过屏幕。 内存泄漏无休止地增长-根本没有任何其他输入。 从我已经注意到的情况来看,取消此设置所需要做的就是创建任何类型的物理体。 通过下面的时间戳,您可以看到从C代到D代,我们在大约1分钟20秒左右的时间内增长了733KiB。 如果我们深入研究C一代的时间框架,我们可以看到导致错误的原因。 罪魁祸首是CAMetalDrawable和_NSArrayM(也是金属函数)。 潜水更深…… 深入研究CAMetalDrawable,我们看到它正在创建一堆这64字节的分配。 进入这些分配之一可以发现…… 有很多东西在此调用“保留/释放”,但是其中一个特别称为“保留”,但是从来没有附带的“释放”,您可以看到它是中间的,“ Jet”下的Response — jet_context_Metal:create_texture_from_Metal_D…等等。因此有了ARC从不释放这些分配,并且将这些分配保留在内存中。 解 好的-太好了,所以我发现了造成这种情况的原因,这并不是我在做的任何事情,但是由于没有在Metal中创建新的游戏引擎,因此我似乎无法解决该问题既不放弃SpriteKit,也不接受我的游戏内存泄漏很小的游戏。 但是a,我偶然发现了来自苹果公司的有趣的技术质量检查。 “如何为SpriteKit和SceneKit指定渲染器?”解决方案是将Metal完全放弃用于OpenGL。 尽管我确信Metal可以为大型3D游戏提供许多好处,但我的简单2D游戏确实不需要额外的推动力。 说了这么多,我要做的就是在info.plist文件中将布尔类型的“ PrefersOpenGL”添加为= YES 和BOOM! 稳定的内存使用。 至少要等到下一个。 我已将此问题提交给了bug跟踪程序供Apple审查,希望它很快就会修复。

iOS Swift项目的内存泄漏集成测试

ARC在iOS编程世界中有很大帮助,但是像Java中的GC一样,它不能解决保留周期的问题。 GC在运行时工作,可以检测到保留周期,而无需引用该过程的“根”对象,然后销毁它。 但是ARC正在编译时间,因此它不能这样做。 即使您的泄漏对象很小,并且不会占用太多内存,但是如果它们保留在内存中并可能对应用程序造成奇怪的行为,您仍然需要小心。 在本文中,我将解释一种简单的方法来为iOS swift项目中的内存泄漏添加集成测试。 我还将讲述我面临的问题 添加内存泄漏集成测试以及解决方法。 请在此处下载启动项目:https://github.com/bigbangvn/MemoryLeakIntegationCheck/blob/master/LeakIntegrationCheck_StartProject.zip 尝试运行该应用程序,然后运行测试“ LeakIntegrationCheckTests”。 它现在将失败,但是我们将要修复。 这个例子很简单。 我们只有一个登录屏幕和一个主屏幕。 我们想测试一下是否存在内存泄漏,在用户登录到主屏幕后,执行一些请求并注销。 首先,对于纯swift对象,没有任何麻烦,我们需要添加代码来跟踪实例数。 避免测试代码影响生产。 我们将使用一个标志。 转到项目->构建设置->活动编译条件,然后将ENABLE_LEAK_CHECK添加到要测试的目标,您可以仅使用“调试”目标。 转到类HomeManager,在该类的末尾,添加以下代码以跟踪实例数: #if ENABLE_LEAK_CHECKinit(){type(of:self).instanceCount + = 1print(“ \(String(describing:self))\(#function)”)}静态var instanceCount = 0deinit {type(of:self).instanceCount -= 1print(“ \(字符串(描述:自我))\(#功能)”)}#endif 然后对HomeViewController,MyService,MyEntity执行相同的操作。 ( 这种实例计数跟踪的方法目前是相当手动的。我们可以通过添加一个类来跟踪实例计数,甚至跟踪与对象实例相关联的调用堆栈,来进行一些改进 ) 现在转到您的测试“ LeakIntegrationCheckTests.swift”,并查看该函数: func testLeakAfterLogout(){ } 在第57行的XCTAssert中注释掉第24行的注释。再次运行测试,它将通过。 您可能会问:为什么只有将XCTAssert放在tearDown()中才能通过测试? 让我解释! 当我们调用“ AppDelegate.shared.switchToLoginScreen()”以注销时,我们更改了窗口rootViewController。 尽管Window不再保留对旧ViewController(HomeViewController)的引用,但UIKit仍需要安排一些与旧ViewController有关的任务。 而且这些任务只能在我们的测试方法:testLeakAfterLogout()完成并将控制返回到主运行循环之后才能继续。 这就是为什么我们需要将泄漏检查放在tearDown()函数中的原因。 另外,我们需要在testLeakAfterLogout()末尾调用delayAndFlushTasks()来强制主线程执行所有待处理的任务,因此,在我们的测试函数返回之后,主运行循环可以使用旧的RootViewController继续执行计划的任务,并停止保留它。 在HomeViewController的deinit()上放置一个断点,您将看到deinit()由应用程序主循环触发。 这意味着HomeViewController在更改Window RootViewController之后不会释放,它可能在应用程序主运行循环的下一次迭代中释放。 现在,让我们对测试做一件事。 […]

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的文档: 仅当确定引用始终引用尚未取消分配的实例时,才使用无主引用。 如果在释放该实例后尝试访问一个未拥有的引用的值,则会收到运行时错误。

iOS版参考资料

推荐人未完成的推荐作品。 Yasbemos que no esasíde sencillo,las referencias fuertes son necesarias pero hay que tener clarocuándohay que hacerlasdébiles,es Decir,identédóndehay riesgo de crear un ciclo deretenciónde memoria。 佩罗底漆 ¿Ques ARC? 自动引用计数,自动引用计数 ,大号rasgos,美国的mecanismo的备忘录。 公民身份证明书上的公民身份证明书,以书面形式证明。1.公民身份证明书上的公民身份以书面形式作证。1.西班牙裔美国人的信仰证明书上的自由魁北克省,利物浦或再利用。 ¿Quées unareferencia fuerte吗? 声明可变的实用程序,例如: var objeto = AlgunaClase() estamos creando或referencia fuerte desde el contexto实际( self )hacia objeto 。 ¿Quéesunareferenciadébil? 纪念性和无罪性的参考书目,无保留意见的无保留意见的海洋。 帕拉·德菲尼拉(Para definirla),《弱者》是无名的。 弱 weak乌拉圭objeto) […]

内存管理

历史: 手动保留释放(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 ,则可以创建一个无主引用,而不是弱引用。

追踪RxSwift内存泄漏

这是关于使用Xcode内存图调试器来跟踪和消除RxSwift中的内存泄漏的简短教程。 正如我在前一篇关于避免RxSwift中的内存泄漏的帖子(https://medium.com/@chuck.krutsinger/avoiding-rxswift-memory-leaks-87885bd0023d)中提到的那样,我介绍了一些无意中造成内存泄漏的方法。 在本文中,我将跟踪一些内存泄漏,以演示如何使用Xcode和RxSwift中可用的工具。 样例项目 您可以从MemoryLeaksExample下载示例项目。 该示例应用程序在MVVM架构中使用RxSwift / RxCocoa与ReSwift结合使用,以隔离有状态的副作用。 我不会在这里介绍这些架构模式,但会在以后的文章中介绍。 仅供参考-示例项目是使用Xcode 10.1,Swift 4.2,RxSwift 4.4.0,RxCocoa 4.4.0和ReSwift 4.0.1编写的。 该调试会话将重点放在MemoryLeakViewController和MemoryLeakViewModel上,它们的功能与PlayGamesViewController和PlayGamesViewModel相同,但是会发生内存泄漏。 我不建议将MemoryLeak *版本用作开发风格,因为这种风格可能会导致我们在本文中将要介绍的各种内存泄漏。 其他视图控制器和视图模型是更好地构建MVVM解决方案的更好示例。 在以后的文章中,我将讨论并演示以这种样式的MVVM创建内存泄漏有多么困难。 入门-泄漏 下载项目后,您必须将MemoryLeaksExample目标-> General-> Team设置更改为您的团队,关闭工作区,然后安装Cocoapods。 项目运行后,请在Xcode中观察调试区域,以查看RxSwift资源计数。 登录屏幕上的资源计数为205。 您可以使用除“假”之外的任何用户名和密码字符串登录,这将导致登录失败。 继续登录以进入主屏幕。 在调试区域中,您将看到资源数量减少了,并且登录屏幕已被释放。 主屏幕使用的RxSwift资源少于登录屏幕,因此减少的计数确认登录屏幕在分配时释放了其资源。 接下来,通过点击“ Memory Leak Example”,然后点击“ Home”后退按钮,演示内存泄漏。 这样做几次。 您会在调试区域中看到,没有来自MemoryLeakViewController的deinit消息,并且资源数量稳定增长。 不好。 我们将对其进行跟踪。 内存图调试器 在使用内存图调试器之前,我们应该启用malloc日志记录,以便可以跟踪泄漏。 编辑构建方案,转到“运行”选项卡,然后选择“诊断”选项并启用malloc日志记录。 在主屏幕上时,通过点击Xcode中的按钮来启动内存图调试器。 然后,您将看到存在MemoryLeakViewController和MemoryLeakViewModel的多个实例,每次打开该视图并返回到主屏幕时,每个实例一个。 以我为例,它已经执行了3次,这是三个实例。 您还会注意到,我们泄漏了GameCell实例,因为每个视图都打开了其中的10个,另外还有一个由表视图创建的实例。 展开MemoryLeakViewController,单击一个实例,然后查看该图。 视图控制器实例在最右边,您可以看到从RxTableViewDataSourceProxy到视图控制器实例的一系列引用。 单击最靠近视图控制器框的Swift闭合上下文框。 现在打开右侧的Xcode面板以查看回溯。 嗯,没有提及我们的视图控制器。 尝试左边的下一个。 这确实提到了我们的视图控制器。 如果将鼠标移至回溯中的该项目,则右侧会出现一个小箭头。 单击该箭头,您将进入创建该闭包的代码。 […]

[快速] ARC,保留周期,强参考周期

。로젝트의기능구현이테스트를다가앱이느려지는다마주했습니다。 확인해보니예상대로메모리가있었습니다 중간중간끝난후여서적적적중간중간중간중간중간중간중간중간중간중간지지지지지지지지지들었습니들었습니들었습니들었습니들었습니들었습니들었습니。 swift의Memory의리가어떻게지,保留Cycle이무엇인지그스팅하겠습니스팅하겠습니다。 • 内存管理 自动参考计数(ARC)的默认值。 카운팅을하며로아주다。클래스인스턴스가카운팅을하며해할때마할때마reference强大的参考力0됬을때메모에서리에서해되는되는방식입니다 로ARC의있습니다。 •保留周期 。리가해제되지않고지되어가되어기는다말합니다。 。가가가가가가가가가가가가다 ninit的deinit应用程序deinit的应用程序。 。이해를준비하였습니다。 爸爸妈妈配偶配偶ARC가0이되지메모리에서제가되지않았습니다。 帕帕(papa)妈妈(mama)인스턴스에(nil)상이상가불다(없습니다)。 。다돌아가서보겠습니다。 제가위에서“강한”이말한것이힌트입니다。 强大,虚弱,无主的3가지방법이있습니다。 그중strong이默认이기기“때문에”순환참조인다。 。지느껴이해결사약함을이됩니다。 we(弱)레퍼런스변화하시키지않습니다。 n이남아있다면메모리를제하며변수는자동으로nil이됩니다。 때문에弱반드시可选반드시이어야합니다。 owned리고(未拥有)는는변화시키지않지값이가이가정하기타입이아닙니다。 运行时异常崩溃崩溃。 。가가는는있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때있을때 下载클로저를알아보겠습니다。 。저는용할용할복복아닌아닌아닌아닌값을됩니。 。제가있습니다。 zy기서지연변수(lazy)용한가유는이이이로로있게있게위함입니위함입니위함입니위함입니다위함입니다 (la懒的용하사용하지않으면가에러다。) info프로내에서는저에내에서는내에서는내에서는내에서는내에서는내에서는내에서는self내에서는다。 a변수의변수의변수의n n카운트는카운트는카운트는카운트는카운트는카운트는카운트는카운트는。。。。。。 말씀드린弱,无主를사있습니다。 내에서참조를하여내에서내에서내에서내에서。。。。。다。 마지막으로 。로저를지역적으로클래스와강한참조가강한참조가강한참조가강한참조로레퍼런스타입을사용하지않아도됩니다。