Tag: iOS应用开发

在iOS上构建自己的视频音序器时要避免的陷阱

Rosberry 的iOS开发人员Anton Kormakov 嗨! 我叫Anton,我是Rosberry的iOS开发人员。 不久前,我碰巧从事名为Hype Type的项目,不得不解决一些有关使用视频,文本和动画的有趣任务。 在本文中,我想告诉您一些陷阱,以及如何避免它们在iOS上构建实时视频定序器。 Hype Type使用户可以录制一组短片和/或多张图片,总运行时间为15秒,向制作的剪辑中添加文本,并向其中应用一个可用的动画。 在这种情况下,处理视频的关键方面是,用户应该可以选择彼此无关地管理视频剪辑:更改播放速度,反向,翻转和(可能在以后的版本中)随时随地交换剪辑。 您可以问:“为什么不使用AVMutableComposition ?” 在大多数情况下,您是对的-显然这是一个相对方便的视频音序器。 但是,遗憾的是,它有很多限制,所以我们无法使用它。 首先,不可能在旅途中更改和添加轨道-要获得更改后的视频流,必须重新创建AVPlayerItem并重新初始化AVPlayer 。 同样,使用AVMutableComposition中的图像并不是完美无缺的-将静态图像添加到时间线中,必须使用AVVideoCompositionCoreAnimationTool ,这肯定会增加大量开销,并且会大大降低渲染速度。 简短的网络搜索并未发现其他或多或少合适的解决方案来应对这一任务,因此我们决定开发自己的视频序列发生器。 首先,介绍一下项目中渲染管道的结构。 我必须立即说,我不会详细介绍希望您有所了解,否则这篇文章会引起骚动。 如果您是新手,我建议您应该更加注意著名的框架GPUImage (Obj-C,Swift),这是在OpenGLES上使用清晰插图进行处理的一个很好的起点。 负责通过计时器在屏幕上呈现录制的视频的视图( CADisplayLink )向定序器请求帧。 由于该应用主要用于视频,因此使用YCbCr色彩空间并将每个帧作为CVPixelBufferRef发送会更合乎逻辑。 在获取每个帧时,将创建亮度和色度纹理,并将其发送到着色器程序。 一个人在输出上获得RGB图像,并呈现给用户。 在这种情况下, 刷新循环如下所示: 这里几乎所有内容都是使用包装器构建的(用于CVPixelBufferRef , CVOpenGLESTexture等)—这允许将基本的底层逻辑带到单独的层,并大大简化了使用OpenGL的基本步骤。 当然,它有一些缺点(主要是-性能略有下降,灵活性较低),但是,它们并不是那么关键。 值得澄清:self.context —是EAGLContext的简单包装,使CVOpenGLESTextureCache和多线程OpenGL调用的工作更加轻松。 self.source —一个定序器,用于确定应从哪个轨道将哪个帧分配给视图。 现在有几句话关于我们如何组织要渲染的帧的获取。 由于定序器将同时处理视频和图像,因此用通用协议覆盖它是合乎逻辑的。 在这种情况下,音序器的任务是控制播放头,并根据其位置从相关音轨中释放新帧。 实现MovieSourceProtocol的对象处理如何获取帧的逻辑。 这种方案使该系统具有通用性和可扩展性,因为图像和视频处理的唯一区别将是获取帧的方法。 因此,我们的VideoSequencer变得非常简单,主要的问题仍然是识别当前轨道,并使所有轨道具有相同的帧频。 这里的VideoSequencerTrack是实现MovieSourceProtocol的对象的包装,该对象包含不同的元数据。 现在,让我们开始获取帧,并仔细观察一种情况-图像表示。 一个人可以从相机上获取它—在这种情况下,我们可以立即以YCbCr格式获取CVPixelBufferRef,然后仅复制它就足够了(为什么这很重要,我将在后面解释),并根据请求将其返回。 或从图片库中获取图片-在这种情况下,您将不得不跳过一些挂钩并将其手动转换为所需的格式。 从RGB转换为YCbCr可以在GPU中进行处理,但是,现代设备的CPU可以非常快地完成此任务,尤其要记住,应用程序在使用图像之前还会对其进行裁剪和压缩。 其余的很简单。 唯一要做的就是在给定的时间内给出相同的帧。 现在,让我们添加一些视频。 我们决定为其使用AVPlayer-主要是因为它具有易于使用的API来获取帧并处理声音。 […]

