在开发过程中,我最近的iOS应用“为您放松声音”,我不得不面对一些问题和挑战。 其中之一是在滚动过程中滞后的集合视图。 刚开始时,我确定这只是模拟器而已,我对此并不太在意,但是随后我为iPhone进行构建,并且看到了与模拟器相同的滞后集合视图。 我深入研究代码,开始检查所有内容,一段时间后,很明显,集合视图性能问题是由两件事引起的:阴影和圆角。 事实证明,我一直用于阴影处理的代码并不是非常有效。 这是我以前使用的代码。 上面的代码将阴影添加到集合视图中的单元格中。 每次移动单元格时,都会重新绘制以这种方式创建的阴影。 因此,当我滚动集合视图时,所有单元格都被重新绘制了阴影。 这足以破坏iPhone 6s +上的流畅滚动。 幸运的是,它非常容易修复。 这是我现在使用的代码。 这两个简单的代码行使滚动收集视图超级顺畅。 它们允许绘图系统将阴影缓存为位图,然后重新使用它,直到需要重新绘制为止。 对于我的收藏视图单元格以及整个视图中几乎所有其他阴影,这是一个完美的解决方案。 因此,如果您的收藏视图(或其他任何视图)使用了大量阴影,并且在滚动过程中感觉放慢了速度,那么这也可能是您的解决方案! 这是我想与您分享的提高性能的第一(最简单)技术,第二将很快发布! 谢谢您的阅读,我希望您学到了一些有用的东西🙂
在本文中,我将尝试以最简单的方式说明如何尊重函数式编程的构建块,该模型经过数小时的研究,发现它并未得到充分利用。 Swift是一个功能对象混合体,因此它为我们提供了应用功能编程的支持,无论是类型推断还是灵活的功能管理。 快速回顾一下范式: 函数是一个转换,它接受一个(或几个)参数并返回一个值。 函数也是范例的一等公民 ,这意味着它是一个值,可以将其作为参数传递给另一个函数,获取结果甚至存储它。 以Currying为基础,我们可以给函数提供比期望少的参数,因此它将给我们带来期望缺少参数的函数。 此概念称为部分应用程序 。 我们也可以像在数学世界中一样在彼此之间编写函数,只要第一个函数的输出与第二个函数的输入匹配即可。 我们还可以将函数作为其他函数的参数传递。 将其他函数作为参数接收的函数称为高阶函数 。 如果没有支持不可变性的上下文,这一切都是不可能的,这意味着我们的函数不会更改我们的数据,而是会给我们提供副本,这是将函数应用于原始数据的结果。 每次我们调用具有特定值的函数时,预期结果都是相同的。 这些概念是范式的基础,将它们组合在一起可以赋予我们极大的灵活性,更高的代码可重用性百分比,并使我们可以构建更具声明性的组件。 现在,我们如何在Swift这样的混合语言中应用这些概念,并专注于功能的一部分? 职能和一等公民 在任何事情之前,我们定义“添加”功能: func add(number:Int,otherNumber:Int)-> Int { 返回号码+其他号码 } 它的类型是: 添加::(Int,Int)-> Int 范式允许我们在恒定的情况下存储此函数: 让storedAdd:(Int,Int)-> Int =添加 或者也可以像这样直接定义: 让加= {(num(num:Int,otherNum:Int)in num + otherNum} 返回值是隐式的,类型是自动推断的。 这两个声明是等效的,因此它的使用取决于首选项和上下文。 定义函数后,假设我们要将5加到几个数字上: 让foo = add(5,1)let bar = add(5,5)let bla = add(5,100) 您在这里看到问题了吗? 在每种情况下,我们都重复相同的操作,即增加5。如果我们想再执行10次该怎么办? 样板代码。 如果我们要进行更改怎么办? 如果不是要加5,而要加20,该怎么办?复制粘贴不是一种选择。 […]
正如我所说的,我根本没有发布任何应用程序的计划–直到我上了Udemy的Geeky Lemon课程。 在编写了基本应用程序,设计并添加广告以及关闭广告的方法之后,他通过发布与我进行了交谈。 在不知不觉中,我已经在App Store上发布了一个应用。 Tap Stars在我的生日那天上线,并且仍可供下载-现在我正在了解一个新版本,有关Swift和iOS的更多信息。 瑞安·莫里森(Ryan Morrison)的《踢星》 自那时以来,我已经完成了数十门课程,遵循了在线指南并观看了YouTube视频,从而使我对自己构建基本应用和游戏的能力充满信心。 我的想法是我通过建造中学到的。 通过遵循指南和编码以及与其他人一起构建一个完整的应用程序,我比以往任何时候都可以教我更多的知识,从而更快地获得了更多的知识。 实际上,我最近已经完成了另一个对儿童友好的计算器应用程序–而不是一个屏幕来完成您具有加,减,减,除,乘和平方根屏幕的所有功能。 我遵循了一个指南,但是从他的代码中转移了很多,以一种更适合我的风格的方式来做。 我也已经开始研究macOS版本以练习跨平台工作。
3月16日,我到达阿姆斯特丹的PathéArena。 今天,标志性的电影院都与 Appdevcon 有关, Appdevcon 是应用程序开发人员(主要)为应用程序开发人员而举行的年度会议。 我进入,迅速拿起我的徽章,然后上楼梯去会议厅。 在那儿,我加入了越来越多的排队等候咖啡的开发人员。 在他们的背后,像CocoaheadsNL,荷兰Android用户组,Appsterdam和Egeniq(活动组织者)这样的赞助商正在共享美食。 拿到急需的黑咖啡和一瓶水后,我去了13号馆进行当天的第一次演讲。 演讲者:Ash Furrow ( Artsy ) 主题:通过建立更好的团队来构建更好的软件 一个非常鼓舞人心的演讲,与实际的发展无关。 相反,Ash专注于管理心理学以及如何为在那里的团队创造最佳的工作环境-从而构建更好的软件。 简而言之:创造一个每个人都感到安全,没有任何羞辱的空间,并有足够的空间进行公开讨论。 这将使人们指出错误,承认错误,最重要的是从错误中学习。 怎么样? 假设每个人都在尽自己最大的努力,预期并解决苦难,并始终表现出同情心。 此外,Ash推荐Radical Candor作为一本不错的书,并总结了协同作用的概念,因为“……团队是团队合作的总和”。 演讲者:保罗·哈德森( 用Swift破解 ) 主题:如何像专业人士一样进行调试 Pauls的话题全部是关于iOS和Swift的。 Paul从一个非常熟悉的示例开始,在代码中包括print()来检查问题,然后是另一个print()然后是另一个,然后是另一个……然后,您明白了。 Paul提供的解决方案很简单: 断点 。 他演示了如何使用它们在激活时自动打印东西或播放声音。 Paul解释说,而不是删除断点,而是检查BreakpointManager枚举以使其为有条件的。 假设您要调试登录流程。 将BreakpointManager.login设置为’true’,所有登录流程断点将被激活。 由于某些断点适用于所有应用程序,因此您甚至可以在团队中共享它们。 Paul还分享了其他有用的调试技术,该网站真棒,使他们对Assert,Precondition和FatalError有所了解,并为我们提供了许多新的见解。 咖啡时间(休闲时光! 在拍摄下一张咖啡因时,我遇到了前同事Dylan Drost,他刚刚在Cross Platform大厅完成了关于Flutter的演讲。 我请他分享精彩片段,他很高兴地做到了: Flutter的当前状态,例如Dart语言的自定义渲染引擎 Flutter当前缺少可用于生产的内容,例如视频播放和其他基本本机功能 Google大量投资Flutter和Android,因此实际上是在与自己竞争 Google的新操作系统Fuchsia可能会在Flutter被采纳为Android的替代品时发挥作用 我很快又给自己喝了杯咖啡,坐下来进行下一次演讲。 演讲者:Phil Nash( Jetbrains ) 主题:可选不是失败 Phil首先讨论了函数的域和共域,并继续探讨Swift的发展方式,在错误处理方面缺乏该语言,以及如何以及为何引入可选函数。 […]
目前,我处于项目模式,这是我在Flatiron学校的最后阶段。 与小组成员交谈后,我意识到我对使用mapKit或CoreLocation不熟悉。 因此,我决定尝试使用它来尝试在地图上找到我的当前位置。 以下是我采取的步骤: 1.在Xcode中启动一个单一视图项目。 2.(可选)创建项目后,转到情节提要,然后将视图控制器嵌入导航控制器中。 转到编辑器,单击“嵌入”,然后选择导航控制器。 3.在项目右侧的“实用工具”部分,搜索“ Map Kit视图”并将其拖到视图控制器中。 扩展视图的大小以填充屏幕,然后添加缺少的约束(您可以使用三角形的“分辨工具”,位于编辑器的右下角)。 4.现在,在助手编辑器中,控制并拖动视图控制器中的地图视图以创建出口。 5.进入您的info.plist文件,并在信息属性列表下添加字符串类型为NSLocationWhenInUseUsageDescription的键。 该值可以是任何描述。 6.在视图控制器中,导入mapKit和核心位置。 7.使用CLLocationManger添加位置管理器属性,并在viewDidLoad中,在加载视图后立即设置位置管理器。 8.最后,添加位置委托方法:获取传入的最后一个位置,找到位置的中心以及通过定义要显示的地图部分来创建区域。 9.点击运行! 这就是我得到的。
作为Wireless Registry的移动开发人员,我一直在调整,升级和个性化我们的iOS和Android SDK,以供开发人员集成到他们的应用程序中。 当然,在任何人使用板载SDK将应用程序投入生产之前,他们需要在一系列设备和操作系统版本上对其进行测试。 多年来,尽管拒绝具有冗余架构片段的二进制文件一直是App Store审核过程中不受欢迎的怪癖,但绝大多数iOS开发人员至少部分地依赖模拟器来进行方便的版本和设备测试。 因此,我通常为开发人员提供准备好发布的框架,其中包括对真实设备体系结构(ARMv7,ARMv7s,ARM64)的唯一支持,以及带有“胖”二进制文件的框架,除实际设备外,还可以在模拟器上进行测试。 在本文中,我将描述将Swift框架转换为胖二进制文件的最快方法(不过,如果您有几分钟的时间,则应在Build Phases中设置运行时脚本,而不要使用命令像我这样的线)。 首先,创建Swift框架 在XCode中创建一个新的框架项目,选择“框架和库”,突出显示“ Cocoa Touch Framework”图标,然后命名您的项目。 将所有Swift文件添加到项目中,并确保将要从外部访问的所有类/方法都声明为public。 最后,确保已将调试版本的“仅构建活动体系结构”设置为“ 否 ”: 现在,使框架通用 打开命令行,导航到可以保存临时文件的目录,然后输入(但不执行): $ lipo -create -output YOUR-FRAMEWORK-PROJECT-NAME 现在,回到您的框架项目并运行两次:一次以连接到计算机的真实设备为目标,一次以模拟器为目标。 然后,在“产品”文件夹下,右键单击YOUR-FRAMEWORK-PROJECT-NAME.framework,然后选择“在Finder中显示”。 您应该看到一个类似于以下内容的目录结构: 右键单击Debug-iphoneos框架内的可执行文件 目录,按住Option键,复制其路径,然后将其粘贴到命令行中。 添加一个空格,然后对Debug-iphonesimulator框架目录中的可执行文件执行相同的操作。 您的命令行现在应如下所示: $ lipo -create -output您的框架项目名称实设备可执行路径名仿真器可执行路径名 现在执行它! 结果应该是您指定目录中的新可执行文件。 删除Debug-iphoneos框架目录中的可执行文件,并将其替换为刚创建的可执行文件。 最后,将Debug-iphonesimulator版本中的i386和x86_64切片从Debug-iphoneos目录拖到.swiftmodule文件夹中。 现在,您在Debug-iphoneos中的框架目录是通用的! 最后,将框架导入Swift项目 要亲自查看,请启动一个新的Swift项目,导航到项目窗口内的“常规”选项卡,然后将.framework目录拖动到Embedded Binaries(选择“如果需要,复制项目”)。 现在,只需导入框架,在代码中的任何位置调用其方法和类,然后在真实的设备或模拟器上运行它即可!
嘿伙计! 今天我们将讨论通用的东西,看看上面的图片。 你看到了什么? 提供一些屏幕的简单iOS应用程序导航流程。 他们有什么共同点? 乍一看,我们可以观察到基于TableViewController构建的四个屏幕,对吗? 你同意吗? 可能最直观的方法是构建五个视图控制器来完成此应用程序,但我想分享一种方法,我们将仅使用两个方法。 一个用于所有列表屏幕中使用的通用表视图控制器,另一个用于显示未找到的屏幕,第二个视图控制器的构建只是为了证明您可以将另一种视图控制器与我们将要展示的概念集成在一起的概念。这里。 在本文的最后获得GitHub上的完整代码。 有什么变化? 如果您看一看,确实会注意到这些表格视图屏幕中的单元格正在发生变化。 因此,我们可以将表视图作为通用组件重用,并自定义所需的任何单元格。 为了使用故事板实现此目标,我认为这很困难,我不会说不可能,但是我花了很多时间,而且我也找不到一个优雅的解决方案,这主要是因为我们必须告知通用类型,并告知通用视图控制器和方法情节提要实例化不利于此。 因此这是一个复杂的主题,当然也有优点和缺点,如果您想了解更多信息,我在下面的链接中写了一篇关于该主题的文章: 什么? 以编程方式进行布局? 你疯了吗? 我为什么要这样做? 当我第一次听它时,我承认这听起来很奇怪。 一个聪明的同事向我和我建议了… medium.com 因此,为了实现此目标,我使用了程序化的视图控制器,请看以下内容: 上面的代码具有执行表视图控制器表示所需的全部内容,并且具有(cellForAt)方法,numberOfRowsInSection和didSelectRowAt方法已实现。 注意构造函数推断出的通用类型,该通用类型有一个约束,并且它必须符合协议DescriptiveProtocol才能为(cellForAt)方法中的每个项目提供绑定UITableViewCell的方法。 因此,以这种方式,数据源中的每个元素都必须告知必须通过表视图中的可重用出队方法返回哪种单元格类型。 这是窍门,通用表视图对单元格一无所知,因此可以将其用于所有单元格。 描述符对象负责保存单元格类型,重用标识符和配置单元格必须调用的闭包。 如您所见,此结构符合DescriptiveProtocol,并且具有称为描述符的属性,如上所述,它有责任将其绑定到UIViewTableCell专业化,这时将在调用表视图cellForAt方法时通知单元格类型。 其余代码是不言自明的,我认为这不是灵丹妙药,但是可以在某些特定情况下帮助某人,如果您有话要说,请随时发表评论。 再见,下次见。 heuristisk / hkImperatorMensa hkImperatorMensa –通用表视图控制器 github.com
去年大约这个时候,我被允许访问工作中的数据库后端,并着手自学SQL。 我具有只读访问权限,因此在老板提供的一些示例以及google的一些帮助下,我在系统中玩转并进行了试验,发现错误,并快速学习了复杂数据库中的SQL基础知识。 我对SQL感到很自在,它使我想起了拉丁语,并对它们如何组合有了很好的思维导图。 我于今年1月在墨尔本的Rails Girls之前开始学习Ruby。 遵循《 Rails Girls》中的教程非常棒,并且在一天结束时有一些有用的东西令人鼓舞。 在那之间,我们那天遇到的可爱的人们,以及Nimmo对Ruby的热情,确定了我的道路。 下一步是Ruby for Kids(傻瓜类),遵循教程的要求很棒,我制作了一些游戏,这非常令人满意。 我正在学习如何做东西! 不过,我感觉好像不明白自己在做什么。 我尝试过在线课程,但是由于无法设法使Ruby符合我脑海中的“语言”模式,我变得越来越沮丧,直到我在Ruby Monk方面有了精神突破(Ruby并不像一种语言,就像一种编织方式)图案!)。 有了这种观念上的转变真是一种解脱,但是我真正想要的是一个可以尝试使用Ruby的地方,在那里我什么都不会破坏。 有很多建议只是开始编写一些东西,但是我不知道该怎么编码。 即使有了《 Ruby for Kids》一书,我还是在做东西,但要遵循别人的条件。 我可以看到您需要设置游戏的结构,然后在其后填写一些代码,但是如果不遵循说明,我看不到如何知道如何做。 然后,一个朋友读了“与好友一起学习Ruby”,并提到他正在学习Swift-我调查并找到了Swift Playgrounds。 Swift Playgrounds为我提供了我所需要的,一个无法打破,易于重置的游戏场所,结果Ruby for Kids试图教给我的东西开始变得有意义,而我我对Ruby有了更多的SQL级别的了解。 我爱Swift和Playgrounds。 您从一个角色开始,而Playgrounds会教您一点点语言。 在每个新步骤中,您都必须提出一个解决方案,该解决方案可以提供他们所要求的结果,但是您如何到达目的地并不重要。 它们鼓励您尽可能优雅,但最低要求是使其正常工作。 它非常出色,并且开始在我的脑海中构建一种代码语言及其工作方式的模型。 克服挫败感真令人兴奋,我希望Ruby也有类似的东西。 这是否意味着我将必须学习足够的知识才能做到这一点? 国王尼姆王
如果初学者和高级程序员有什么共同点,是我们希望事情简单明了吗? 没有功能或效率的折衷 核心数据是一个非常有用的框架,它使开发人员能够在设备上本地管理数据。 尽管有用且非常强大,但是对于初学者来说,这尤其令人恐惧,尤其是在处理诸如NSManagedObject和NSPredicate NSManagedObject对象时。 当我们只想管理数据时,对于经验丰富的开发人员来说也可能会很费力。 CoreDataBC解决了这个问题; 基于核心数据构建的高级框架。 它可以解决您必须解决的大多数麻烦,并使开发人员更轻松地交互和管理其数据模型。 这就是框架的简单性。 // 保存数据 self.coreData.pushSingleValue([“ ”:]) //检索数据 self.coreData.retrieveData() //获取数据 let coreDataRecords = self.coreData.getData()//返回NSManagedObject的数组 //更新数据 如果让recordToUpdate = coreDataRecords.first { self.coreData.update(recordToUpdate,[“ ”:] } 如果您想要有关该框架的更多信息,请参阅GitHub文档。 在本教程中,我将演示如何使用CoreDataBC创建一个简单的待办事项列表 应用程序 。 没什么复杂的,只是一个简单的UITableView将显示一些数据,一个添加到列表中的按钮以及滑动操作以将其标记为已完成和删除。 先决条件 您应该至少在UITableViews中具有一些背景知识,并已安装CocoaPods。 如果您尚未安装CocoaPods,请参阅CocoaPods安装指南。 如果您正在阅读本文,那么我假设您已经对UIKit框架以及Swift有了很好的理解。 最后说明:一切都会以编程方式完成,只是增加了挑战。 项目设置和安装 创建一个新的Single View Xcode项目,并选中“ Use Core Data并打开终端。 暂时关闭Xcode项目,并在终端中将CD插入Xcode项目目录并初始化pod。 荚初始化 这样,您的项目目录中将有一个名为Podfile的新文件。 在文本编辑器中打开文件,然后在其下方显示“#Pod # Pods for 添加CoreDataBC pod。 […]
让我们来看看所有可能的方式 所有应用都以一种或另一种方式定义全局常量。 有人认为所有常量都应该是全局常量的一部分,无论是仅在一个位置还是在多个位置使用它。 在开始时,一切看起来都不错,但是随着您的应用程序的增长,您将发现难以管理。 恕我直言,如果只在一个地方使用常量,最好不要创建全局常量。 您可以使用类型属性在类型上而不是在该类型的实例上定义常量。 要将类型属性声明为常量,只需使用static let 。 通常,以这种方式声明的类型属性优于全局常量,因为它们更容易与实例属性区分开。 让我们探索在多个地方使用全局常量时声明全局常量的方法: 使用结构 struct是值类型,可用于定义常量。 您也可以使用嵌套struct创建层次struct 。 结构常数{ 静态让步宽度:CGFloat = 100 静态让高度:CGFloat = 100 } 常量可以这样访问: Constants.width 嵌套结构将如下所示: struct ConstantsStruct { 静态让行高度:CGFloat = 18 struct ContainerSize { 静态让步宽度:CGFloat = 100 静态让高度:CGFloat = 100 } } 这种方法的缺点是,您最终会创建struct实例。 let instance = ConstantsStruct() // Useless, but legal 2. 使用无大小写的枚举: 为什么命名为不区分大小写的枚举? […]