Tag: iOS应用开发

快速提示:文档

在编写漂亮的“自我文档”代码和添加自己的解释性注释之间,代码文档始终是拉锯战。 自我记录代码始终是目标,但有时简单的注释将有助于您节省时间和精神疲劳。 为了帮助您达到适当的平衡,我们收集了一些有用的文档提示,可在您的代码库中使用。 Xcode带有方便的功能,称为快速帮助。 这是在Option + Clicking代码库时看到的漂亮的文档弹出窗口。 该文档还显示在“实用工具”抽屉的“快速帮助”面板中。 快速帮助功能通过允许您记住实际操作的实际情况,可以真正地节省大量时间。 您还可以创建自己的快速帮助文档。 在类,结构,枚举,属性,方法等上方直接以/// …或/** … */形式的注释将呈现为快速帮助。 在此注释中,您可以使用类似于Markdown的语法来编写丰富的文档,其中包括基本的文本格式,示例代码,链接,甚至是图像和视频。 有关所有详细信息,请参见Apple的标记格式参考。 当光标位于函数上时,要记住的方便快捷方式是Command + Option + / 。 这将自动为您的函数生成一个可随时填写的模板,包括参数列表和返回类型。 专家提示:游乐场具有自己独特的文档功能,包括将特殊注释( /*: … */和//: … )呈现为精美的,类似于打印的格式的能力,非常适合为您的团队或团队构建培训材料甚至用作演示媒体。 有时候,您只需要一个简单的注释即可帮助您慢走记忆或指出代码中有些棘手的内容。 以下是一些有用的约定: // MARK:可用于概述代码。 这些与属性和方法声明一起显示在跳转栏中。 它们是Swift的#pragma mark -版本。 // TODO:在标记将来的工作位置时非常有用,尤其是在布置完成当前任务所需的子任务时。 这些特殊注释显示在Xcode的跳转栏中,因此我想通过将内容包装在星号上来使其脱颖而出(例如// TODO: *** … *** )。 评论应简短而切题。 如果需要提供更多信息,请将其放在下一行的另一条注释中。 您的代码库不应堆满未完成的TODO。 我们将在短期内讨论一种防止这种情况的方法。 // FIXME:与TODO类似,除了它通常表示损坏的东西,而不是不完整的东西。 这些应该遵循与TODO类似的约定,包括不要长期坚持。 // NOTE:当留下有关某项工作原理的信息或指出特殊注意事项时,遵循的有用约定。 // […]

像老板一样联网— RxSwift简介