2017年适用于iOS应用开发的我的工具集

嗨,开发人员,我想分享我的iOS开发工具集列表,我不会描述框架或代码段,仅描述我在Mac上使用的应用或服务,对我来说是必需的,使生活变得更轻松。 出色的工具可以使您的日常工作变得更加有趣或愉快。 开始! 当然,第一件事是GIT客户端。 我正在使用Source Tree 。 2.图形编辑器。 也许您的团队中有一位设计师,但是无论如何,有时您需要在图形编辑器中执行一些操作。 例如:删除Alpha通道,调整大小,更改颜色等。对于这些任务,我更喜欢使用Pixelmator。 它不是免费工具,但值得。 3.使用不同的后端需要进行一些测试,查找API中的错误或类似的东西。 我推荐邮差 。 4.计时器。 我在工作时总是使用计时器,这种方法可以更好地控制您的时间。 它不仅适用于每小时合同,而且您可以更好地管理所有正在执行的任务的时间。 您正在感觉自己的生产力。 我的建议是Tyme 。 简单的工具,没有困难,项目和时间都很喜欢。 感觉您的生产力:) 5.颜色选择器。 大多数开发人员会说,您可以使用免费的Web服务选择颜色,很多。 我知道,但是有些情况下我没有互联网连接,因此我一直在工作,所以出色的拾色器的离线版本可以节省时间。 我的选择是Drop 。 6.任务管理。 实际上,我不会去描述管理和通信工具。 但是trello我不仅用于项目管理,还用于个人任务,目标,说明。 强烈推荐。 这是一个链接 。 7.持续集成,持续部署。 我的建议是buddybuild 。 想象一下,您有一台专用的Mac,但是无需编写脚本来构建项目,进行部署等。该服务会观察您的存储库,并且如果进行了一些更改,它将进行构建和部署。 如果您是旅游者或在旅途中工作,这确实是不可替代的。 如果您的Internet连接不畅,您只需要几兆字节即可推送到存储库,其他操作将由该服务完成。 或者您的笔记本电脑电池没电了,或者您没有时间编译大型项目,在这种情况下, buddybuild将为您提供帮助。 8.图像优化工具。 对于每个应用程序,构建大小始终很重要。 优化 。 9. MakeAppIcon 。 为应用程序图标生成所有图像可以节省您的时间。 10. 齐普林 。 简单生成图像,字体,颜色等。单击几下便产生了资产。 11.文本编辑器。 当然,每个开发人员都会审阅或编辑一些json […]

View Controller生命周期介绍:何时使用viewDidLayoutSubviews

