本文是有关创建(iMessage样式)聊天气泡的两篇文章的第二篇。 第一篇文章在这里可用。 在本教程中,我们将介绍创建带有尾巴的聊天气泡的高级方法。 本教程是使用Swift 4.1和Xcode 9.2创建的。 源代码在Github上可用。 本教程将教您如何创建带有尾巴的聊天气泡,看起来像iMessage中的聊天气泡。 但是本文不是关于创建一个成熟的聊天应用程序的。 我将专注于如何以高级方式创建动态大小的气泡。 开始吧! 我们将创建一个UIBezierPath实例,它看起来像一个聊天气泡 并根据我们内容的大小调整此路径的大小 我们将使用boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], attributes: [NSAttributedStringKey : Any]? = nil, context: NSStringDrawingContext?) -> CGRect String实例的boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], attributes: [NSAttributedStringKey : Any]? = nil, context: NSStringDrawingContext?) -> CGRect方法来计算文本内容的boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], attributes: [NSAttributedStringKey […]
这是我们在WWDC 2017的“国情咨文”演讲期间从苹果公司获得的一切的简要回顾。 源代码编辑器 从头开始用Swift重写 内置降价编辑器 更好的修复(内联并且不破坏格式) 300多种新的诊断程序,分析仪及其修复程序 文件打开速度提高3倍,滚动速度达到60 fps,行跳移速度提高了50倍 在Playgrounds的代码编辑器中标记化(悬停时按住Cmd) 动作的上下文菜单(在标记化结构时点按) 全新的重构系统 Cmd +/-调整代码文本的大小 SDK版本可用性修复 协议实施存根修复 “提取”将实现移至其自己的方法/ let 重命名/编辑范围 跨源代码进行全局重命名/重构-跨所有片实时更新 开源转换/动作-开发人员可能会引入新的东西 斯威夫特4 字符串现在是字符集,就像数组一样 带”””多行字符串文字 单边范围和使用下标的字符串切片 Unicode 9 Grapheme Breaking(Unicode 9字素突破)-更好地支持Unicode(相对于旧版本,它实际上是正确的) 可编码协议:编码/解码JSON / plist的超级超级简单方法: try JSONEncoder().encode(Codable) vs try JSONDecoder.decode(Type.self, from: payload) Xcode 9 Swift语言版本(3.2 / 4.0)-允许逐步升级到Swift 4 构建时间:混合和匹配Swift / Objective-C的速度应提高40% 整个模块优化应该有更好的构建时间(大约2倍)(从Xcode 8.3.2开始,理论上来说) 核心技术 索引器 完全重新架构 快速打开x35更快 […]
在iOS中开始新项目的最重要问题之一是为我们的项目选择哪种体系结构,在对该问题进行了一些研究之后,我在VIPER(视图交互器演示者实体路由)中发现了解决此问题的好选择,因此,我创建了一个泛型生成器,该类自动生成类的自动生成器,该类具有通过VIPER进行通信的协议。 此解决方案基于@rayvinly在Clean Swift上创建的模板 使用VIPER模板的存储库在这里:https://github.com/alejouribesanchez/VIPER-Generics-Generator 交流的方式很简单,在该存储库中,有一个可以在此图中抽象的示例: 例 该示例是一个简单的应用程序,使用viper架构从Internet /本地存储中加载数据,其主要动作是当用户单击按钮LOAD DATA时,视图控制器调用Presenter。 如果无事可做,则演示者将执行业务规则,演示者将调用交互器;如果未完成业务规则,则演示者将调用视图控制器以通知用户。 调用交互器后,它将进行连接以获取数据并将对象返回给演示者。 然后,演示者将信息应用于业务规则,并通知视图控制器以显示正确的消息。 该体系结构的所有组件都必须实现自己的协议,该协议的思想是要了解视图,演示者和交互者的作用。 在此处进行示例:https://github.com/alejouribesanchez/VIPER-Generics-Generator/tree/master/ViperExample 感谢您的阅读! 如果您喜欢这篇文章,请单击“推荐”(❤按钮),以便其他人也可以阅读它= D 如果要聊天, 请 在Instagram上关注我: https : //twitter.com/alejouribes https://www.instagram.com/alejouribesanchez/ 如果要聊天, 请 在Twitter上关注我: https : //twitter.com/alejouribes
对于想要开发Metal的iOS开发人员而言,自然的起点是Apple的Hello Triangle演示。 它确实是金属的“ Hello World”。 它所做的只是将一个二维三角形(其角分别为红色,绿色和蓝色) MTKView到MTKView 。 顶点着色器和片段着色器几乎一样简单。 即使这样,这也是开始弄清管道各部分如何组合的好方法。 唯一的是-它是用目标C编写的。 作为Swift开发人员,我发现自己希望看到该语言的Hello Triangle版本。 因此,我决定将其转换为Swift。 (转换本身非常简单:您可以在此仓库中查看代码。) 为了使事情更加有趣,我还更新了该演示以支持宽色彩,这在Apple的生态系统中意味着使用Display P3色彩空间。 (宽色是指显示超出传统色域(称为sRGB)的颜色的能力;这是我在之前的文章中所探讨的。) 在“ Hello Triangle”中支持宽颜色在概念上很简单:不要将顶点设置为sRGB中定义的纯红色,绿色和蓝色,而是将它们设置为“ Display P3”中定义的纯红色,绿色和蓝色。 在支持该功能的设备上,三角形的角将显得更明亮,更生动。 但是作为金属新手,我觉得有些棘手。 在MacOS中, MTKView类具有可设置的colorspace属性,这大概使事情变得很简单-但在iOS中,该属性不可用。 因此,我尚不清楚我在Metal管道中的哪个位置进行调整以支持广泛的色彩。 我在这篇出色的Stack Overflow回复和相关博客文章中找到了答案。 作者解释了如何将Display P3颜色值(范围从0.0到1.0,但实际上是指比正常范围更大的颜色空间)转换为扩展的sRGB值(与标准sRGB相当,但它们可以为负或大于sRGB)。 1.0)借助矩阵变换。 确切的数学运算取决于colorPixelFormat的MTKView ,它确定在哪里应用gamma。 好的,关于伽玛:伽玛校正的要点是,在保存图像之前,色彩强度通常会通过非线性函数传递。 因为大多数图像只有256个亮度级别,并且人眼对暗色的变化非常敏感,所以伽玛功能有助于存储更多的暗度,从而牺牲了明亮的强度。 这些值随后在显示在显示器上时通过反函数传递。 由于伽玛编码不是线性的,因此在编码之前均匀分布的值(也称为压缩)在编码之后不会均匀分布。 (此博客文章对伽马校正有很好的解释。) Metal管道中可能发生很多隐式的伽玛编码和解码,并且如果您在不知道自己处于哪种状态的情况下操纵值,则事情会很快搞砸。 正如我从较早的博客文章中了解到的,当将多种颜色呈现到MTKView时,有两种处理伽玛的选项: 将您的Display P3颜色值转换为sRGB中的线性 (未编码)对应值,并允许MTKView通过选择像素格式.bgra10_xr_srgb为您应用伽玛编码。 将P3值转换为线性sRGB,然后通过选择像素格式.bgra10_xr预先在数学上.bgra10_xr应用伽玛编码。 在此演示中,这是将左角的“扩展”颜色转换为1.2249, -0.04203, -0.0196 (这是P3最红的红色,转换为线性sRGB)与将其转换为1.0930, -0.2267, -0.1501 (P3的1.0930, -0.2267, -0.1501最红的红色,是应用了gamma编码的 […]
大家好, 我们正在分享“快速每日提示”的第三包。 每周提示列表 传递运算符 算子∈ CaseIterable协议 随机播放和随机播放功能 计算属性 静态类型属性 类型方法 如果您想分享技巧,则可以从GitHub打开请求请求。 您还可以阅读 Weekly I和 Weekly II 。
首先,创建一个新项目,将TableView添加到默认ViewController,将tableView固定到ViewController,然后将ViewController嵌入到Navigation Controller中,并确保该项目能够按预期编译并运行。 这是基本步骤,此处将不介绍。 如果您在这部分上遇到麻烦,那么现在就更深入地了解这一主题可能为时过早。 您的ViewController类将如下所示: 类ViewController:UIViewController {@IBOutlet弱var tableView:UITableView? 覆盖func viewDidLoad(){super.viewDidLoad()}} 我创建了一个简单的JSON数据,它模仿了服务器的响应。 您可以下载它。 将此文件保存在项目文件夹中,并确保文件在文件检查器中具有项目名称作为目标: 您还将需要一些图像。 下载档案,将其解压缩,然后将图片添加到资产文件夹。 不要重命名任何图像。 我们需要创建一个模型,该模型将保存我们从JSON读取的所有数据。 class Profile {var fullName:String? var pictureUrl:字符串? var email:字符串? var about:字串? var friends = [Friend]()var profileAttributes = [Attribute]()} class Friend {var name:String? var pictureUrl:字符串?}类属性{var键:字符串? var值:字符串?} 我们将使用JSON对象添加一个初始化程序,因此您可以轻松地将JSON映射到模型。 首先,我们需要从.json文件中提取内容并将其表示为Data的方法: 公共功能dataFromFile(_ filename:String)->数据? {@objc class TestClass:NSObject {} let bundle = Bundle(for:TestClass.self)if let path […]
嗨! 今天的主题将是关于TeamCity以及如何在iOS项目中提供持续集成。 动机 我已经为许多项目配置了很多次TeamCity。 在项目开发过程中使用持续集成系统有很多优点。 此外,TeamCity还有很多替代方案,例如CircleCI,TravisCI等。 但是在这篇文章中,我想与大家分享我在Bright发明公司获得的TeamCity经验。 我们开始的每个项目-我们都从配置持续集成的东西开始,在这种情况下,我们使用TeamCity来处理。 这篇文章更像是一个教程,它将指导您完成iOS项目配置中的所有基本和最重要的步骤。 另外,我假设您已经下载并托管了TeamCity服务。 希望你会喜欢! 步骤1:创建一个根项目 首先,您需要转到托管TeamCity的页面。 登录后,转到“管理”页面,在“ Project-related Settings部分中单击“ Projects选项卡,然后单击“ Create project 之后,您应该看到项目中使用的版本控制的配置屏幕。 我更喜欢手动配置所有内容的方法,但是您当然可以使用预定义的部分,例如: From GitHub 。 From Bitbucket Cloud等。在此步骤中,您要做的就是提供项目的名称,然后点击“ Create 步骤2:添加VCS根目录 当然,为了构建我们的项目,我们需要提供构建源。 我们的TeamCity服务应该能够从存储库中获取更改。 如果您使用的是GitHub,BitBucket或类似的平台,则有两种方法: 向可以访问存储库的帐户提供凭据 要么 生成SSH密钥并使用它在GitHub / Bitbucket中授权TeamCity 在本文中,我将向您展示如何通过上传SSH密钥进行配置。 生成新的SSH密钥 如果您还没有听说过生成SSH密钥,或者您不知道真正的SSH密钥是什么,请查看 此链接 要生成新的SSH密钥,可以使用终端命令: 接下来,提供新密钥的名称和可选的密码,然后在运行ssh-keygen -t rsa命令的目录中,应该看到两个文件。 一个是带有.pub扩展名的公共密钥,第二个是私有密钥。 公开的将在github / bitbucket的存储库中使用。 私钥将在TeamCity服务中使用。 在TeamCity中使用生成的密钥 转到已创建的项目的“设置”页面,然后单击“ VCS SSH Keys选项卡。 […]
协议,协议扩展,协议一致性 Swift中没有抽象类(就像Objective-C一样)。 最好的选择是使用协议,就像Java接口一样。 然后,借助Swift 2.0,您可以使用协议扩展添加方法实现和计算的属性实现。 唯一的限制是您不能提供成员变量或常量 , 也没有动态分配 。 怎么运行的 如果您熟悉Objective-C,协议并不是什么新鲜事物。 为了说明此解决方案,以下示例定义了一个具有单实例方法要求的协议: 协议RandomNumberGenerator {func random()-> Double} 该协议RandomNumberGenerator ,要求任何符合条件的类型都具有一个称为random的实例方法,该方法在每次调用时都会返回Double值。 这是采用并符合RandomNumberGenerator协议的类的实现。 此类实现称为线性同余生成器的伪随机数生成器算法: 可以扩展协议以将方法,初始化程序,下标和计算属性实现提供给符合类型。 这使您可以定义协议本身的行为,而不是每种类型的单独一致性或全局函数。 例如,可以扩展randomBool()协议以提供randomBool()方法,该方法使用所需的random()方法的结果返回随机的Bool值: 扩展 RandomNumberGenerator {func randomBool ()-> Bool {return random()> 0.5}} 通过在协议上创建扩展,所有符合类型的类型都会自动获得此方法的实现,而无需进行任何其他修改。 协议扩展可以将实现添加到符合标准的类型,但不能使协议扩展或从另一个协议继承。 协议继承始终在协议声明本身中指定。 礼宾员工{ var AnnualSalary:Int {get} }扩展员工{ var biweeklySalary:Int { 返回self.annualSalary / 26 } func logSalary(){ print(“每年$ \(self.annualSalary)或每两周$ \(self.biweeklySalary)”) } } struct […]
简要回顾概念 当我们谈论功能的组成时,我们采用的是两个功能,其中一个的输出值是另一个的输入值。 他们都必须等待一个参数(这将是复合函数的输入),也就是说,它们没有被完全应用。 (此过程称为部分申请) (雾)(x)= f(g(x)) 在谈论部分应用程序时,特别是在讨论部分应用程序功能时:如果传递的参数少于期望的接收数量,则该函数将返回一个新函数,该函数将等待其余参数。 f(x,y,z):w / f(x,y)->(g(z)-> w) 没有另外的基本概念,局部应用就不可能存在。 咖喱化是将等待几个参数的函数转换为一系列接受一个参数并返回等待下一个参数的函数的过程。 考虑到这一点,部分应用是计算直到特定参数N的过程。 f(x,y,z):w / f(x)->(g(y)->(h(z)-> w)) (我没有使用数学符号,尽管这样做是正确的,因为这些概念属于数学。 所有这些概念在这里都有更好的解释,以及如何在Swift中应用。
循环是重复的代码块,我们可以用来对Swift中的多个数据执行一项操作。 DRY原则指出“不要自己重复”。这是一种已存在很长时间的编码原则,但是Swift中的循环是重复代码的块。 如何使用循环是一种好习惯? 虽然循环反复重复相同的代码,但这样做是在单个循环的范围内进行的。 例如,我们可以从数组中传入数据,并且可以对该集合的每个项目执行相同的操作。 这是Swift语言非常有用的组件。 在这篇文章中,我们将学习3种流行的Swift循环类型。 让我们变得循环! 🙃 搭建游乐场 首先,如果尚未打开Xcode,请点击Create New Playground 。 给它起一个类似Loops的名称,然后单击Next 。 选择某个位置以保存此.playground文件,然后单击“ Create以保存它。 您应该看到类似以下的屏幕: 删除左侧的所有样板代码,但根据需要保留import UIKit 。 为什么要使用循环 假设我们有4名员工在公司工作。 每个员工的薪水不同: 员工1:$ 45,000 员工2:$ 100,000 员工3:$ 54,000 员工4:$ 20,000(对不起,兄弟)。 创建4个变量(每个雇员一个),并将每个变量的值设置为上面的相关薪水: 导入UIKitvar employee1Salary = 45000.0 var employee2Salary = 100000.0 var employee3Salary = 54000.0 var employee4Salary = 20000.0 我们刚刚完成了2016年第四季度,我们度过了非常成功的一年。 我们希望给每个员工加薪10%。 在您的游乐场中,键入: 导入UIKitvar employee1Salary […]