在保存之前一切都很好。 但是,当我打印获取的结果时,事情发生了。 崩溃…。 这就是我所得到的。 没有控制台日志,没有警告,没有谋杀武器。 最初的线索是EXC_BAD_ACCESS和EXC_1386,表明它的存在,是的,ZOMBIE。 僵尸是保留计数为0的对象仍然继续存在。 要确认它在产品->编辑方案->诊断中启用了僵尸,请为Zombie对象启用复选标记。 再次运行该应用程序,我得到了日志。 由于字符串僵尸对象而导致崩溃的原因。 是时候找到僵尸了。 为了更深入地研究,我们需要侦探“ xcode工具”的帮助。 打开xcode->开发人员工具->工具-> 选择僵尸 在方案中选择所需的模拟器和应用,然后点击红色的录制按钮。 景气,我们弹出这个僵尸, 查看分配历史记录,我发现在获取之后,访问属性“ newName”会导致该属性的内存释放, 但为什么 ? 动机是什么? 过渡到ARC发行说明 描述如何将代码从手动保留/发行转换为使用ARC。 developer.apple.com ARC对方法命名施加了约束: 您不能给访问器一个以new开头的名称。 解决案例后,将核心数据实体的属性从“ newName”重命名为“ updatedName”,解决了崩溃问题。 希望这对您有帮助。 任何帮助都可以通过pratheesh_db@hotmail.com与我联系。
手机上的内存是共享资源。 管理不当的应用程序会耗尽内存,崩溃并遭受性能急剧下降的困扰。 当我们将内存的给定部分分配给一组对象,而在使用完它们后忘记释放它,则会发生内存泄漏。 这意味着系统永远无法回收内存并将其用于其他用途,这最终意味着我们将耗尽可用内存。 尝试查找内存泄漏时,一个好的第一步是运行该应用程序,并查看Xcode中的内存使用情况图。 如果在使用应用程序时内存使用量趋于增加,则可能是某些内存没有适当释放。 内存图 Xcode内存图调试器有助于查找和修复保留周期和泄漏的内存。 激活后,它将暂停应用程序执行,并显示当前堆中的对象以及它们之间的关系以及哪些引用使它们保持活动状态。 可以通过选择“内存图”来启动“内存图”调试器 调试菜单栏中的调试器按钮。 在下面的文章中了解有关内存图调试的信息。 iOS-使用Xcode内存图调试器识别内存泄漏 来自petethedeveloper.com medium.com的交叉发布 在Xcode 9中使用内存图调试器 我从未真正花费时间来正确学习如何使用乐器。 当然,我知道如何使用Time Profiler和… medium.com 可能会有所帮助 主线程检查器 选择您的应用方案->产品>方案>编辑方案 方案1:如果主线程检查器为“未检查 ”。 在多线程环境中使用Logger。 线程清理程序告诉我们,由于多个线程正在访问我们的日志并间接访问logEventSource,因此存在竞争状态。 这将导致我们发生意外的行为,这可能很难跟踪或复制。 现在我们如何避免这种情况? 同步功能代码。 互斥锁 信号 GCD 让我们使用苹果推荐的方法: 生成的崩溃报告通常显示每个堆栈跟踪帧的内存地址,而不是源代码位置。 这使得很难确定错误在代码中发生的位置。这些调试符号包含所需的信息,以从内存地址转换为关联的源文件和行号。 象征性 符号化是将返回地址转换回人类可读的方法/文件名和行号的过程。 符号化使您更容易识别错误的根源并及时解决错误。 编译源代码时,编译器会将人类可读的源代码转换为机器可读的代码,并创建一个已编译的二进制文件。 它还会生成调试符号和映射表。 如果您看到映射表,则每个调试符号都将映射到已编译二进制文件中的确切机器指令,并映射到生成它的源代码中的行号。 有两种类型的构建,一种是调试构建,另一种是发行版本。 因此,根据构建设置,默认情况下,调试构建将调试符号存储在二进制文件中,另一方面,发布构建将调试符号存储在dSYM文件中以减小二进制文件的大小。 在构建过程中,XCode将从主可执行文件( 二进制 )中剥离所有调试信息,并将其放入名为dSYM的特殊文件中。 这有助于使我们的可执行文件更小,更易于分发给用户。 可能会有所帮助 谢谢!!!
实现是直接的。 我有一个实体“ MyApp”,有一个属性“ newName”。 在viewWillAppear中,我只是创建实体,为属性分配值,进行保存,最后进行访存。 在保存之前一切都很好。 但是,当我打印获取的结果时,事情发生了。 崩溃…。 这就是我所得到的。 没有控制台日志,没有警告,没有谋杀武器。 最初的线索是EXC_BAD_ACCESS和EXC_1386,表明它的存在,是的,ZOMBIE。 僵尸是保留计数为0的对象仍然继续存在。 要确认它在产品->编辑方案->诊断中启用了僵尸,请为Zombie对象启用复选标记。 再次运行该应用程序,我得到了日志。 由于字符串僵尸对象而导致崩溃的原因。 是时候找到僵尸了。 为了更深入地研究,我们需要侦探“ xcode工具”的帮助。 打开xcode->开发人员工具->工具-> 选择僵尸 在方案中选择所需的模拟器和应用,然后点击红色的录制按钮。 景气,我们弹出这个僵尸, 查看分配历史记录,我发现在获取之后,访问属性“ newName”会导致该属性的内存释放, 但为什么 ? 动机是什么? 过渡到ARC发行说明 描述如何将代码从手动保留/发行转换为使用ARC。 developer.apple.com ARC对方法命名施加了约束: 您不能给访问器一个以new开头的名称。 解决案例后,将核心数据实体的属性从“ newName”重命名为“ updatedName”,解决了崩溃问题。 希望这对您有帮助。 任何帮助都可以通过pratheesh_db@hotmail.com与我联系。
表格视图是否以60 fps(每秒帧数)滚动? 还是看起来生涩而不光滑? 我的现在以60 fps的速度平稳运行。 它曾经不稳定,平均速度约为38 fps。 这就是我做的。 每行中具有复杂单元格的表可能难以平滑滚动。 您需要在滚动时配置和布局单元,这是有限的时间。 当需要看时,滚动会变得缓慢而生涩。 我的平均速度约为38 fps(尽管分布范围很广)。 显然很慢。 问题在于表单元格是一个自定义视图,其中包含其他自定义视图,并且这些视图的位置和大小受到各种限制。 看起来非常不错,这是一个很棒的UI。 但是,当我们的表视图控制器代表被要求提供行高时,很难很快地弄清这一点。 问题 在我们的应用程序中,表格单元格的大小可能会因数据而异,几乎相差2倍! 因此,我们在调用heightForRowAtIndexPath方法时配置并布局一次单元,然后在调用cellForRowAtIndexPath方法时再次进行所有操作。 我们本可以使用estimatedHeightForRowAtIndexPath方法。 但是对我们来说,如果不进行完整的布局很难估算。 另一位开发人员希望表格准确无误。 因此,他们只是设置单元格视图并在其上进行布局,然后询问该单元格视图的高度。 那行得通,而且是准确的。 但是非常慢。 为什么我要关心的是38 fps,而不是60? 应用程序的响应性在快速动作的工作方式(如滚动等快速动作)中非常明显。 如果滚动是平滑的,则用户可以快速流畅地查看应用程序。 而且以平均38 fps的速度不规律地滚动时,会显得生涩且不流畅。 60 fps的速度与屏幕更新的速度一样快,因此必须每16毫秒更新一次(实际上由于系统和图形开销而要少)。 我在委托中的heightForRowAtIndexPath和cellForRowAtIndexPath方法上设置了一个断点,并看到多次调用该断点。 这段代码每次都在重做单元格布局。 有趣的是,我看到在heightForRowAtIndexPath.之前叫做cellForRowAtIndexPath heightForRowAtIndexPath. 与我预期的相反,但这有所帮助。 第一次尝试 我试图简化该过程,并根据行的元素和潜在的配置来计算高度。 这演变成一系列让我不安的特殊情况。 这很复杂,无法支持。 这意味着更改单元格不仅仅是更改xib文件的问题,而是再次对布局计算重新进行反向工程以估计或计算高度。 我不喜欢为要维护代码的人添加地雷。 (可能是我!)这行不通。 真正的解决方案: 因此,我回到了“布局并询问高度”方法。 但是这一次,我将在单元格上进行布局时缓存高度。 我创建了一个像这样的类: @interface MyCachedRowHeight : NSObject @property […]
他们说:“写不止一个” 不久前,我开始使用自定义Instruments软件包。 去年Apple WWDC 410会议之后,我感到很兴奋,并认为构建某个东西会很棒。 在上一篇文章中,我描述了整体程序包体系结构,开发工作流程中的一些陷阱以及在AppSpector中我们如何构建自定义程序包来跟踪SDK中的流量压缩。 在410会议上,Apple工程师说:在另一张幻灯片上“制造多个仪器”。 所以我想-为什么不呢? Instruments的自定义软件包是实现高度特定的调试流程的理想工具。 每个人都知道一个bug可以忍受多久,因为您不知道发生了什么。 一旦找到“观点”来解决问题,您就快完成了。 解决方法始终是大约10%,而找到正确的视角就是剩下的时间。 在思考软件包的一些想法时,我遇到了CossackLabs [1]的一篇很棒的文章,内容涉及开放跟踪框架及其实现。 可视化应用程序内部连续过程的想法看起来很适合作为一种工具。 这样的过程的完美示例是在不同视图控制器的上下文中执行的任何操作,堆积在队列中的操作或客户端-后端消息交换。 如果我只知道实施将需要32个小时😉 封装架构 让我们从一个基本的方法开始:为了实现类似开放式跟踪的图形,我决定使用看起来最好的图形元素。 开放式跟踪框架处理范围的两个基本概念:正在发生事情的上下文; 范围-范围内的一些活动。 包实现中的作用域具有开始和停止事件,唯一名称以及结果:成功或失败。 与成熟的开放式跟踪框架所建议的相比,此方法大大简化了,但足以用于试验软件包中的图并很有用。 打包方案不是很复杂。 我将不深入介绍第一部分中描述的元素,而我只会讲一些关于图形的特定内容。 您可以在这里浏览: https://github.com/appspector/Tracer/blob/master/TracerPackage/TracerPackage.instrpkg 我在周末构建原始实现时遇到的第一个问题是,仅在发送stop事件后,图形通道才出现在UI中。 我想从开始事件开始显示它,并用不同的颜色突出显示当前正在运行的跨度。 多亏了参加410次会议的Apple工程师Kacper,我才发现仪器具有一种特殊的结构,称为“开放间隔模板”。 它是一种结构,用于定义开始和结束事件之间包可使用的字段。 图本身用“图”节点描述,其中包含诸如标题和对表的引用之类的字段,以从中获取数据; “ plot-template”结构描述了显示的图形通道。 下面的示例意味着我们将为每个唯一的作用域都有一个单独的通道,它将从作用域名称变量中获取其名称。 “ plot-template”下的最后两个标签描述了车道内的线,颜色将来自“ status-color”,标签来自“ span-name”。 另一个有趣的事情是,“ open-interval-template”只能操作出现在开始模式中的变量。 这完全有道理,因为当您显示开始但未结束的事件时,您的代码无法使用结束模式中的数据。 同样,在表的最后两列中,我们计算行和状态标签的颜色,为此,我们需要知道事件的状态-它是正在运行还是已经完成? 我看到解决此问题的唯一方法是仅检查结束模式中存在的变量。 这就是为什么您在开始和结束模式中看到“ span-name-started”和“ span-name-stopped”变量的原因。 第一个用于在行上绘制跨度名称,第二个用于区分正在运行的跨度和结束跨度。 这是关于自定义程序包的丑陋事情之一,感觉它应该有另一个更优雅的解决方案。 第一次尝试 我很高兴在真实代码上尝试使用示踪剂,因此我开始寻找一个很好的例子。 第一次尝试是AppSpector SDK和消息处理模块。 每条消息的传入和传出都需要经过两个步骤:序列化,打包,压缩和最终发送。 有时,由于诸如网络故障等各种原因,消息可能会在队列中等待。这看起来很合适,因此我插入了示踪剂调用并开始记录期望的图像,就像在开放的示踪手册中有很多重叠的通道一样。 […]