作为iOS开发人员,我们总是担心自己缺乏知识,有时我们感到自己的技能不足。 我们对所有程序员说,您足够了解并且对自己耐心,因为您在日常工作或编码方面的嗜好继续保持​​卓越。 许多不同的开发人员总是会列出很多清单,说很多不同的事情,我们作为iOS开发人员首先应该知道。 但是多少钱够了? 今天,我们将专注于小事情,这些小事情将有助于使我们更加清晰地了解,以建立更牢固的基础。 我们将首先了解在新项目中每天使用的那些小代码。 我相信,小的小事情将使我们对大的事情有更大的了解。 在本教程中,我们将解决viewDidLoad , viewDidAppear和viewDidLayoutSubviews之间的差异。 到本教程结束时,我们希望您比以前有更好的理解,并能够有效地使用上述方法。 我将尝试使用许多不同的方式来解释这些方法,因为有时很难理解一条语句,这是我们大多数人都理解的真正斗争。 您可能会看到重复的解释,我将尝试用不同的词来解释,以帮助您从不同的角度理解它。 您应该现在就熟悉该方法,或者至少对每次运行代码时的作用有一个大概的了解。 每次创建项目时,您都会看到此代码。 如果您不这样做,那完全没问题。 Apple在viewDidLoad上给出的定义提到, 在将控制器的视图加载到内存之后调用该定义。 简而言之,它是第一个加载的方法。 您可能正在考虑在什么条件下可以充分利用此方法? 答案是,基本上您希望应用程序首先加载。 例如,您可能想要不同的背景颜色,而不是白色,则可能选择蓝色。 你们中有些人可能有使用这种方法的经验,并且对它有些了解,而有些人可能会发现这种新方法。 无论您的经验如何,您至少会在项目中使用其中之一。 苹果将​​其定义为“通知视图控制器其视图已添加到视图层次结构中。 换句话说,它基本上意味着在向用户显示屏幕时将调用此方法。 viewDidAppear和viewDidLoad之间的区别是,每次您在屏幕上着陆时都会调用viewDidAppear ,而viewDidLoad仅在应用加载时被调用一次。 让我向您展示一个简单的实验,以帮助您了解其工作原理。 我将使用一种更现实的方式进行解释。 您将在viewDidAppear看到,我通过添加300将viewDidAppear的位置创建在屏幕外部,并且我正在使用动画将图像从屏幕外部移动到屏幕底部中心。 到目前为止,您应该已经了解并理解,通过上述示例, viewDidAppear被重复调用,而viewDidLoad仅被调用一次。 苹果对此表示了很好的解释,称其被通知来通知视图控制器其视图刚刚布置了其子视图 。 换句话说,每次更新,旋转或更改视图或其bounds change时,都会调用viewDidLayoutSubviews 。 此处的关键字是界限变化。 但是要知道,使用viewDidLayoutSubviews ,它仅在对视图应用了所有自动布局或自动调整大小的计算之后才会发生。 这意味着,每次视图大小更改并且重新计算视图布局时,都会调用viewDidLayoutSubviews方法。 每次构建应用程序时, viewDidLayoutSubviews都会在viewDidLoad之后发生,因为请记住, viewDidLayoutSubviews是在应用布局计算时发生的。 然后,当您旋转应用程序时, viewDidLayoutSubviews将再次发生,并且这仅适用于纵向到横向以及横向到纵向。 而不是从左景观到右景观。 您可以通过转到硬件>方向使用模拟器来玩它。 但是,让我们考虑一下。 真正的用途是什么? 下图说明了使用viewDidLayoutSubviews的区别和结果。 您可以通过不实现viewDidLayoutSubviews来尝试以下示例,并且可以看到如下所示的差异。 注意宽度的变化。 现在,我将通过几件事来说明该方法的过程。 […]

将iOS应用集成到设置应用

该捆绑包包含一个“ en.lproj ”文件夹,该文件夹具有用于本地化 (值)资源的“ Root.strings ”文件,该文件是可选的实现方式,但推荐用于最佳实践。 另一个是“ Root.plist ”,我们需要对其进行配置。 →Root.plist:这是iPhone设置架构字典,其中的键包括“字符串文件名 ”,“ SettingsPageTitle ”和最重要的“ 首选项 ”,后者是数组类型。 它仅接受6个值,这些值也是字典类型。 我们可以选择拨动开关,滑块,组,文本字段,标题和多值。 选择类型后,我们可以对其进行更多配置,例如提供其默认值等。 偏好项及其属性: 1.组:组类型用于在单个页面上组织首选项组。 组类型不代表可配置的首选项。 它仅包含一个标题字符串,该字符串立即显示在一个或多个可配置的首选项(例如headerView或tableView标头)之前。 特性: Type :此属性指定首选项的类型。 例如TextField,Title,Toggle Switch,Slider等 标题 :此属性用于设置首选项的标题。 →这两个属性对于所有首选项都是通用的。 2.标题:标题类型显示一个只读字符串值。 您可以使用此类型显示只读首选项值(例如应用程序版本信息)。 特性: 默认值:此属性用于设置默认值。 例如应用程式版本 标识符:此唯一标识符用于保存和检索首选项值。 3. TextField:文本字段类型显示标题(可选)和可编辑的文本字段。 它用于接受用户的输入。 此类型的键是PSTextFieldSpecifier。 特性: 标识符:此唯一标识符用于保存和检索首选项值。 TextField是安全的:此属性用于输入安全文本,例如密码。 它具有两个值:1.是,2.否 KeyboardType:此属性用于设置键盘类型,例如URL,电子邮件地址,数字键盘等。 自动大写:此属性用于设置大写。 例如句子,单词,所有字符 4.拨动开关:拨动开关是一个ON / OFF类型的按钮。 在需要两个值之一的情况下,可以使用它来配置首选项。 特性: 默认值:用于将默认切换设置为ON或OFF。 它有两个值“是”和“否” OFF值:用于设置切换OFF值 […]

