Tag: iOS应用程序开发

如何使用Swift在iOS应用中构建自定义相机?

如果您正在阅读本文,则可能正在构建下一个与Instagram或Snapchat竞争的大型社交媒体应用程序,或者是一个可以帮助人们每天拍照的简单应用程序。 我想谈的是建立像Snapchat一样出色的自定义相机。 我不会详细介绍录制视频或拍照的内容,本文重点介绍构建自定义相机的UI部分。 希望我能写一篇有关录制视频和拍照的文章。 让我们开始… 创建一个名为CameraViewController的新视图控制器,然后开始导入和实现。 导入UIKit 导入AVFoundationclass CameraViewController:UIViewController { 将您的拍照按钮和照片预览视图放到情节提要中的视图控制器上。 @IBOutlet弱var photoPreviewImageView:UIImageView! 创建一个从按钮到视图控制器的操作,并将其命名为didTapOnTakePhotoButton 。 @IBAction func didTapOnTakePhotoButton(_ sender:UIButton){} 使用AVFoundation库可以进行摄影机操作,我们需要为此定义一些变量。 var会话:AVCaptureSession? var stillImageOutput:AVCaptureStillImageOutput? var videoPreviewLayer:AVCaptureVideoPreviewLayer? 开始在viewDidLoad方法中配置相机 覆盖func viewDidLoad(){ super.viewDidLoad() 会话= AVCaptureSession() session!.sessionPreset = AVCaptureSessionPresetPhoto let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) var错误:NSError? var输入:AVCaptureDeviceInput! 做{ 输入=尝试AVCaptureDeviceInput(设备:backCamera) }将let error1捕获为NSError { 错误=错误1 输入=无 打印(错误!.localizedDescription) } 如果错误== nil && session!.canAddInput(input){ 会话!.addInput(输入) stillImageOutput […]

Swift中的单元测试

作者:Matt North —高级IOS工程师 let greeting = “Hello!” 在Grindr,测试是我们开发工作流程的关键部分。 像许多公司一样,我们正在将iOS代码库过渡到Swift。 这是从几个方面进行的调整,Swift中的单元测试提出了特殊的挑战。 但是我们坚信单元测试所带来的价值。 那么,我们如何在Grindr编写Swift测试? 最佳实务 面对现实吧,对任何人来说,开始单元测试都可能是一项艰巨的任务。 对于Swift开发人员而言,更糟糕的是,Apple几乎没有文档说明如何编写可测试的代码。 无论您是重构现有的代码库以使其可测试,还是要着眼于可测试性来开始一个新项目,编写可测试代码都需要一个好的计划。 我将介绍2种技术/原理,这些技术/原理将有助于使您的代码更具可测试性: 依赖注入/协议驱动开发 函数式编程技术 依赖注入 依赖注入不是一个新主意,但在iOS社区中并不普遍。 依赖注入是在创建类时提供类的依赖(通常在初始化器中)的一种做法。 这样做可以使您的类可重用和自定义。 除了可重用代码的许多优点外,在编写单元测试时,这一点尤其重要。 让我们看一个例子: 错误的方法 class UserRepository { static let shared = UserRepository() private let dbContext = NSManagedObjectContext() // returns an array of users func getUsers() -> [User] { let fetchRequest = NSFetchRequest(entityName: “User”) […]

如何使用MSL(金属着色语言)向UIImage添加效果。

如果要创建可以更快,更简洁地处理的图像效果,则使用着色器语言是更好的方法之一。 例如,此封面图像由GPU用几行着色器代码处理。 而且我已经使用着色器发布了2个应用程序(FastFilm / PXSL)。 我将向您展示如何用MSL编写。 Xcode 10.0(Swift 4.2) iOS 12.0 Metal&MetalKit在iOS 9和更高版本上可用。 但是,它们不适用于iPhone 5和5C。 ImageProcessor.Shared.Setup() let outImage = ImageProcessor.Shared.Run(inImage) 感谢您的阅读。 请尝试重写着色器程序。 下次,我将撰写有关如何使用MSL创建电影风格效果的文章。 顺便说一句,这是我的第一篇文章! 所以..最后, “ Hello Medium” 。

Swift和Firestore:查询具有今天日期的字段

我天真地尝试执行以下操作。 让ref = Firestore.firestore()。collection(“ posts”) 让今天= Date() 让queryRef = ref.whereField(“ created”,isEqualTo:今天) 不幸的是,它没有返回任何结果,我想它正在为我们的日期字段寻找完全匹配的结果。 注意:希望实际上是这样。我并没有过多地关注它是否应该返回非空结果。 😅 经过几次Google搜索,我想到了这个: 让日历= Calendar.current 让组件= calendar.dateComponents([。year,.month,.day],来自:Date()) 让开始= calendar.date(来自:组件)! let end = calendar.date(byAdding:.day,value:1,to:start)!let queryRef = ref .whereField(“ created”,isGreaterThan:start) .whereField(“ created”,isLessThan:end) 现在,我得到了预期的结果。 ☺️ 我们可以快速将其重构为CollectionReference上的方法…… 然后在呼叫站点: 让queryRef = queryRef.whereField(“ created”,isDateInToday:date)

将iOS项目从CocoaPods迁移到Carthage的五个步骤

注意:这篇文章最初是在XCBlog上发布的 ,请阅读原始文章以获得更好的图形。 苹果可能不喜欢iOS开发人员将第三方依赖项添加到iOS项目这一事实。 苹果的核心技术为健康的文档提供了足够的框架和工具,开发人员可以使用它们来构建和分发iOS应用。 这可能是Apple目前没有任何官方程序包管理器来管理iOS应用程序依赖性的原因。 但是,这不是现实,iOS开发人员希望共享和分发代码以实现可重用性,避免重复并节省时间。 长期以来,CocoaPods一直作为iOS应用程序的依赖项管理解决方案。 它是用Ruby编写的,iOS开发人员需要了解Ruby才能使用它。 只要一切正常,一切都会好的,但是如果CocoaPods或Xcode项目中CocoaPods所做的不可思议的设置出现问题,痛苦就会开始。 迦太基是另一个由Swift编写并由Github工程师维护的依赖项管理解决方案。 在上一篇博客文章中,我解释了CocoaPods和Carthage有什么区别以及如何选择合适的框架。 我强烈建议您在此处阅读该帖子,以了解基本区别。 在本文中,我们将假设您已决定去迦太基,我们将看到从CocoaPods迁移到迦太基有多么容易。 通过应用这五个步骤可以轻松实现。 相关性分析 迦太基干跑 CocoPods退役 清理Xcode项目 将框架链接到目标 我们将详细讨论每个阶段。 这里要注意的一件事,我们只是在谈论Swift框架和动态库,而不是在谈论旧的Objective-C或静态框架。 将iOS项目迁移到Carthage的第一步是依赖性分析。 如果您使用的是CocoaPods,则iOS项目的Podfile中必须挂有一系列依赖项。 在分析阶段,您应该做两件事。 在此阶段,请尝试摆脱不再使用的依赖项,或者尽可能替换为其他方法。 该示例为SwiftLint,请思考为什么我们需要将SwiftLint添加为对iOS应用程序的依赖。 它可以在Github预提交钩子上轻松运行,也可以从本地计算机或Continuous Integration服务器上的命令行脚本轻松运行。 同样,检查使用了多少其他依赖项,看看是否可以轻松地用本机Apple技术替换这些依赖项,例如可以将URLSession和Codable替换为Alamofire或SwiftyJSON。 更少的依赖关系减少麻烦。 几乎所有主要的第三方Swift框架都支持Carthage。 检查方法是访问框架的Github存储库页面并查看README文件。 应当有徽章说明迦太基的支持以及平台的支持,如下所示(虽然不是很大) 如果您在那里没有看到徽章,并且可以使用xcodebuild构建Swift框架,并且该框架具有受iOS平台支持的方案,那么也应该可以。 一次,您确认了这两件事,就可以继续进行下一步,即迦太基空运行。 在此阶段,您已经确认支持从CocoaPods迁移到Carthage所需的依赖项。 是时候准备Cartfile并在其中添加所有依赖项,并在Podfile或Podfile中提到正确的版本。lockOnce准备好Cartfile,而不是尝试在当前项目上运行Carthage更新。 $迦太基更新-平台iOS 执行此命令后,可能是时候喝咖啡了。 当您从喝咖啡休息时间回来并且一切都已成功构建后,便可以进行下一步了。 但是,您陷在错误中,现在是修复这些错误的好时机。 常见的错误是 Swift版本可能有所不同 该框架不支持iOS平台,或者在构建时并未考虑到迦太基。 或迦太基已指定的任何其他错误 一旦成功构建所有内容,您应该拥有带有Checkout和Build子目录的Carthage目录,该目录具有依赖项框架和预构建框架的所有源代码。 在这个阶段,您最好从您的iOS项目中放弃CocoaPods。 当您将CocoaPods集成到iOS项目中时,您可能已经观察到CocoaPods几乎侵入了您的Xcode项目。 CococPods不仅创建了Xcode Workspace,而且还深入渗透到构建设置和构建阶段。 从iOS项目中删除所有混乱的过程听起来像是y牛刮胡子,但事实并非如此。 无需手动删除CococPods文件,脚本和框架。 非常感谢CocoPods-Deintegrate插件,该插件几乎删除了CocoaPods在Xcode项目中放置的所有标记。 我们只需要下载插件并从iOS项目的根目录或您的Xcode项目或工作区所在的位置运行pod deintegrate脚本即可。 […]

使用闭包的更好的编程组件

TL; DR:使用闭包在代码中创建模块化且简洁的UI组件。 有无数种方法可以在您的应用程序中实现UI组件。 使用情节提要是一种流行的选择,但是有时您会希望以编程方式对其进行布局。 在本文中,我将向您展示以编程方式构建相同UI,一个简单的登录屏幕的迭代实现。 首先,我将向您展示最简单的方法,该方法写起来快,却难以维护。 其次,我将向您展示使用私有帮助器方法的更好方法。 第三,我将向您展示使用闭包实现UI的最佳方法。 如果您以前没有使用过闭包,那么在阅读本文之后,您将很快意识到它们的强大功能! 在深入探讨编程方法之前,我想简要介绍一下Storyboard。 它们在初学者的iOS教程中无处不在,因为它们易于可视化和理解。 它们也非常强大。 您可以拖放组件,实时自定义UI组件的几乎所有方面(例如,字体大小,背景颜色),并测试UI在各种设备尺寸和方向上的外观。 但是,有时也需要部分或全部以编程方式创建UI。 对我来说,它正在与其他iOS开发人员合作,他们更喜欢仅在代码中构建UI。 在共享的iOS代码库上工作时,情节提要文件肯定会很快变得令人头疼。 在编写程序性UILabel , UIButton和其他核心UI组件时,我当然想学习实现它们的最佳实践。 以下是实现简单登录屏幕的三个示例,这些示例说明了编写程序UI代码时的注意事项。 假设我们要创建此屏幕: 在这里,我们有一个标题标签,一个标题标签和两个按钮。 我们如何以编程方式做到这一点? 好吧,最简单的方法是将其全部写入viewDidLoad() : 实现#1:实例化viewDidLoad()中的每个UI组件 这确实是实现此目的的最简单方法,但这就是收益的终点。 如果我想要另一个按钮怎么办? 您必须命名它并编写很多重复的代码。 如果我需要重命名标签怎么办? 然后,您必须查找并替换该名称的所有实例。 我什至没有包括布局代码,您可以很快看到它变长的时间! 不仅如此,它还会污染viewDidLoad()函数,随着项目的发展,我们希望避免使用该函数。 也许我们可以使用私人助手功能? 实施#2:私人帮手功能 现在, viewDidLoad()看起来更干净了! 我们将标签和按钮实现重构为private (限制访问)和可重用的帮助器函数(例如, createLabel(text:textColor:font:)用于创建标题和标题标签)。 这样比较好,但是仍然存在一些缺点。 首先,如果我们希望UI组件具有很多自定义项,则init参数开始变得冗长且不可扩展。 在上面的代码段中, createButton(text:textColor:font:backgroundColor:)方法具有四个输入,其中之一具有可选的默认值。 随着我们的按钮变得越来越复杂,我们想权衡可重用的帮助器功能与versus肿的万能包(乍看之下很难理解)的好处。 尽管此函数遵循DRY原理,但我们牺牲了可读性(如果添加其他参数,则线性可能将其标记为太长)。 在第三个实现中,我们将使用不同的东西: 闭包 。 闭包是封装在许多情况下弹出的功能块。 实际上,您一直都在使用闭包-函数(全局和嵌套)是一种闭包! 这只是一个更抽象的术语。 例如,闭包表达式可以存储为变量并在读取时执行。 封盖很棒,值得一读(请参阅Apple的文档)。 您可以对它们做很多事情,并使代码保持模块化。 […]

Swift 5.0的新功能

了解Swift 5.0中可用的关键功能。Swift 5.0的主要目标是使语言达到ABI稳定性。 这将使稳定的Swift运行时能够由OS供应商部署,并且可以通过可执行文件和库进行链接。 Swift 5的新改进: 增强字符串文字定界符以支持原始文本(SE-0200) 将结果添加到标准库(SE-0235) 修复ExpressibleByStringInterpolation (SE-0228) 引入用户定义的动态“可调用”类型(SE-0216) 处理将来的枚举案件(SE-0192) 拼合由“ try?”产生的嵌套可选内容 (SE-0230) 将isMultiple添加到BinaryInteger (SE-0225) 特别说明: 在运行iOS 12.2,watchOS 5.2和tvOS 12.2的设备的构建变体中,Swift应用程序不再包含用于Swift标准库的动态链接库和Swift SDK覆盖。 因此,在部署用于使用TestFlight进行测试或为本地开发分发而精简应用程序存档时,Swift应用程序可以较小。 为了减少Swift元数据占用的空间,现在,在Swift中定义的便捷初始化程序正在调用Objective-C中定义的指定初始化程序时,才提前分配一个对象。 阅读这些改进说明,以获取更深入的知识,以增强您对即将发生的变化的了解。 增强字符串文字定界符以支持原始文本(SE-0200) 扩展定界符 我们的设计添加了可定制的字符串定界符。 您可以使用一个或多个# (磅,数字符号,U + 0023)字符填充字符串文字: “This is a Swift string literal” #”This is also a Swift string literal”# 自定义转义分隔符 使用自定义边界定界符的字符串在前导反斜杠后镜像其英镑符号,如以下示例所示,它们产生的结果与前面的字符串文字相同: #”This string has an \#(interpolated) item”# ####”This […]

第34周Swift故事

1. 如何为中心选项卡栏项目创建自定义动作? – Yalcin Ozdemir 2. iOS中的表单-第1部分– Eric Downey 3.蒸气3系列III-测试–吴胜华 4.在Swift中同步异步– Mladen Despotovic 5.通过使用设计模式简化iOS代码– Arlind Aliu 6.基于Xcode方案的不同应用程序显示名称– Jesus Guerra 7. Swifty Firebase API @ Ka-ching —第3部分– Morten Bek Ditlevsen 8.具有Kitura编码路由的服务器端Swift CRUD API – Alfian Losari 9.在斯威夫特等待,没有失败的承诺–姆拉登·德斯波托维奇 请为这些出色的作家提供一本书,以感谢他们对Swift2Go出版物的贡献。 任何愿意在Medium上编写Swift故事的人都应邀以作家的身份加入Swift2Go出版物,并为社区做出贡献。 您可以通过发送电子邮件至 info@swift2go.com 进行 申请 。 如果您想帮助发展这个社区,可以通过与您的朋友分享出版物或其中的故事来做到这一点。 🚀 关注我们并继续关注更多Swift故事。 👇

最后了解Swift中的可选内容!

很难理解Swift中的可选概念吗? 感觉被Swift代码中不同的“?”和“!”淹没了吗? 阅读本教程以最终了解主选项! 您将在本教程中学到什么: 什么是可选选项以及如何使用它们 如何安全解开可选项 理解Swift语句中的“?”和“!” 什么是可选的? 🎁 在Swift中,变量和常量不能为零。 这意味着我们不能为他们分配任何东西。 因此,与其使用可能成为 零,并崩溃我们的程序,我们使用可选的。 为了创建一个可选的,我们必须声明一个带有类型注释的变量,但是除了给它赋值之外,我们在数据类型之后写一个“?”。 现在,我们可以为选项分配一个值或分配nil,因为可选参数可以代表这两种情况。 有几种方法可以访问可选内容中的值(以便从容器中“获取内容”)。 强制展开🔍 当我们想强制打开可选的包装时,我们告诉程序我们肯定知道可选的包含一个值并且不是nil。 我们用“!”强行打开可选选项。 但要注意 :如果在可选参数为nil时执行此操作,则程序将崩溃。 因此,只有在绝对确定可选选项不是nil时,才应使用强制展开。 为了确保我们的可选不为零 在拆开包装之前,我们可以使用一种称为可选绑定的技术。 可选装订🤓 我们可以使用if-let语句以安全的方式打开可选的包装。 因此,我们编写了一个if语句,仅在检查可选值是否包含值之后才解开可选值。 我们通过尝试将可选值分配给常量来检查这种情况。 如果可选是 nil我们的代码将返回false,因为如我们所知,常数不能为nil。 但是,如果可选值包含一个值,我们可以将其分配给常量,并且满足if语句的条件。 然后,我们可以在if语句中使用已声明的常量,并将其与print语句一起输出。 注意:声明的常量仅在if语句内可用,不能在外部使用。 也可以一次具有多个if-let语句: 当然,我们也可以使用变量代替常量。 然后,我们可以在语句中更改其值。 每当不确定不确定可选值是否包含值时,请使用可选绑定技术。 可选链接⛓ 您还应该了解一件事:可选链接。 当查询或访问可选属性,方法等时,Swift中使用了可选链接。 为了理解这一点,我们创建了一个Person类。 现在,我们声明该类的可选。 可选内容现在可以包含Person类的实例,也可以包含nil。 要访问该类的属性和方法,我们使用可选链接。 为此,我们在调用属性或方法之前用“?”标记可选项。 如果可选包含nil,则该语句也将返回nil,但是与强制展开不同,它不会崩溃。 如果可选内容包含Person类的实例,则我们的代码将执行相应的代码。 如果我们的语句返回一个值,则该值本身也总是可选的。 要访问它,我们还必须打开它。 结论🎊 希望您理解了Swift中的可选概念。 关键是,可选字段可以表示nil或一个值,可以使用强制展开或可选绑定对其进行访问。 您还可以通过可选链接对可选对象执行操作! 如果有不清楚的地方,请随时在评论中提问或给我写消息。 我会尽快回复(: […]

修复内向崩溃

几乎所有的iOS开发人员都已经发生了这种情况。 我们确实看到某些崩溃确实发生在“我的代码”区域之外,例如CFNetwork。 发生这种情况时,项目负责人经常会弹出一个问题:“计数是多少?”,如果不听,可能会出现这样的问题:“我们还有99.5%的崩溃率吗?” “是? 那么我们可以忽略它。 让我们专注于门票。” 这些崩溃最糟糕的部分是,我们不知道为什么会发生这种情况,最重要的是它发生在哪里。 我们只是空白。 堆栈跟踪没有显示与跟踪它们相关的任何内容。 在我早期的开发人员时代,我经常忽略了此类崩溃。 但是我认为,我们至少应该知道此类崩溃的根源。 也许这可以帮助我们追踪崩溃,或者,如果不是这样,则至少可以通过低估这种情况不会在应用程序的主要流程中弹出来了解其严重性。 因此,这就是我们在系统中跟踪此类崩溃的方式。 使用, Crashlytics自定义键/日志 自定义键可帮助您获取导致崩溃的应用程序的特定状态。 您可以将任意键/值对与崩溃报告相关联,可以从Fabric仪表板直接查看。 记录一些有关导致崩溃的事件的上下文通常很有用。 Crashlytics提供了日志记录工具来简化此过程。 这些消息与崩溃数据相关联,如果您查看特定的崩溃,则这些消息在Fabric仪表板中可见。 我们保存一个像 Crashlytics.sharedInstance()。setObjectValue(“ value”,forKey:“ key”) 和日志一样 CLSLogv(“正在记录-%@,%@”,getVaList([“ LogA”,“ LogB”])) 我们可以使用它们为崩溃添加更多细节。 在我们的系统中,我们有一个名为CrashTrackerController的父UIViewController ,我们的大多数视图控制器都从该子类继承而来。 从这一点出发,我们记录并保存自定义密钥 这就是其中一个日志的样子 这对我们来说确实很好。 现在,我们知道发生崩溃的控制器,通过查看日志,我们可以了解生成崩溃的最新流程。