Tag: iOS应用程序开发

如何提高iOS应用的性能

基础 在开始建议之前,最好先定义并阐明本文之外的基本概念,这是主要主题 。 您可能已经知道,主线程不应用于繁重的操作,而应主要用于: 接受用户输入/交互; 显示结果并更新UI。 当主线程必须处理太多操作时,最常见的后果是丢帧现象,这是很普遍的现象,当我们不能保证60 fps(或每16.67毫秒一次)时,就会发生这种情况。 如何调试和识别精确丢失的帧? 有时,很容易发现它们,因为最关键的问题是不响应 ,而其他时候则不是,我们需要更准确的信息来跟踪它们。 例如,使用CADisplayLink (以非常快速的方式直接通过代码跟踪它们)或使用TimeProfiler以更准确的方式进行跟踪 。 要使用CADisplayLink,您可以简单地使用此类: 现在您知道您的帧下降了,该怎么办? 您可以采取一些措施,在本文中,我建议一些措施: 减少视图和透明视图的数量 最小化在连续调用的函数中完成的工作量 解码JPEG图像 屏幕外渲染 让我们一一讨论。 1.减少视图和透明视图的数量 为了提高应用程序的性能,要做的第一件事是(尽可能): 减少视图数量; 避免透明。 解决第二点很简单: label.layer.opacity = 1.0 label.backgroundColor = .white 为了轻松发现透明胶片的这种重叠,我们可以依靠一个非常方便的工具:调试->视图调试->渲染-> 颜色混合层 。 该工具使我们可以轻松地发现视图重叠,如以下示例所示: 2.最小化连续调用函数中完成的工作量 似乎很明显,但是像cellForItemAt indexPath或scrollViewDidScroll之类的函数必须非常快,因为它们是连续调用的。 始终确保使用最轻巧的配置方法来拥有“最哑”的视图/单元。 (例如,不涉及布局约束,对象分配等) 3.解码JPEG图像 当我们处理掉帧问题时,“通常的嫌疑人”之一就是图像解码。 通常,此操作是在主线程下通过imageViews完成的。 但这有时会导致我们的应用程序持续减速,尤其是在图像很大时。 为了减轻该问题,一种解决方案是将解码工作移至后台队列 。 这样,操作将不会像UIImageView所采用的常规解码那样高效,但是mainThread将是免费的。 下面让我们看一下卢克·帕罕(Luke Parham)的“ Catstagram”项目中的一些摘录: 在后台解码图像 : 您可以添加一些进一步的缓存控制以提高效率。 […]

使用DJI SDK的DJI Drones的iOS应用