在几乎每个应用程序中,您都将需要联网。 我们如此努力,以至于一段时间后它变成了第二自然。 RxSwift的伟大之处在于,它使联网变得轻而易举,尤其是从JSON解析模型时。 在此示例中,我们将假设您有一个使用connect()方法处理网络的View模型。 我将从Udemy课程提供指向我的一个Gist的链接,该链接将为我们提供一些可使用的JSON。 观测值和订阅 创建可观察对象时,您定义其行为。 事情是存在一个可以观察到的可观察的事物,而当您这样做时,我们的内存就会出现问题。 这就是为什么看起来很奇怪,我们在创建可观察对象时必须返回一次性对象。 这将使我们有机会取消正在做的事情,这在使用网络时特别方便。 单打 单打是更具体的可观察变量,它们返回一个值或一个错误,这在我们的JSON将返回或将出现错误的情况下是完美的。 它确实使用了方便的成功/错误枚举以及模式匹配。 func connect()-> Single { return Single .create(subscribe:{single in 让url =“ https://gist.githubusercontent.com/isaacmendez/9ef13dfe10f668c2cd433ec1d99f92bc/raw/cd6c72578caa1ba0c4376af40813f1a995ab580e/inspringQuotesDataModel.json” Observable.from([url]) .map { 让url = URL(string:$ 0)! 返回URLRequest(url:url) } .flatMap { URLSession.shared.rx.response(请求:请求) } .subscribe(onNext:{[弱自我]响应, 守卫让json =试试? JSONDecoder()。decode([[[String:String]]。self,from:data)else { 单(.error(URLError.couldNotPullData)) 返回 } 让newTitle = json [0] [“ quote”] ?? “你们都不要引号” 单(.success(newTitle)) } […]

在Swift中管理临时文件

引用计数非常适合将未使用的对象带出内存。 这同样适用于我们分配的临时文件。 假设您正在构建一个视频共享应用程序,这是每次用户决定从该应用程序上传一些内容时必须执行的操作: 拍摄电影并存储到临时文件中。 向用户展示过滤器/裁剪/任何编辑用户界面。 将最终视频渲染到另一个临时文件,现在可以安全地删除第一个文件。 将视频上传到云中,完成后删除第二个文件。 手动处理这些文件会增加额外的复杂性,并且可以很容易地进行监督,从而由于丢失数据而导致过多的存储使用。 当我的宠物项目突然接管了我所有的存储库时,我自己面对了这个问题😂 引用计数在这里很容易解决:我们可以创建包含常规URL TemporaryFileURL类,并在其deinit方法中执行清除。 现在,临时文件在从应用程序中取消引用时将自动删除。 请注意,我在这里使用了很少使用的带有赋值语法的捕获来传递contentURL进行延迟的文件清理:我们最好不要在释放过程中捕获self ,因此我们只复制基础文件URL并让self正确地释放。 现在,您可能希望统一处理文件的所有代码,无论它们是正常的还是临时的。 这就是ManagedURL协议的代表。 我们可以使URL struct和/或NSURL类符合协议,并在各处传递ManagedURL引用。 我还添加了一个no-op keepAlive函数,其唯一目的是允许通过用作完成处理程序的各种闭包轻松捕获对象。 这样我们可以在执行后台操作时保留文件,如下所示: 正如詹姆斯·理查德(James Richard)在Twitter上提醒的那样,这种技术称为“资源获取即初始化”或RAII,并且已经在C ++中使用很久了。 这个技巧对管理任何外部资源的生命周期都非常有用,但是由于析构函数在ARC,GC,延迟,try / finally和其他方法的现代世界中并不常见,因此常常被忽略。 感谢您的宝贵时间,并希望本文对您有所帮助。 如果您觉得本文有用,请不要忘记to。

使用iOS 12中的自定义Siri快捷方式构建交互式语音应用

Siri Shortcut是Apple在iOS 12中基于SiriKit框架引入的新API。 它为开发人员提供了为用户在应用程序中经常使用的活动提供自定义快捷方式的方法。 用户通过向Siri发出语音命令来调用快捷方式,可以通过记录与快捷方式关联的自定义短语来自定义实际短语。 自iOS 10中发布SiriKit以来,Apple一直在其提供的多个内置域(例如乘车共享,付款,消息传递等)中限制Siri的使用。开发人员无法选择提供自己的自定义意图。 但是,借助iOS 12中的Siri Shortcut,Apple终于为开发人员提供了框架,供他们构建自己的自定义意图,该意图可以使用至少可以用于Siri Shortcut的自定义参数和响应进行配置。 开发人员创建自定义意图的能力为开发人员打开了许多与Siri进行交互的方式,例如: 点东西(例如披萨,咖啡,早餐😋); 搜索可以连接到任何API的信息; 执行我们希望Siri执行的任何自定义操作; 还有很多! Apple鼓励开发人员仅为用户创建有意义的快捷方式,例如,为用户在使用应用程序时希望重复的活动提供快捷方式。 不建议为用户仅在应用程序中执行一次的活动创建快捷方式。 我真的鼓励大家观看下面的Apple WWDC 2018视频,以从Siri工程师那里了解有关Siri Shortcut的更多信息: Siri快捷方式简介– WWDC 2018 –视频– Apple Developer Siri快捷方式是iOS 12中的一项强大新功能,可让您的应用向Siri公开其功能。 这个… developer.apple.com 使用Siri快捷键构建语音– WWDC 2018 –视频– Apple Developer Siri快捷方式是帮助人们执行操作或从您的应用程序获取信息的好方法,但是快捷方式可以是… developer.apple.com 在本文中,我想提供一个简单的示例,说明如何使用Siri Shortcut使用The Movie DB API对即将上映的电影进行搜索,然后使用自定义Intent UI Extension显示结果。 为了使用Siri快捷方式构建演示应用程序,我们将介绍以下内容: 创建新项目并设置Podfile。 创建共享框架以在主应用程序和扩展之间共享。 构建影片列表视图控制器 创建Siri意向定义文件 创建意图扩展 创建意图UI扩展 从View […]

加快Xcode构建

随着项目的发展,构建时间可能会成为问题。 但是,您可以对Xcode进行一些调整,这些调整可以减少无需任何额外工作即可完成构建的时间。 增加线程数 : 默认情况下,Xcode通常使用与计算机CPU中相同数量的线程。 但是,通过将线程数增加到默认值以上,可以显着减少构建时间-在某些情况下可以减少30%。 这利用了某些处理器对多线程或仿真其他内核的能力。 请记住,您可能需要尝试确定代码库中并行生成的收益是否递减,然后相应地调整线程数。 启用新的构建系统: Apple的“新构建系统”完全用Swift编写,旨在提高整体性能和依赖性管理。 请注意,虽然新版本系统在Xcode 9+中可用,但是必须在Xcode的Project / Workplace Settings下启用它,因为“ Standard Build”将是默认选项。 或者,可以通过命令行启用“新构建系统”(详细信息在下面链接)。 您可以在此处找到更多详细信息和启用新构建系统的说明: Xcode用于快速Swift构建的新构建系统 调整iOS模拟器: ãApple iOS测试模拟器可让您跨不同的软件和硬件组合进行测试(但仅限于Mac)。 通过使用“物理尺寸”或“像素精确”窗口尺寸,您既可以减少测试的大小,又可以减少完成测试所需的时间。 最终,这些配置更改将使用更少的资源,并有助于在模拟任何人都看不到的像素完美的iPhone阅读器时防止测试变慢。 您可以在此处找到配置说明:调整Xcode iPhone模拟器的比例和大小 使用并行化的构建: 并行构建可以通过构建不同时依赖于彼此的应用程序组件来减少Xcode的构建总时间。 对于可以轻松并行运行的,具有许多较小依赖项的项目,可以节省大量时间。 收益显然取决于代码的编写方式,但是值得测试,因为默认情况下未启用并行化构建。 您可以通过编辑Xcode方案并在方案的构建操作中选中“并行构建”来启用并行构建。 您可以在此处找到有关利用并行化构建的更多详细信息:什么时候应该检查Xcode方案的“并行化构建”? 打开构建时间摘要: 构建时间摘要使您能够报告每个Xcode构建的构建时间。 换句话说,构建时间摘要可以帮助您识别影响构建时间的构建部分,并进一步优化构建顺序以获取整体收益。 构建时间摘要所提供的见解虽然本身并不能解决,但在尝试优化构建时间时,可以在确定工作的优先顺序时很有用。 更大的构建机器: ‍从技术上讲,这不是Xcode的调整,但是较大的构建计算机在尝试加快构建速度时确实产生了巨大的影响。 更高的计算能力仅意味着可以更快地完成流程和构建。 我们的测试表明,从双核Mac mini迁移到12核Mac Pro可以使速度提高3倍,而无需付出任何额外的努力。 当您准备升级或扩展Mac基础架构时,请随时通过MacStadium与我们联系。 ‍其他资源: 当然,这些只是可以用来加快Xcode构建时间的一些建议。 以下资源可以提供有关改善Xcode构建时间的其他信息和建议。 优化Swift代码的编译时间 从iOS Edit-Build-Test周期减少了50%的等待时间 加快Xcode中Swift编译和编译时间的8条技巧 如何使用Xcode 9和iOS 11构建更好的应用程序 ‍ […]

Swift 4.2的新增功能

Swift 4.2是4.1和4.0的主要更新。 该更新主要与改进,代码优化和运行时性能增强有关。 现在,您可以使用Xcode 10.0构建用Swift 4或Swift 3编写的目标。在本文中,我将讨论Swift 4.2中引入的新功能。 让我们一一解决。 取消ImplicitlyUnwrappedOptional (IUO)类型ImplicitlyUnwrappedOptional (IUO) -0054 该建议引入了从Swift中移除ImplicitlyUnwrappedOptional类型,并在声明IUO attribute其替换为IUO attribute 。 您仍将继续使用语法T! 。 但是,使用! 在属性或变量声明的类型末尾,不再表明该声明具有IUO类型。 相反,它表示两件事: 声明具有可选类型。 该声明具有指示其值可能被隐式强制的属性。 (没有人会写或观察该属性,但我们将其称为@_autounwrapped 。)此后,此声明称为IUO声明。 以下是一些示例: // f:()-> Int ?,具有IUO属性 func f()->整数! { 返回 3 } //成功; x1:整数? = 3 令 x1 = f() //成功; x2:整数? = .some(3) 让 x2:诠释? = f() //成功; x3:整数? […]

iOS面试问题(快速)-第2部分

1.在Swift中解释泛型? 利用GENICS,您可以编写可与任何类型一起使用的灵活,可重用的函数和类型 。 您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。 Swift的Array和Dictionary类型都是通用集合。 在下面的代码中,用于交换两个值的泛型函数用于字符串和整数。 这是可重用代码的示例。 func swapTwoValues (_ a:inout T,_ b:inout T){ 让临时A = a a = b b =临时A } var num1 = 4 var num2 = 5 var str1 =“ a” var str2 =“ b” swapTwoValues(&num1,&num2) swapTwoValues(&str1,&str2) print(“ num1:”,num1) //输出:5 print(“ num2:”,num2) //输出:4 print(“ str1:”,str1) //输出:b print(“ str2:”,str2) //输出:a 2. swift中的可选内容是什么?何时使用可选内容? […]

让我检查我的调度程序

为RxSwift编写测试可能很棘手。 RxSwift的一项核心功能是默认情况下所有操作都是异步发生的。 如果您正确连接了所有可观察对象和观察者,则您的应用程序将按预期运行。 不幸的是,异步代码很难进行单元测试,因为您必须处理近似和可能。 但是,如果我们正确地组织代码,则测试Rx代码将变得非常简单。 通常,RxSwift与MVVM结合使用,因此让我们编写一个ViewModel进行测试。 当我在iOS中指MVVM时,指的是一种体系结构,其中代码按数据传输类型(模型),视图(UIView和UIViewController子类)和ViewModels大致划分。 视图主要用于在屏幕上绘制,模型没有逻辑,并且可以从一个地方到另一个地方传送数据。 ViewModel用于获取模型并以使View简单的方式对其进行转换。 尽管我们的体系结构只有四个字母和三个组成部分,但这并不意味着我们仅限于三种对象。 这些类型中的每一种都可以由名称和责任不同的任何数量的类型支持。 但是,定义整个iOS应用程序应如何设计其体系结构超出了本博客文章的范围,因此让我们继续使用ViewModel。 假设我们有一个应用程序供用户发布他们喜欢的乐器的图片。 在这个应用程序中,我们希望用户能够互相关注。 当您关注用户时,将看到一个显示以下内容的视图: 您有多少个追随者 最后追踪的对象 因此,我们的应用程序需要一种创建关系的方法,在该关系中用户跟随另一个用户,然后我们收集该数据并将其显示在屏幕上。 让我们从考虑网络开始。 假设我们的后端为用户提供了一个不错的RESTful接口。 api / v1 / followers /将使用我们的一系列用户响应GET请求。 该端点还将允许客户端将用户放入用户并创建新的关注者。 对于我们的iOS客户端,我们可能需要使用URLSession发出网络请求。 不必担心URLSession如何工作的细节,我们如何制作一个协议来包装网络调用。 这样,我们可以为生产实现真正的网络类型,但在测试中将其保留。 美丽! 现在我们知道了网络层的外观,让我们考虑一下ViewModel。 我们需要一种跟踪用户的方法。 让我们从这里开始。 这是一个很好的开始! 现在,我们有了一个可以跟随其他用户的对象! 更好的是,由于我们指定了调度程序,因此可以通过将网络调用移至后台队列来防止UI挂起。 如果您不熟悉调度程序,则它们是决定可观察对象的工作将在哪里运行的类型。 尽管这是一个很好的第一步,但是当您仔细观察时,并没有真正好的方法来对该对象进行单元测试。 这是个“火上浇油”的电话,因此,作为消费者,没有办法知道跟踪是否成功。 最重要的是,因为我们在该对象内创建了操作队列,所以即使我们知道要查找的内容,也无法确定它何时真正发生。 让我们解决这个问题。 我们还有两个要求: 您有多少个追随者 最后追踪的对象 由于这些要求都使用来自同一端点的数据,因此我们应该能够将这些实现为对来自followers()方法的可观察输入的转换。 让我们将两个可观察对象连接在一起,以便在您请求关注者时,如果响应成功,则请求更新的关注者列表。 该对象感觉更适合测试,我们提供了输入(用户),并且我们应该能够观察到输出(新计数和最新关注者)。 为了隔离我们正在测试的内容,我们将注入一个模拟的FollowerNetworkLayer,它将返回任意的测试数据。 自创建了FollowerNetworkLayer协议以来,我们可以创建一个接受静态数据的结构并将其返回以进行测试。 我们不在乎测试我们的网络层,我们可以单独进行测试。 当前,我们仅在测试要求我们的ViewModel跟随用户时,它会正确返回预期数据。 它完全需要网络层的事实与我们的实际目的相切。 在这里,我们在Observable上使用.just(_ :)静态方法来创建我们的Observable。 […]

谷歌增加了一个新的队友

您好,对于所有出色的iOS工程师, 今天是学习令人兴奋的事情的好日子。 因此,如果几天前像我一样,您可能会被标题弄糊涂。 不用担心,我们将介绍Google的新功能。 该消息还将使您对Firebase感到不满。 你看到我在那里做什么吗? 好的,山姆,没有您的任何搞笑笑话,请您说明发生了什么! 谁是新队友? 好的,我不知道您是否听说过Google以Fabric的名义收购了一家公司的消息。 Twitter在2014年将Fabric引入了世界。您可以将Fabric视为Firebase的竞争对手。 如果您不知道Firebase是什么,请立即停止并在此处查看我的文章。 两者都有类似的工具,可帮助开发人员构建应用程序,而无需从头开始创建大量后端基础架构。 这些平台使开发人员可以专注于构建出色的应用程序,而不必担心如何创建身份验证,实时数据库或分析之类的流程。 布 即使Firebase和Fabric相似,Fabric也提供了一些我们可以讨论和探索的功能。 仅查看Fabrics工具(套件),我就感到非常兴奋,因为它们提供了有用的产品。 我认为有三种套件对任何应用都将非常有帮助。 我也相信这些工具也是Google可能正在研究的工具。 1.数字:使用电话号码(而不是电子邮件和密码)验证用户。 无需密码,因为用户将保持登录状态。 Fabric声称Digits的使用体验简单,安全且安全。 另外,他们指出,数字的转换率比要求的电子邮件高20%。 使用此工具,将无需登录电子邮件,但用户只需输入一次电话号码并提供验证码即可。 就我个人而言,我更希望通过电话号码将电子邮件发送给公司。 我将在未来几周内测试Digits,以查看是否可以在应用程序中使用它。 2.解答:提供有关受众如何使用您的应用程序的实时统计信息。 答案检查活动的用户数,会话长度,稳定性等级和保留率。 它类似于Google Analytics(分析),它从应用程序收集什么数据。 他们俩都会收集有关谁在使用该应用程序,获利和崩溃报告的数据。 答案是另一种工具,它不仅提供图表,还向您显示对您来说很重要的数字。 您会为您收集并编译所有数据,因此您不必弄清楚图表上显示了有关您的应用程序的信息。 我知道此工具将是Google尝试在其Firebase Analytics Platform中实现的工具。 为了节省时间,我遗漏了很多其他信息。 请在此处随意检查此工具的功能。 3. Crashlytics: iOS和Android排名第一的崩溃报告平台。 我只能说的是,我对Crashlytics提供的所有信息感到惊讶。 您检查是否由于应用程序,硬件或操作系统(iOS和Android)而导致崩溃。 知道崩溃信息很重要,因为如果您的应用出现问题,您可以准确找到问题发生的地方。 这样您就可以将所需的资源放在正确的位置以修复该错误。 我不能强调拥有像Crashlytics这样的工具有多么重要。 我并未涉及所有功能,但您可以在此处查看它们。 我的想法 现在,我们讨论了Fabric中三个工具的基础知识,让我们看看Google将使用这些产品。 Google为Firebase投入了大量时间和金钱。 Google已使其变得可访问,并开始扩展该平台。 尽管该平台正在增长,但仍有许多开发人员需要抓住。 另一方面,Fabric的产品已经起飞,并且已经被沃尔玛,Uber等大型企业使用。我明白了Google为什么要这些工具的原因,因为它将大大改善Firebase平台。 Google将找到一种将Crashlytics之类的工具整合到Firebase Analytics中的方法。 Firebase产品经理在这里讨论了一些工具的用途。 […]

iOS推送通知背景下载神秘化

在实施推送通知时,我发现许多有关后台下载如何工作的不完整和不准确的信息。 我必须通过实验弄清楚其中的一些内容,以防万一它可以帮助其他人,这就是我所学到的。 (请注意,我将不介绍设置Apple Push Notifications的详细信息-这是一个完全不同的主题)。 期望的行为 至少对于我的应用程序而言,期望的行为是到达推送通知以触发后台下载,以便在用户下次打开该应用程序时(通过点击通知或正常打开该应用程序),该数据已经在那里。 此外,如果用户点击通知本身,则该应用应打开并显示该通知引用的特定视图/数据。 为了更具体一点,在紧急电子邮件和任务管理应用程序中,有关新电子邮件的通知应触发该应用程序从服务器下载该消息的内容,然后点击通知应打开该应用程序并显示该特定线程。 一个明显的问题是为什么您不能仅随通知一起直接发送所需的内容。 问题在于,Apple将通知有效载荷限制为2 KB,不足以包含大多数电子邮件的内容和元数据。 配置项目以进行通知背景下载 首先,您需要为您的应用设置适当的功能。 我假设您已经在目标设置的“功能”部分中启用了“推送通知”。 对于后台获取,您还需要在“后台模式”下启用“后台获取”和“远程通知”。 所有重要内容可用标志 其次,不要忘记在服务器发出的实际通知中将content-available设置为1,以触发后台下载。 如果您未能在通知中包含此标志,则通知到达时,您的应用将不会收到任何协议方法调用。 了解相关的App Delegate协议方法 乍一看,这似乎很简单。 UIApplicationDelegateProtocol提供了application:didReceiveRemoteNotification:fetchCompletionHandler:方法,该方法在通知到达电话时被调用。 并发症有两个方面: 当用户点击通知以启动应用程序时,也会使用完全相同的参数调用完全相同的didReceiveRemoteNotification方法。 如果通知到达时(或用户点击通知时)应用尚未运行,则通知信息将作为启动选项传递给didFinishLaunchingWithOptions,然后调用didReceiveRemoteNotification *。 同样,没有区分通知到达与用户点击通知。 因此,您需要处理四种情况: 通知到达,应用程序在后台运行。 通知到达,应用未在后台运行。 用户点击通知,应用程序在后台运行。 用户点击通知,应用未在后台运行。 案例1和3仅在案例2和4在didFinishLaunchingWithOptions的启动选项中提供通知详细信息时才调用didReceiveRemoteNotification,然后调用didReceiveRemoteNotification。 更为复杂的是,如果用户通过将其从内存中刷出而手动杀死了您的应用程序,则不会发生情况2。 也就是说,您的应用程序永远不会在后台启动以获取数据,直到用户选择再次启动它。 从用户点击通知中区分通知到达 除了一个例外,您可以通过检查应用程序状态来区分通知到达和用户在didReceiveRemoteNotification(或didFinishLaunchingWithOptions)中点击通知的情况。 如果应用程序在后台运行(UIApplicationStateBackground),则应执行后台下载。 相反,如果应用程序是“非活动的”(UIApplicationStateInactive),则表示它是响应于用户点击通知而从后台移动到活动的。 如果该应用程序已经处于活动状态(UIApplicationStateActive),则通常不需要执行任何操作。 但是,有一个重要的例子。 如果应用程序已暂停(在快速应用程序切换模式下,双击主页按钮后),并且通知到达,则应用程序的状态将为UIApplicationStateInactive而不是UIApplicationStateBackground。 但是,这并不意味着用户点击了通知。 因此,您需要其他逻辑来检测这种情况。 您可以将applicationWillEnterForeground用作其他信息。 当应用程序从后台转换为非活动状态时,始终会调用该方法,因此您可以依靠它在用户点击通知且应用程序实际上正在启动时(而不是通知到达时)被调用,而用户尚未交互。 您可以保留一个标志来跟踪该应用程序是否真正启动。 这是AppDelegate中的基本代码: -(void)applicationWillResignActive:(UIApplication *)application { self.appIsStarting =否; } […]