Tag: Objective C

iOS / Swift中的OpenCV入门

对于不认识的人,OpenCV是计算机视觉开放源代码库。 它是用C ++编写的,这意味着您几乎可以在任何地方使用它。 从桌面应用程序到移动应用程序。 简而言之,OpenCV是: OpenCV(开源计算机视觉库)是一个开源计算机视觉和机器学习软件库。 OpenCV的构建旨在为计算机视觉应用程序提供通用的基础结构,并加速在商业产品中使用机器感知。 作为BSD许可的产品,OpenCV使企业可以轻松地使用和修改代码。 尽管创建新项目并添加pod或框架不是通常的任意任务,但考虑到它的好处,这是一个相当简单的过程。 首先,您可以克隆包含我们将在此处执行的操作的存储库。 在这个项目中,我们将从手机的摄像头获取视频流,并对其应用一些简单的色彩效果,仅用于演示目的。 因此,您需要将必需的权限添加到您的info.plist文件(即NSCameraUsageDescription 。 我们将添加OpenCV框架并将其与Swift一起使用。 首先创建一个项目(du!)。 然后初始化pods: $ cd project_root_directory $ pod init 然后将框架添加到您的Podfile : pod’OpenCV’,’〜> 3.1.0.1′ 不要忘记打开由CocoaPods创建的工作区,而不是打开您创建的项目。 OpenCV对称为Mat的n维密集数组数据类型(而不是UIImages 。 因此,我们需要一种在两者之间进行转换的方法。 为此,我们UIImage添加扩展 UIImage + OpenCV.h UIImage + OpenCV.mm 不要错过.mm扩展名。 它表明它是一个Objective-C ++文件,因此XCode以此进行编译。 否则它将无法正常工作。 接下来,我们将创建一个类,用于从相机获取图像流以进行处理: OpenCVCam.h OpenCVCam.mm 上面的类初始化相机,并处理每一帧。 它没有做任何花哨或复杂的事情,但对于初学者来说,这很好。 好了,图像已处理。 现在怎么办? 现在,我们必须在视图控制器中获取图像,或者将其实际使用或呈现。 为此,我们定义了一个委托(在OpenCVCam.mm ): OpenCVCamDelegate.h 到目前为止并不难,不是吗? 好的,我们差不多完成了。 不过,有一个很小的问题。 […]

如何使用Appcode和Swiftify加快应用程序到Swift的转换

Swiftify提供了多种将Objective-C代码转换为Swift的方法。 如果您使用AppCode而不是Xcode进行开发,则可以使用Swiftify的AppCode插件直接从编辑器中转换代码行或整个文件的选择。 优点 AppCode的可扩展性使其成为一个理想的IDE,可将您的Objective-C项目逐步迁移到每个文件的Swift。 它使您能够: 同时转换.h和.m文件对,与Swiftify的Xcode扩展名不同,由于Xcode Source Editor扩展名的限制,Swiftify的Xcode扩展名一次只能处理一个文件。 借助内置的AppCode项目文件解析器,自动更新Xcode项目文件。 无需离开AppCode或使用外部工具即可完成整个转换。 安装插件 要安装Swiftify AppCode插件,请转到AppCode菜单,然后选择首选项 。 从侧面板中选择插件 ,然后选择底部的浏览存储库按钮。 搜索“ Swiftify”,然后单击“安装”按钮。 最后,重新启动AppCode以开始使用插件。 入门 在开始将代码转换为Swift之前,您需要添加API Key 。 转到Swiftify扩展页面,然后复制您的API密钥。 返回AppCode,打开AppCode> Preferences ,选择Tools ,然后快速化并粘贴您的API密钥。 在AppCode中打开您的应用,然后选择一个Objective-C类开始对其进行转换。 将Objective-C类转换为Swift AppCode插件可让您将代码行或整个文件中的一部分转换为Swift。 选择一些Objective-C代码,右键单击它,然后选择Swiftify> Convert Selection to Swift 。 您也可以通过单击“ 工具”菜单,然后选择“ Swiftify”来访问相同的选项。 要转换整个类,请从项目窗口中选择.h和.m文件,右键单击它们,然后选择Swiftify> Convert [FileName] to Swift 。 Swiftify将创建一个新文件,其中包含来自Objective-C标头的所有类和方法以及您选择的实现文件。 请注意,在这种情况下,Swiftify不会生成Objective-C桥接标头,因此,如果新生成的Swift代码使用Objective-C类,则需要手动创建桥接标头。 为了能够构建项目,请选择旧的.h和.m文件,右键单击它们,然后选择从Xcode项目中排除 。 这将从项目文件中删除对这些文件的引用,但会将它们保留在项目目录中,以防您需要再次返回它们。 确认一切正常后,可以继续从项目目录中删除旧的.h和.m文件。 选择下一个要转换的Objective-C文件,然后执行相同的步骤。 如果遇到错误,表明您的项目对刚转换的类的某个体系结构具有未定义的符号,请确保选择“运行”>“清理构建文件夹” ,然后再次构建应用,以进行清理构建 […]

如何保持您的iOS本地化文件整洁-Swift脚本版本

与bash脚本类似,我们首先通过create()从根目录中递归搜索本地化的字符串文件。 Apple的FileManager通过枚举对象使文件搜索变得容易。 注意,由于我们通常将打包在本地化文件中的Pod本地化文件打包,因此我们将忽略它们。在parse(_ path: String)方法中的本地化文件并存储时,我们将在此处搜索键重复来优化脚本。 Set的键。 该方法将为所有重复的密钥以及找到的文件路径打印error 。 ( 注意:任何 print(“error:”) 或 print(“warning:”) 格式都会通知Xcode在工具栏上显示相应的消息以及其他构建失败和警告 ) 接下来,我们将验证validateMatchKeys方法中所有可本地化的字符串文件中的键是否匹配。 我们将使用symmetricDifference编织出任何与基本文件都不匹配的额外键。 如果任何可本地化的文件不包含相同的键,则此方法将引发错误并中止脚本。 这使您有机会在下一次执行cleanWrite()之前清理可本地化的文件,它会使用已排序的键并删除多余的空格和换行符来重写可本地化的文件。 下一步是搜索代码库,存储这些文件中使用的密钥,并根据我们的基本密钥进行验证。 有了一点正则表达式,我们就可以成功找到密钥并将它们和文件的路径存储在LocalizationCodeFile结构中,同时还可以通过紧凑地映射出没有密钥的任何文件来优化脚本。 一旦有了我们的结构,我们将点击validateMissingKeys() -将遍历我们的LocalizationCodeFile集合,并减去基本键的每组键。 此结果中的任何其他键都不是我们基本键的子集,因此会给我们丢失的键。 如果找到任何丢失的键,则会引发错误。 我们的最后一个策略是搜索任何死键,这些死键是在可本地化文件中定义但未在我们的代码库中使用的键。 我们可以通过从flatization从LocalizationCodeFile集合中收集的所有键减去基本键来检索死键。 此处找到的所有键均显示为警告,因为此步骤更多是建议清除技术债务,而不是影响问题的用户。 对具有600多个可执行文件和估计800多个密钥的企业代码库执行bash脚本平均要花费81秒 。 在相同的代码库上运行此swift脚本平均要花3秒 ! 🚀🙌 保持干净 ,可读的代码库应该是每个工程师的目标。 通过将此Swift脚本注入到您的后期构建中,清理和维护可本地化的文件应有助于实现该目标并感到自动化。 您可以阅读我以前的博客,以了解如何将脚本注入到Xcode构建后编译中( https://buildingvts.com/clean-ios-localizable-files-8b910413b985 )。 我还在其中包括了一个包含整个脚本的GitHub项目以及此处的示例项目:https://github.com/ginowu7/CleanSwiftLocalizableExample。 随时发表任何意见或建议,您可以在Twitter @ ginowu07上关注我! 编码愉快! 🙏

在您的Swift应用中运行时内省和修改类

介绍ObjectiveKit 还记得2016年5月的重大动态辩论吗? 如果没有,请快速阅读以下内容: 动态迅捷 布伦特·西蒙斯(Brent Simmons)(如果有不清楚的话,请参见存档):在最近和将来的文章中,我正在记录问题…… mjtsai.com 简而言之,争论是开发人员目前正在利用ObjC运行时的动态功能解决许多类型的问题。 当我们(可能)朝着Swift完全取代Objective C的未来迈进时,Swift将需要提供自己的本机动态解决方案。 在iOS和macOS上,至少在可预见的将来,Swift将在Objective C运行时之上运行,这意味着我们可以完全访问这些功能。 可悲的是,在Swift中使用它们确实很痛苦。 我们可以做得更好…… 你好ObjectiveKit ObjectiveKit是用于访问Objective C运行时函数的新Swift框架。 它使自省,修改方法和在运行时创建类之类的事情变得非常容易,以一种对Swift来说尽可能原生的方式进行。 它是如何工作的? 您需要做的就是初始化一个ObjectiveClass对象,该对象的类型是您要内省/修改的类,然后使用ObjectiveKit的众多功能之一。 这是一个简单的示例: 使用Objective C运行时既有趣,有教育意义,又对调试非常有用。 但是,这也很危险-在生产中使用前请格外小心。 检查一下: github.com/marmelroy/ObjectiveKit

NSTimer代表NoSwiftyTimer

NSTimer是Apple提供的创建计时器的最简单机制之一。 您可能已经看到它适用于多种用途:在一定的延迟后显示或隐藏视图,定期更新的视图或周期性或延迟执行的任何其他任务。 毫无疑问,它们是非常通用且功能强大的工具。 NSTimer基本上只是在等待特定时间间隔之后,然后将特定消息触发到其目标。 如您所见,我在这里谈论消息和目标。 这是第一个问题出现的地方。 目标和消息听起来不是很迅速,对吗? 最近,我不得不使用NSTimers,我发现了一些令人讨厌的细节。 首先,正如我们所看到的,它具有基于Objective-C运行时的非常古老的时尚语法,使用目标和选择器而不是闭包,这使它们在我的Swift代码中看起来像一条鱼。 另一方面,更重要的是,如果您不关注ARC,则NSTimers是在应用程序中引入内存泄漏的最简单方法之一。 为什么? 好吧,请检查以下示例: 从NSTimer到SwiftyTimer 苹果在NSTimer的文档中留下了非常明确的信息: 子类化注释 :您不应尝试将NSTimer子类化。 由于这个原因,我决定使用组合来创建我的自定义Swifty版本的NSTimers。 基本上将它们包裹起来,将其讨厌的部分扫到地毯下。 但这将使我能够解决这两个问题,获得更快捷的语法并更容易避免内存泄漏。 使用这个简单的包装器,我们能够以非常简单且易读的方式避免来自计时器的强烈引用。 再一次,如果您将此代码复制到操场上,您将看到它现在生成另一个输出: 你好 再见 多亏了附加层,我们得以避免内存泄漏,因为NSTimer现在保留的不是使用计时器的代码,而是SwiftyTimer的实例。 当然,我们在SwiftyTimer和NSTimer之间仍然有一个保留周期,但是通过使用SwiftyTimer的invalidate方法,我们可以轻松打破这一局面。 在这一点上,快速化定时器的使用,使用参数的默认值并利用闭包是一项非常容易的任务。 最后获得一个更具可读性和更少错误的解决方案。 结论 Apple可能(并希望)很快会给仍然需要它的那些API带来所有的爱和温柔,但是与此同时,它们是创造力的好借口,因此获得了更具可读性和安全性的代码……害羞! 如有任何疑问,请随时在github,twitter或dcordero.me上添加我。

iOS TableView使用Swift预取数据源

Apple引入了用于在iOS 10中预取UITableView和UICollectionView的 API。这是有关如何实现UITableViewDataSourcePrefetching协议的简短故事。 总览 为了实现预取,我们向视图控制器确认了UITableViewDataSourcePrefetching协议,就像UITableViewDataSource和UITableViewDelegate一样 。 这使表视图的数据源可以在调用tableView(_:cellForRowAt 🙂数据源方法之前开始为单元格加载数据。 入门 将视图控制器设置为表视图预取数据源 tableView.prefetchDataSource =自我 在tableView(_:prefetchRowsAt :)的实现中,初始化指定索引路径中单元格所需的数据的异步加载。 func tableView(_ tableView:UITableView,prefetchRowsAt indexPaths:[IndexPath]){ 用于indexPaths中的indexPath { 警卫让_ = loadingOperations [indexPath]否则{返回} 如果让dataLoader = dataStore.loadPhoto(at:indexPath.row){ loadingQueue.addOperation(dataLoader) loadingOperations [indexPath] = dataLoader } } } 当表视图通知您tableView(_:cancelPrefetchingForRowsAt 🙂方法不再需要数据时,取消挂起的数据加载操作 func tableView(_ tableView:UITableView,cancelPrefetchingForRowsAt indexPaths:[IndexPath]){ 用于indexPaths中的indexPath { 如果让dataLoader = loadingOperations [indexPath] { dataLoader.cancel() loadingOperations.removeValue(forKey:indexPath) } } } 异步加载数据 与tableView(_:cellForRowAt […]

有效地将UISearchController与UICollectionView结合使用

使用UITableView可以轻松集成UISearchController,而使用UICollectionView则不容易 问题 苹果公司的iOS类UITableView与UISearchController及其UISearchBar配合得很好,但是,几乎所有开发人员在尝试将搜索栏与UICollectionView对象进行可视化集成时都举手示意。 在开发负责显示大型组织的REST服务的照片缩略图的应用程序时,我发现了这个问题,并且我希望拥有与UITableView相同的布局。 基于StackOverflow和其他发布内容,大多数人要么不理会试图直观地集成类,要么重载了节标题。 解决方案 由于我希望搜索栏以动画方式显示和隐藏,并在UICollectionViewController的上下文中与相关的集合视图保持正确的尺寸,因此这比我期望支持iOS 9的工作量要多得多和10,但我确实为我的需要制定了解决方案。 为了实现这一点,我编写了一个名为DSSSearchController的UISearchController子类,该子类添加了许多用于显示和隐藏搜索栏的方法。 我将其设计为可与任何视图一起使用,但仅使用特定的集合视图对其进行了测试。 在下面,您将找到Objective-C标头和源代码以及Swift中的版本。 如您所见,需要大量代码来确保搜索栏相对于集合视图的大小正确。 在iOS 9和10中,Apple似乎不将AutoLayout与由UICollectionViewController管理的集合视图一起使用,因此这就是为什么使用框架进行大量计算的原因-试图使用AutoLayout被证明是有问题的。 早期,我发现某些动画会产生一些我不喜欢的搜索栏重影或覆盖,因此这就是为什么某些操作按其原样进行排序的原因。 为了使用我的类,我编写了一个名为configureSearchController的方法,该方法在viewDidLoad期间调用以初始化该类并在搜索栏上设置一些选项。 在我的原始代码中,获得searchBar属性后,将其barTintColor更改为深海蓝色,将tintColor更改为白色,并将其搜索字段的tintColor更改为深海蓝色。 另外,我的导航栏的barStyle属性具有UIBarStyleBlack。 当用户点击导航栏中的放大镜图标时,将调用toggleSearchBar:方法。 我发现当我要展示一个视图控制器时,我需要知道我的搜索控制器是否是要展示的控制器,这是在搜索字段具有焦点时发生的。 我确定我的解决方案可以改进,并且可能会在更高版本的iOS中中断,但目前可以使用。 希望iOS 10的后继版本将内置一个解决方案。

使UI适应iPhone X时从设备模型中抽象出来

仅使用“自动布局”使按钮具有自定义外观 我们的设计师最近要求在屏幕底部制作一个如下所示的按钮: 在这篇文章中,我将展示如何在不依赖设备模型查找的情况下实现这种自适应UI。 心态 每年,当新设备问世时,人们一直在问如何以编程方式检测模型的问题(2017年也不例外)。 尽管可以这样做,但该API有点奇怪。 这是因为Apple努力教会我们不要这样做。 取而代之的是,他们要求开发人员在进行功能测试时依赖可用性测试,并依靠自动布局来制作自定义界面。 换句话说,抽象远离特定的设备模型。 好吧,在一个可能可行的理想世界中……从这个角度看事物有时确实会有所帮助。 安全区 我要做的第一件事是更改按钮的约束,以遵守主视图控制器视图的安全区域。 这立即解决了我们在iPhone X Simulator和Xcode 9中首次启动该应用程序时遇到的问题。 NSLayoutConstraint * buttonBottomConstraint = nil; 如果(@available(iOS 11,*)){ buttonBottomConstraint = [self.button.bottomAnchor约束EqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor]; } 其他{ buttonBottomConstraint = [self.button.bottomAnchor约束EqualToAnchor:self.bottomLayoutGuide.topAnchor]; } 注意:如果您想知道bottomLayoutGuide.topAnchor ,这是因为bottomLayoutGuide具有id类型。 没有帮助吗? 好吧,这超出了这个故事的范围。 对不起that 然后,我决定重做按钮的所有约束,以坚持安全区域: NSLayoutConstraint * buttonBottomConstraint = nil; NSLayoutConstraint * buttonLeadingConstraint = nil; NSLayoutConstraint * buttonTrailingConstraint = nil; 如果(@available(iOS 11,*)){ […]

Mobven的iOS环境

曾几何时,iOS开发工具相当简单且静态。 目标C是一门成熟的语言,它基于良好的旧C语言。Cocoapods仅被接受为依赖性管理器。 然后斯威夫特发生了。 没有指针,没有分号,没有.h文件。 它为不了解C / C ++或Java的人提供了一个避风港。 Swift 1.0是一个有趣的工具。 表/集合视图不再是痛苦的来源,项目变得整洁,应用程序原型制作时间大大减少。 但是,每次更改都会带来混乱。 斯威夫特也是如此。 语法不稳定(对那些经历过2.0移植的人们是有帮助的),缓慢的编译时间(如旧的Eclipse经验),错误的语法荧光笔(很抱歉,不是错误的,不能正常工作)和不眠,咖啡因激发的工程师是我最早写的。 Swift是从多年经验中提炼出来的产品。 最终,它将在许多领域取代Objective-C,但今天不是那天。 因此,为了不造成令人尴尬的生产失败和小故障,我们坚持使用旧的Objective-C,并在实验室实验中限制Swift。 在Mobven,我们创建了一个应用程序开发流程,以赋予开发人员自由的空间。 开发过程非常简单。 该代码与单元测试一起编写。 然后,一位资深人士与原始作者进行审查。 如果一切正常,则将代码合并到主分支(称为dev)中。 CI系统使用Fabric和周期结束来构建,测试和发布。 为了保持循环运动,工具必须固定且可靠。 这是Mobven iOS团队提供的5个基本开发工具。 Git:源代码控制是工程师必不可少的工具。 这样可以防止出现“新文件夹(42)”的情况。 而且,它使开发人员可以在同一代码库上工作。 Git旨在管理巨大的代码库,并且可以完美地完成其工作。 Jenkins CI: Jenkins提升了周期的重量级。 首先,它提取代码,运行测试,创建IPA并将其分发。 其次,它检查每个推送分支的代码质量和代码覆盖率。 许多开发人员讨厌编写像文档这样的单元测试,但这是整个应用程序的故障保护。 防止将新的错误引入代码库是一项巨大的优点,并且可以节省时间。 Cocoapods:作为依赖项管理器,Cocoapods的工作方式类似于Ruby Gems。 它可以正常工作并节省大量时间。 我们在内部和公开使用我们的应用程序和框架。 捕获:在应用程序开发中,创建错误场景是一项艰巨的任务。 借助Capture,我们的质量检查团队可以轻松指出错误的UI实施和崩溃情况。 动量:这种内部框架使我们能够毫不费力地重新创建错误方案。 质量检查团队还将其用于自动化过程测试。 总之,没有一种创建移动应用程序的真正方法。 我们的团队始终如一,纪律严明,堪称典范。 动量和捕获是它的产物。 坎纳·塔塔尔(Caner Y.Tatar) 软件工程师 http://www.mobven.com

Swift与Objective-C:Swift开发的7大好处

iOS在包括美国,英国,加拿大和澳大利亚在内的全球多个主要市场中占据主导地位,被认为是商务应用程序的首选移动平台。 实际上,就应用程序收入和采用率而言,iOS已证明胜过其主要竞争对手Android。 然而,新兴技术将iOS应用程序开发的快速性和可用性提升到一个新的水平。 忽略它们对于每家现代公司来说都是判断失误。 选择合适的技术栈是构建iOS应用程序时需要做出的最重要的决定之一。 这就是为什么在过去的几年中,Objective-C与Swift的困境一直是人们讨论的热点。 背景 Swift是Apple创建的一种通用而强大的编程语言,它是Objective-C的现代替代品。 自2014年正式发布以来,Swift经历了很长的路要走,从引起争议和经常受到批评到成为最受欢迎的编程语言和最受追捧的技术技能。 该语言主要用于构建iOS,Mac,Apple TV和Apple Watch的应用程序,已被iOS社区的开发人员迅速采用。 随着苹果公司最近的“大动作”,开源其全新的编程语言,在iOS开发人员社区的共同努力下,Swift有望实现更快的增长。 许多最有才华的开发人员都在早期采用Swift,并将当前的项目转移到它上,这对于如此年轻的技术而言是非凡的。 但是,它的前身似乎不会很快失去立足点:Indeed.com代表的趋势表明对Objective-C开发人员的稳定需求。 因此,至少到目前为止,这两种语言将继续在iOS生态系统中共存。 只要使用最新版本的语言,使用Objective-C(或与Swift结合使用)运行应用程序构建就可以了。 除此之外,完全在Swift上构建新应用程序有多安全? 这种方法有什么好处? 通过使用实际案例和具体示例,以下信息包含了我们对Swift必须提供的好处的看法。 Swift的好处:为什么要为新项目选择Swift? 1. Swift应用程序快速且高效 从一开始,Apple就将Swift定位为一种快速,轻量级的语言(嗯,它的名字不言而喻)。 根据苹果公司发布的官方信息,Swift比Objective-C快2.6倍,并且随着每种新语言版本的增加,这一数字也在增长。 对于面向客户的应用程序,即使速度差异很小,也可能是决定产品成功与否的关键因素。 如果您的产品需要处理繁重的计算或具有复杂的业务逻辑,那么速度和性能就变得更加重要。 这就是Swift成为构建快速高效的面向消费者的应用程序的首选技术的原因。 另请阅读:在雇用应用程序开发人员之前要询问的10个问题 2.提高团队生产力和幸福感 Swift代码真的很接近自然英语。 简洁明了,这对开发人员的生产力产生了积极的影响。 作为Apple开发人员工具生态系统的一部分,Swift提供了所有必要的现成工具。 除了良好的旧XCode外,Swift还为开发人员提供了绝佳的机会,即可以通过使用Swift Playgrounds即时查看运行中的代码。 所有这些方面使Swift开发变得快速高效。 反过来,这意味着可以为您节省更多的时间和金钱。 此外,根据Stack Overflow Developer的调查,Swift连续第二年仍是最受欢迎的编程语言之一。 开发人员对语言完全钦佩,这一事实极大地促进了开发人员的动力和生产力。 另请阅读:创建应用程序需要多长时间 3.建立时考虑到安全性 使用Swift,您的开发人员可以使用高级错误处理来避免在Objective-C中发生的大多数典型错误。 在Objective-C中,某些缺陷可能不会引起注意,并且以后可能导致无法预测的系统行为。 减少了反馈循环,因为Swift代码中的错误可以通过编译器错误看到,并且可以立即得到解决。 结果是减少了生产中的崩溃和错误,从而大大减少了开发测试阶段所花费的时间和金钱。 4.您的应用程序将面向未来 正如Lyft的首席工程师Martin Conte Mac Donell所说:“使用现代工具为Apple已经计划的一切打开了大门-新平台,新设备。” 实际上,Swift提供了开箱即用的工具和资源,可为Apple生态系统中的每个设备(从Apple Watch到Apple TV)构建应用程序,这意味着100%的兼容性,使您可以充分利用硬件的潜力局限性。 […]