1.WAYPOINT MISSION:此任务附带一系列预定义的路标(位置)。 设置高度和航向角后,无人机会飞到每个航路点并执行所需的动作,例如捕获照片或录制视频。 2.热点任务:在此任务中,无人机以定义的半径和高度绕着给定位置(热点)盘旋。 可以为此任务定义速度,摄像头动作,旋转方向。 3.DOWNSHOTMISSION(下潜任务):这是无人机飞行到指定位置,到达所需高度并在该位置执行摄像机操作的任务。 4.全景任务:在此任务中,相机旋转并以开发人员可以定义的不同角度拍摄照片,然后可以手动拼接拍摄的照片以制作全景照片。 5.跟随我的任务:在跟随我的任务中,飞机将遵循不断发送给飞机的GPS坐标,并保持恒定的高度间隔。 如果超过6秒钟未收到新的GPS坐标,则飞机将悬停在原地。 任务控制负责执行任务。 任一个任务 可以通过专门的任务负责人来运行,或使用时间线来连续进行一系列任务和动作。 请参阅链接以获取有关任务控制的详细信息。 任务运营商: 它们提供API,例如运行,暂停,停止以控制任务,并且可以通过侦听器跟踪状态。 他们负责执行单项任务。 很少有运算符是waypointMissionOperator , hotpointMissionOperator , PanoramaMissionOperator , followMeMissionOperator 。 时间线是所有时间线元素( DJIMissionControlTimelineElement )的集合 可以是诸如航路点任务(DJIWaypointMissionOperator),热点任务(DJIHotpointMissionOperator)或一系列动作之类的任务 。 可以给每个元素一个动作,例如DJIGoToAction , DJIAircraftYawAction , DJIGimbalAttitudeAction,以及捕获照片或录制视频的动作等。 为什么要时间表? 当任务执行者执行单个任务时,可以使用时间表来加载多个任务。 DJIMissionTrigger可以与时间轴元素一起使用,以在满足任何特定条件时通知用户。 注意 : 📣任务控制时间表仅适用于DJI飞机,不适用于任何DJI手持设备。 如何执行? 首先,我们需要创建定义无人机行为的时间轴元素。 定义所有元素(动作)后,将使用scheduleElements将这些元素安排到任务控制中 然后startTimeline 。 可以添加侦听器以跟踪时间轴的进度。 注意 : 📣参考链接以下载有关创建时间轴的示例。 该示例显示将Downshot任务添加到时间轴。 有关时间轴的更多信息,请参阅文档 。 以下是一些常见的常见问题和解决方案: 这些是在开发过程中可能会遇到的常见问题。 产品断开连接是面临的一个常见问题,其发生的原因有很多,例如USB电缆损坏,电池电量不足,退出了模拟器。 […]

Swift中网络单元测试的完整指南

面对现实吧,编写测试在iOS开发中并不那么流行(至少与为后端编写测试相比)。 我曾经是一个单独的开发人员,但最初并未受过本地“测试驱动”开发人员的培训。 因此,我花了很多时间研究如何编写测试以及如何编写可测试的代码。 这就是为什么我要写这篇文章。 我想分享我在Swift中进行测试时发现的东西。 希望我的见解可以节省您在丛林中奔波的时间。 在本文中,我们将讨论测试101的开始: 依赖注入 。 想象一下,您正在编写测试。 如果您的测试目标(SUT,被测系统)以某种方式与现实世界相关,例如网络和CoreData,则编写测试代码会更加复杂。 基本上,我们不希望我们的测试代码依赖于现实世界中的事物。 SUT不应依赖于其他复杂系统,因此我们能够更快,时间不变和环境不变地对其进行测试。 此外,重要的是我们的测试代码不要“污染”生产环境。 “污染”是什么意思? 这意味着我们的测试代码将一些测试内容写入数据库,将一些测试数据提交至生产服务器,等等。这就是存在依赖项注入的原因。 让我们从一个例子开始。 给定一个应该在生产环境中通过Internet执行的类。 Internet部分称为该类的依赖项。 如上所述,当我们运行测试时,该类的Internet部分必须能够用模拟或伪造环境代替。 换句话说,该类的依赖关系必须是“可注入的”。 依赖注入使我们的系统更加灵活。 我们可以在生产代码中“注入”真实的网络环境。 同时,我们还可以“注入”模拟网络环境来运行测试代码,而无需访问互联网。 TL; DR 在本文中,我们将讨论: 如何使用依赖注入技术设计对象 如何在Swift中使用Protocol设计模拟对象 如何测试对象使用的数据以及如何测试对象的行为 依赖注入(DI) 开始吧! 现在,我们将实现一个名为HttpClient的类。 HttpClient应该满足以下要求: HttpClient应该使用与分配的URL相同的URL提交请求。 HttpClient应该提交请求。 因此,这是我们的HttpClient的第一个实现: 似乎HttpClient可以提交“ GET”请求,并通过闭包“ callback”传递返回的值。 HttpClient的用法 问题是:我们如何测试它? 我们如何确保代码满足上面列出的要求? 直观地,我们可以执行代码,为HttpClient分配一个URL,然后在控制台中观察结果。 但是,这样做意味着我们每次实现HttpClient时都必须连接到Internet。 如果测试URL在生产服务器上,那似乎更糟:您的测试运行在一定程度上确实影响了性能,并且您的测试数据已提交到真实世界。 如前所述,我们必须使HttpClient“可测试”。 让我们看一下URLSession。 URLSession是HttpClient的一种“环境”,它是Internet的网关。 还记得我们所说的“可测试”代码吗? 我们必须使Internet组件可更换。 因此,我们编辑HttpClient: 我们更换 与 然后我们添加一个新变量: […]