在React Native中加载自定义字体的最简单方法

字体书预览 通常,它是没有扩展名的文件名。 如果不是这样,请使用查找程序command + i查看字体全名,或者查看“字体书”以检查字体系列名称。 无法识别的字体族“ YOUR_DEFINED_FONTS_FAMILY” 如果此消息显示为红色,则可能是字体家族名称错误。 检查您的字体系列名称。 并确保在链接自定义字体之后构建了应用程序。 我想再次添加字体! 您只需从№2开始执行。 好的字体确实会给应用程序留下深刻的印象。 如果您想创建出色的应用程序,则选择字体很重要。 在网络中,我们可以以相同的方式使用Web字体系统,但是它包含性能问题。 因此,在移动应用程序中,与Web应用程序相比,这是表达的优势。 让我们开始使用自定义字体创建有吸引力的应用程序。 下次,我将向您介绍如何在React Native应用程序中有效地管理字体。 干杯! 🍺

Swift与Objective-C在2019年

Objective-C由Brad Cox和Tom Love于1984年创建,是C的扩展。它在C语言中添加了SmallTalk样式消息传递和对象定向。 Objective-C的比较优势: 与C ++和Objective C ++的互操作性 动态功能,例如方法混乱 更好地支持编写二进制框架。 Objective-C的缺点: 由于Objective-C建立在C之上,因此缺少命名空间 。 Objective-C应用程序中的所有类都应该是全局唯一的。 因此,为了避免冲突,有一个在类名前加前缀的约定。 这就是为什么我们在Foundation Framework中为类提供了‘NS’前缀,在UIKit中为类提供了‘UI’前缀。 显式指针。 在nil对象上发送消息而不会崩溃的能力以及缺乏严格的键入导致了难以跟踪和修复的错误。 该语言在语法上冗长而复杂,但是鉴于它是一种相当古老的语言,因此可以预期。 Swift是一种于2014年发布的年轻语言。它采用现代语法和功能,旨在确保安全性和高性能。 Swift于2015年12月开源。 Swift的比较优势: 由于使用静态类型以及使用可选对象和可选链接,因此Swift更安全。 支持名称空间,清晰的可变性语法,功能模式和简洁的语法。 使用Playgrounds进行交互式开发。 对于新程序员来说,Swift更容易学习。Apple的官方语言指南是一个很好的资源。 Swift表现出色,正在服务器端应用程序中找到自己的位置。 克里斯·贝利 ( Chris Bailey)在Realm Academy上的一次演讲中解释了在服务器端使用Swift的优势,他指出了Swift与服务器和云上其他框架相比的优势。 据他介绍,Swift性能卓越,内存占用量低,这使其成为服务器端开发的理想选择。 Swift现已稳定,其ABI已锁定。 Swift标准库代码包含约42.5%的Swift代码。 标准库中使用的不同语言的拆分如下图所示。 此Swift代码可能是开发人员可以用来改进自己的Swift编码的最佳Swift代码。 在本演讲中,它涵盖得很好。 Swift的比较缺点: 编译时间更长。 没有直接使用C ++库的方法。 模块格式的稳定性仍未实现,对于希望将其代码共享为二进制框架的开发人员而言,这是必需的。 结论 Swift现已正式成为ABI的稳定用户,可以被认为是一种成熟的语言。 Swift中的未来更新不会破坏从现在开始在Swift 5中编写的当前代码。 苹果提供了Objective-C和Swift之间的出色互操作性,并且不会在不久的将来放弃对Objective-C的支持。 对于团队来说,最好将其Objective-C代码的一部分迁移到Swift,因为它现在是ABI Stable。 如果您正在开发一个二进制框架,我建议您等待Swift实现模块格式稳定性。 另外,如果您要使用C ++和Objective-C ++代码库或框架,那么您将需要使用Objective-C和Swift。 […]

使用迦太基的4个技巧

我已经使用Carthage作为我的依赖项管理器大约6个月了,这里有一些我已经学到的技巧。 如《迦太基安装指南》中所示,要从组中更新特定存储库,请使用以下命令: 迦太基更新 –platform ios 很好,没问题-但是该存储库名称的格式是什么? 查看此示例Cartfile 。 您能为下面的每个依赖关系猜测正确的存储库名称吗? github“ swift / Sugar”“ e081f48892c1234dcgujk5a61892e5088fc544ff” github上的“ airbnb / lottie-ios” == 1.5.2 github“ moretap / PrettyBorders”“大师” git“ git@git.nasa.com:SeanBerry / launch-ios.git“ == 1.2.3 正确的格式是文件名的最后一部分,不包括“ .git”后缀。 因此,以上分别是Sugar , lottie-ios , PrettyBorders和launch-ios 。 如果您使用自己的SDK,则可能是将实验性更改推向实验性分支: git“ git@git.company.com/test.git”“ 86753098675309abcdefg” 有时迦太基会找您一个错误,找不到您的提交。 发生了什么? 作为高级开发人员,当出现问题时,我的第一个直觉是指责自己并质疑我的所有假设。 在这种情况下,这是浪费几个小时的好方法。 事实证明,缓存有时不更新(正如2015年的报道)。 清除它,迦太基将被迫重建对您的依赖的了解: rm -rf〜/ Library / Caches / org.carthage.CarthageKit […]

具有XIB文件的自定义UIView