Swift的游乐场驱动开发

作为移动开发人员,我们的使命是为最终用户提供最佳的用户体验,通过专用的应用程序使他们的生活更有趣,更轻松。 任务之一是确保用户看到的用户界面外观良好且正确。 大多数时候,我们可以说应用程序是数据的美化手段。 我们通常从后端获取JSON数据,将其解析为模型,然后使用UIView (主要是UITableView或UICollectionView 。 对于iOS,我们需要根据设计不断调整用户界面,使其适合小型手持设备。 该过程涉及我们更改代码,编译,等待,检查,然后更改代码等等。…诸如Flawless App之类的工具有助于轻松比较iOS应用程序和Sketch设计的结果。 但是真正的麻烦在于编译部分,这花费了很多时间,而对于Swift来说更糟。 它使我们进行快速迭代的效率降低。 看起来编译器在假装编译时正在秘密开采比特币mining 如果您使用React,您将知道它只是状态UI = f(state). UI表示UI = f(state). 您将获得一些数据,并构建一个UI来表示它。 React具有热重载器和Storybook,这使得执行UI迭代非常快。 您进行了一些更改,然后立即看到结果。 您还将获得每种状态所有可能的UI的完整概述。 您知道在iOS中想要相同的东西! 除了在WWDC 2014中引入Swift之外,苹果还引入了Playground,据说这是“探索Swift编程语言的一种新颖的创新方式”。 一开始我并不十分相信,而且我看到很多抱怨Playground运行缓慢或反应迟钝的抱怨。 但是看到Kickstarter iOS应用程序使用Playground加快了样式和开发过程的速度后,我印象深刻。 因此,我开始在某些应用程序中成功使用它。 它不会像React Native或Injection App一样立即重新渲染,但希望多年来会更好。 或至少它取决于开发社区。 Playground的场景是我们一次只能设置一个屏幕或组件的样式。 这迫使我们仔细考虑依赖关系,因此我可以导入一个特定的屏幕并在Playground中对其进行迭代。 Xcode 9允许在Playground中导入自定义框架,只要该框架与Playground在同一工作空间中即可。 我们可以使用Carthage获取自定义框架并进行构建。 但是,如果我们使用CocoaPods,那么它也是可行的。 如果将Playground添加为嵌套项目,则Playground无法访问同一工作空间或父项目中的代码。 为此,您需要创建一个框架并添加要在Playground中使用的源文件。 我们称之为应用程序框架。 本文的演示是一个使用CocoaPods管理依赖项的iOS项目。 在撰写本文时,它是Xcode 9.3和Swift 4.1。 让我们逐步完成使Playground与使用CocoaPods的项目一起使用的步骤。 还有一些好的做法。 步骤1:添加广告连播 我主要使用CocoaPods管理依赖项。 在某些屏幕中,肯定会涉及到一些吊舱。 因此,要使我们的应用程序框架正常工作,它需要与一些吊舱链接。 创建一个新项目,我们称它为UsingPlayground 。 该应用程序显示某种纸屑颗粒🎊。 […]

您需要了解的有关iOS UITableView的所有信息

尽管已经写了有关如何正确使用UITableView ,但新开发人员甚至是经验丰富的开发人员仍然偶尔会遇到一些问题。 关于如何使与UITableView相关的代码更短,更好和更易读的内容,有很多有趣的文章以及方便的示例和最佳实践,但是以某种方式,我还没有看到所有建议的总览。 因此,我决定在这里列出至少在使用UITableView时要遵循的所有原则,但是如果您有任何添加或分享的方式,请在下面的评论部分与我联系🙂 0.分成几节 假设您有一些要使用UITableView实现的Profile屏幕: 第一个建议很简单:将表分成几个部分,以使用不同类型的单元格。 如果 indexPath.section == ProfileSectionIndex { //对个人资料进行处理 } 如果 indexPath.section == InfoSectionIndex { 整数索引= indexPath.row //用info [index]做点什么 } 如果 indexPath.section == FriendsSectionIndex { 整数索引= indexPath.row //与朋友做某事[index] } 比这更有意义,更容易使用: 如果 indexPath.row == 0 { //个人资料 } 如果 indexPath.row> 0 && indexPath.row <info.count + 1 { int index = indexPath.row-1 //我看到了很多次T_T […]

如何使用CocoaPods创建您的私人图书馆(Pod)

凉!! 现在尝试构建您的项目,并检查是否有任何与swift 3相关的问题,然后转到下一步。 检查Podspec文件 在将Podspec文件提交到我们的私有存储库之前,我们可以通过运行以下命令从项目目录进行测试: 将摘要更改为: 接下来,浏览至Github或Bitbucket并为我们的库创建一个私有存储库,然后跳过给定的URL。 初始项目设置的下一步是提交更改并将所有内容推送到您创建的GitHub或Bitbucket远程存储库。 以下步骤可以解决问题: 假设一切顺利,我们可以将更改最终提交到存储库,创建标记并将其推送到存储库。 如果一切顺利,您现在已经准备好一个由Git源代码控制的Snorlax库项目。 现在,您可以为该项目创建CocoaPod podspec,并继续开发支持CocoaPod的库项目。 设置规格仓库 即将进行的所有设置都将获得回报,因为您将拥有一个既定的,可重复的过程,可以为iOS应用开发设置内部库。 根据需要添加更多的私有共享库变得很简单。 登录到Github或Bitbucket并创建一个名为PrivateTrunk的新私有存储库来管理所有私有库。 接下来,使用新创建的URL运行以下命令: 部署库 最后一步是将Podspec推送到专用中继服务。 您可以通过从命令行执行以下命令来执行此操作: 使用图书馆 就是这样,现在您应该可以通过编辑podfile,在顶部添加私人仓库的源代码和标准cocoapods 源文件的方式来安装库。 正常添加库。 摘要 阅读完本教程后,希望您现在了解如何创建自己的私有库。 作为参考,您可以从此处下载完整的Xcode项目 。 与往常一样,给我评论,分享您对本教程的看法,不要忘记关注我以获取更多教程。

斯威夫特:没人犯的常见错误-分解

您好,我亲爱的开发人员, 本文是我最近谈论的主题的延续: 无人问津的常见错误– Swift Bools 您好,我亲爱的开发人员,有时您可以编写一个在语法级别上没有重复的代码… blog.idapgroup.com 最近,我偶然发现了〜sh…〜代码中的一块宝石。 让我向您介绍所有辉煌的代码。 您已经在许多不同的面孔上看到了它,但是它总是归结为以下内容: 现在还为时过早,即使您没有编写这样的代码,也要拭目以待。 您不应该考虑类型和方法,而只考虑代码的思想。 这个想法很简单。 您可以将相同的值设置为具有相同接口的不同对象的多个属性或方法。 首先,代码是计数器DRY,它只是不使用Bool作为Bool 。 这里也有很多重复项。 因此,更好的方法是重构如下代码: 对? 对? 错误! 对于相同的变量,我们已经对isUserInteractionEnabled进行了重复数据删除调用,但是仍然有2个调用isUserInteractionEnabled和2个调用isOn 。 在一个函数的范围内多次调用任何属性本身就是一个缺陷。 即使您的属性在访问期间以最小的开销存储,它也可能在多线程环境中发生变化,或者通过一些复杂的观察代码变得可观察,甚至通过一些困难的计算也可以观察到。 因此,最好的准则是通过正确地分解代码并缓存方法/属性结果,永远不要在函数中多次访问属性或调用方法: 这样做要好得多,但是可以想象,在某个时间点, isUserInteractionEnabled将重命名为userInteractionEnabled 。 搜索代码以查找用法将很麻烦。 让我们尝试避免多次调用isUserInteractionEnabled来实现更好的重复数据删除: 哇 该代码很短。 但这好吗? 在视觉层面上,没有重复。 但是,复制仍然存在。 这是逻辑上的重复,因为我们对每个方法都调用isOn (对于该特定情况为两次)。 所以,让我们缓存它,对吧? 那好多了。 现在,让我们听取我的建议,并考虑将来的用法。 我对YAGNI(您不需要它)原则没有任何意见,我只建议考虑分解,因为小的可链接函数是编写,更改和重用想法的更好方法。 假设我们必须添加另一个要禁用的视图。 假设我们不仅要启用或禁用按钮,还要将其背景色更改为相同的颜色。 假设我们希望能够在完全不同的不相关代码段中启用/禁用视图。 该解决方案的核心是简单且可重用: 让我们分析一下: 我们创建类型别名以使代码更具可读性,并避免编写困难的语法构造。 是的,我认为在代码的多个位置用大括号编写UIView很困难,因为这需要额外的击键,并且自动完成功能无法为您提供帮助; 我们创建视图数组的访问器,如果要更改要处理的视图,则只需在一个访问点中执行此操作,就可以避免重复。 我们创建了enable,可以在代码的不同位置使用它,而无需重写相同的方法或使用继承。 如果属性是一阶函数(它们位于编译器的内部,只需检查AST,但是Swift不会让我们那样使用它们),则可以进一步改进。 我们当然可以通过传递闭包来模拟这种行为: 那只是口味的问题,是一项特殊的任务。 我并不总是使用这种方法,但是我也不能总是避免使用它。 […]

斯威夫特(Swift):常见错误无人问津-常量

您好,我亲爱的开发人员, 今天,我要说的是那件事,这让我很困扰。 您知道,我是一家软件开发公司的CTO。 此外,我是许多其他软件开发公司和初创公司的朋友,我帮助他们建立了移动编码文化或只是采访了人们。 因此,我在审查他人的代码方面拥有丰富的经验。 我这样做是在面试,性能审查,代码审查中赚钱和/或赚钱。 你知道吗? 由于人们容易犯的简单错误,我感到很沮丧。 因此,在本系列文章中,我将向您展示改善代码并使代码更具扩展性和可读性的不同方法。 是的,我会不时抱怨和抱怨。 首先,我将给出一般建议: 干(不要重复自己); 了解您正在使用的乐器; 反思您的代码; 扩展您的视野以改善代码。 第二个建议实际上是第一个建议的专业化。 您会发现,如果您不知道所使用的语言或框架,您将复制该代码。 我可以承认,我每年至少要对代码进行4次反思,每发现一次,平均每分钟就会产生100 WTF。 然后,我将自己的命运视为无能的傻瓜。 然后,我寻求更好的解决方案,然后尝试避免此类错误。 通过扩大视野,我的意思是学习新的语言和范例。 最近,我开始学习FP,可以告诉您,我永远都不会像以前那样编码。 当我仍然在ObjC中编写Ruby时,也发生了同样的情况。 总体而言,您尝试的次数越多,您的代码就越好。 正如Paul Graham曾经说过的那样,您将永远无法用其他语言编写类似Lisp的代码,但是即使您知道Lisp,即使使用更有限的语言,您的代码也肯定会变得更好。 第一个建议是国王,因为重复会导致不良的可重用性和可扩展性,从而导致大量容易出错的代码,这会消耗程序员的时间,例如胖而毛茸茸的野生不死人类不育之猪,充满了愤怒。活的。 修改这样的代码真的很难。 让我们看一下下面的代码: 这里的代码非常简单,但是如果要为前缀函数将“ prefix”字符串更改为“ mama” ,而对于后缀函数则保持不变,则更改代码会很麻烦。 这里的解决方案非常简单。 切勿使用代码中硬编码的任何类型的常数(字符串,数字,对象或其他任何形式)。 将它们放在带有清晰名称的词法范围常量中。 可以使用以下建议将上面的代码重写如下: 与特定内容相关的任何更改都在一个地方完成,这是重复数据删除和DRY的最终目标。 就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。

Swift:没有人会打扰的常见错误-可选的强制解包,vars和强制转换

您好,我亲爱的开发人员, 苹果在Swift中引入了一个非常可怕的东西,它破坏了所有的安全性和完整性检查,并且消除了使用Optional作为安全类型的麻烦。 这件事是力量的阴暗面。 是操作员! 。 关于使用它,我有一些建议: 不要用作! ; 不要使用变量!.doSomething() ; 不要使用let变量:输入! 。 切勿使用强制操作员; 永远不要使用强制操作员; 你不是绝地,不要使用武力; 你也不是西斯,不要用武力; 不,就是不; 杀死所有使用它们的人,烧掉他们的房屋并吃掉它们的小猫; 更重要的是,您永远都不敢自己使用它们。 强制运算符的最大问题在于,Swift并不是鸭子类型的ObjC,如果它们具有相同的接口,则可以避免使用一个对象,而使用另一个对象。 它也不是安全的,就像ObjC一样。 您不能在Swift中将消息发送到nil,而在ObjC中将消息发送到nil则返回nil(即使在ObjC中返回结构的消息仍然不安全)。 这意味着,如果您使用强制,将永远无法确定自己的Swift代码。 您也将无法对此进行推理。 即使,如果您确定,使用force操作符的代码也将按预期运行,则有可能在前一天发生更改,因为您忘记并且无法提供适当类型或适当值的变量。 使用武力的主要原因是开发人员太懒了,无法编写适当的结构良好的可预测代码。 克服懒惰,不要使用强制运算符。 因此,请记住,每次在Swift中使用武力时,您都别无选择。 他必须至少杀死一只小狗和一只小猫。 所以,对动物好,不要用力。 最后,让我再次强调: 请勿使用强迫操作员 没有例外 就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。

iOS应用崩溃:应用崩溃的7个原因以及如何防止崩溃

您是否曾经在iPhone上遇到过应用程序崩溃的经历? 嗯,这对于iOS应用程序用户而言并不陌生,因为手机上使用的大多数应用程序会随着时间的流逝而崩溃。 这个问题很烦人,因为它可能会影响手机的平稳运行,有时还会导致数据丢失。 您还必须想知道造成这种情况的原因,并且必须在寻找解决方案。 您需要的东西很少。 在本文中,我们将探讨导致iPhone突然崩溃的烦恼的一些原因,并采取一些措施来解决此问题。 花一些时间来跟踪并查看解决这些问题的方法。 无崩溃分析 当应用程序崩溃时,将创建一个称为“崩溃报告”的报告。 这将有助于了解问题所在以及它的来源。 这将说明导致iOS应用程序停止运行而没有事先警告的情况。 大多数iOS应用程序开发人员在其iOS应用程序开发过程中均未实现此功能,并且当没有附加崩溃报告附加到iOS应用程序时意外关闭时,解决该问题的措施几乎是无能为力。 因此,对于iOS应用程序开发人员来说,在其开发过程中对应用程序执行崩溃分析以帮助其以最佳方式发挥作用是明智的。 有了此功能,可以合理地减少或阻止iPhone应用程序崩溃的其他原因。 没有功能的单元测试 这是大多数iPhone应用程序崩溃的另一个原因。 创建应用程序非常容易,但是iOS应用程序开发人员之间的竞争可能会阻止他们完全测试所创建的应用程序是否存在错误。 某些应用程序可能在某些情况下可以工作,但在其他方面却往往会失败,这是由于iOS开发人员在iOS应用程序开发期间未进行充分的测试而导致的。 由于计时错误而导致某些结果。 某些iOS应用程序一起使用时可能会发生冲突,从而导致一个或两个崩溃,但如果事先未进行测试,则可能无法检测到。 应连续进行应用程序测试,并应在每个时间间隔监视应用程序的性能,并且必须记录收到的反馈以提高性能,并应尽快解决所记录的问题。 无组织的代码 这对于iOS应用程序开发人员来说应该是显而易见的。 在分散的房间里找到别针有多容易? 这将是一个非常严肃的任务,以无组织的方式编写代码时同样适用于您的代码。 最小的错误将使您的应用程序崩溃。 当要编写的代码太多而所有代码都杂乱无章时,这将导致iPhone应用程序出现一个大问题。 解决此问题的最佳方法是创建用户所需的单一目的代码。 将代码定位在单独需要的地方。 实际上,您自己编写代码可能会加重问题并需要分派任务。 将您的工作集中在错误检测上,看看是否可以解决预先编写的代码中的错误。 没有内存管理 任何iOS应用程序中的内存管理都非常重要,实际上,如果没有合理地管理内存,您的手机可能会并且可能无法正常运行。 内存管理是影响iPhone应用程序的最大,最明显的问题之一,某些应用程序不断打开多个线程并消耗大量内存导致此问题。 阅读有关内存管理的更多信息 未在低互联网和IPV6上测试的应用程序 IPV6对于您的应用程序的平稳运行非常重要且必不可少。 使用您的应用程序测试过的大多数网络都可以正常运行,但是当遇到的问题超出实际经验时,它往往会崩溃。 在某些情况下,将在网络较差或相对未达到测量标准的区域中使用应用程序,在这种区域和情况下,应用程序将反复崩溃。 从3G切换到2G可能会导致数据包混乱或失去连接性,并且大多数情况下,这种后果可能很危险,尤其是在更新某些功能时。 解决此问题的一种显而易见的方法是,预先通知连接用户中断,并在可能的情况下为您提供在任何位置的网络中进行您可能感兴趣的其他操作的能力。 浏览器不兼容 当浏览器不兼容时,它也会主动导致此问题。 因此,有很多人开发用于个人或公众的iOS应用程序,但是如果不以最佳方式进行开发,它可能会崩溃,因为它可能比所需的功能更多或更少。 尽管可以通过在iOS开发过程中特别针对特定的应用程序或特定目的创建应用程序来解决此问题,但是优化应用程序以适合其他手机是另一个合理的选择。 软件生命周期 在更新操作系统(OS)且尚未更新iOS应用程序时,不可避免地会导致iOS应用程序崩溃。 例如,众所周知,Android应用程序会随着时间的推移反复崩溃,因为该操作系统在很大程度上不稳定。 具有更高功能和功能的新版本会定期发布,但是与它一起使用的应用程序几乎没有得到改进,这会使该应用程序无法充分发挥该设备的功能。 使用API​​,可以合理地减少问题。 尽管它也有其自身的问题,但与此同时,它对我们所有人来说都是令人满意的,并且可以轻松地使我们的应用程序与时俱进并保持最新。 iPhone应用程序已过期,但如果我们尽快更新iOS应用程序,则不会受到应用程序崩溃的影响。 结论 iPhone应用程序意外关闭的原因有很多,但是解决问题的最佳方法是及早发现问题并迅速找到解决方案。 持续崩溃的iOS应用程序将导致您丢失数据,并且从长远来看会让您感到厌烦。 […]