如上图所示,您可能遇到了一些示例。 我现在将向您展示如何实现这一目标。 这种方法非常易于使用,可以使您的代码保持整洁。 创建一个超级类 我们将创建一个名为NibView的超类,该类将处理有关XIB文件合并的所有内容。 创建超类的力量在于可重用性。 您可以使每个UIView从其父类继承。 import UIKit class NibView: UIView { var view: UIView! override init(frame: CGRect) { super.init(frame: frame) // Setup view from .xib file xibSetup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) // Setup view from .xib file xibSetup() } } private extension NibView { func xibSetup() { backgroundColor = […]

无极内部

我如何在Swift中构建Promise / A +库 Hydra的GitHub页面 上也提供了这篇文章 介绍 在Objective-C中进行异步编程从来都不是真正令人兴奋的经历。 我们已经使用了多年的代表(我仍然记得我第一次见到它,那是在2001年左右,当时我在Mac OS X上玩过Cocoa的乐趣) ,不久前我们也参加了完成会议处理程序。 但是,这两个过程都不能很好地扩展,并且不能提供可靠的错误处理机制 ,特别是由于语言本身的某些限制( 是的,您几乎可以在C语言中执行任何操作,但这不在本文的讨论范围之内 )。 在厄运的回调金字塔(也称为回调地狱)中迷失自己是很容易的,并且通常您的代码最终变得不那么优雅,阅读和维护起来也不那么简单。 Promises可以帮助我们编写更好的代码,并且在诸如await/async之类的结构的帮助下,处理异步编程确实是一种乐趣。 早在2016年11月,我就决定在Promise库中工作,只是为了进一步了解如何实现此概念以及如何使用Swift这样的现代语言来实现这一概念。 在本文中,我将更深入地了解Promise库:Hydra的体系结构。 在本文中,您不会了解如何在下一个杀手级应用程序中使用Hydra,但将了解它在幕后的工作方式(但是我为Hydra编写了完整的文档,可在GitHub上找到它)。 什么是诺言? 承诺是将来可能会产生单一价值的对象。 该值可以是您期望的对象(即JSON响应)或失败原因(即网络错误) 。 许诺可能处于以下状态之一:已resolved (或已fulfilled ),已rejected或pending 。 一个承诺开始于待处理状态,可以转换到两个状态中的另一个状态。 一旦解决,就无法重新安置。 Promise的用户可以附加回调(或观察者)以获取有关任何状态更改的通知。 then ,Promise的最常见的运算符是and catch ,用于获取Promise的值或捕获任何发生的错误。 但是,还有其他几个运算符可以大大简化网络代码的编写方式,但我们稍后会介绍。 一点历史 Promise的历史可以追溯到很久以前,即1980年代初。 最早的实现最早是在1980年代以Prolog和Lisp等语言出现的。 “ Promise ”一词由Barbara Liskov和Liuba Shrira在一篇名为“ Promises:分布式系统中对高效异步过程调用的语言支持”的学术论文中提出(1988)。 随着承诺兴趣的增长,ECMAScript标准重新定义了Promise的新规范:Promise / A +用于定义Promise的边界和行为。 符合Promise / A +实施的主要规则是: Promise或“ […]

创建一个不使用情节提要的新iOS项目

故事板很棒,它们绝对有目的,并且使快速构建iOS应用程序变得容易。 也就是说,我发现在较大的应用程序上,它们会出现许多问题。 主要是它们很难进行版本控制,并且可能变得庞大。 我敢肯定那里有克服这些问题的团队,但对我个人而言,不使用它们会更容易。 大多数长期应用似乎都使用了直接编写的代码,或者混合了nib / xib文件和代码。 无论出于何种原因,Apple不再提供非故事板单页应用程序,这意味着我们需要做一些事情来创建一个。 我发现摆脱它们,创建一个nav或tab控制器并将其用作我的根源更加自由,而不必再考虑segues了。 无论如何,我们看到的所有奇特的东西都可以通过自定义转换来完成。 还有人在开发周期的后期决定,他们希望VC转移到应用程序中完全不同的位置,从而减少了纠缠。 无论哪种方式,您都会遇到一个应用程序,无论出于何种原因,其中一项要求是该应用程序不能使用情节提要,因此最好知道如何创建该应用程序。 这也是我们在情节提要之前制作应用程序的方式,并且总是有机会最终导致不使用它们的旧项目。 步骤1.创建一个新项目 打开xcode并创建一个新的Single View App,将其命名为任意名称。 出于本教程的目的,我将其命名为测试,不包括任何测试。 当我们打开它时,我们将有一个Main.storyboard和一个ViewController.swift文件。 2.删除情节提要 选择ViewController.swift和Main.storyboard并将其删除。 选择将它们移到垃圾桶 接下来,我们需要通过从我们的info.plist中删除主故事板,让该应用知道不使用主故事板。 打开您的Info.plist,然后单击“主故事板文件库名称”旁边的减号按钮。 步骤3.创建一个新的主ViewController,以在应用启动时使用 创建一个名为MainVC的新文件 这是UIViewController的子类。 单击“ Also create XIB file旁边的检查。 出于本教程的目的,我们将使用xib文件,但是也没有理由。 创建它之后,打开AppDelegate.swift 。 在didFinishLaunchingWithOptions我们需要让应用知道在启动时使用我们的MainVC 。 添加以下代码: self.window = UIWindow(框架:UIScreen.main.bounds) self.window?.rootViewController = MainVC(nibName:“ MainVC”,包:nil) self.window?.makeKeyAndVisible() 就是这样,构建并运行您的应用程序,您应该看到MainVC 。 您现在没有情节提要了。