Tag: swift

更好地编码的简单技巧(Swift iOS)

大家好,今天我决定写一个关于我认为非常重要的“提高编码技巧”的话题。 我认为这很重要,因为Swift为我们提供了许多有趣的工具,以避免在创建应用过程中出错,但是我们大多数人(一开始)通常都不使用它们。 并相信我,他们将节省很多问题。 请别再哭了。 避免使用字符串-使用枚举 如果您使用其他语言,则可能知道什么是常量,如果您不这样做: 在计算机编程中,常数是程序在正常执行期间无法更改的值 枚举是保持所有常量井井有条的方式,例如: enum Countries:String { case usa case colombia case mexico case germany } 现在,我请您考虑如何在oder中比较字符串变量以显示正确的标志。 let country =“哥伦比亚” 如果国家==“哥伦比亚” { } 如果国家==“哥伦比亚” { } 如果国家==“德国” { } 此过程可能会在您的应用程序中产生很多错误,因为通常开发人员在输入时可能会犯错。 列举救援 let country =“哥伦比亚” 如果国家== Countries.colombia.rawValue { } 通过上面的代码,您将非常确定自己正确地输入了条件。 创建面向可重用性的类 尽管这可能是有史以来最明显的建议,但可以再说一遍: 可重用性 没有人喜欢长代码文件,它们很无聊,难以阅读,实际上,当所有文件都弄乱了时,在文件中工作很烦人。 如果您有这样的事情: 覆盖func viewDidLoad(){ super.viewDidLoad() 让shadowPath = UIBezierPath(rect:self.view.bounds) 让borderView […]

斯威夫特:没人犯的常见错误-布尔斯

您好,我亲爱的开发人员, 有时您可以编写一个代码,该代码在语法级别上不是重复的,但是在逻辑上是重复的。 让我们看一个简单的例子: 最终,这段代码说:“如果是,则返回是,否则,则返回否”。 我可以说一个奇怪的口音。 让我们以更好的方式重写它: 您可以说,没有人会在现实生活中犯这样的错误,上帝,您错了。 让我们稍微扩展一下代码: 是的,我敢肯定,您已经看到了这样的代码。 我已经在不同的版本中看过很多次了,我无法一一列举。 更好的解决方案: 但是最好的解决方案实际上是以一种不同的方式分解任务,似乎函数可以完成更多工作。 但是我无法粘贴真实的生活代码(NDA处于最糟糕的状态),由于其明显的简单性,尝试重新分解didProcessEqual毫无意义。 但是我会尽力的。 分解的一种明显方法是将处理移出函数,但让我们假设,对于两种相等情况,处理的一部分是相似的: 是的,你猜对了。 该解决方案为我们带来了重复。 并且我们尝试避免它。 此外,在学校中我们了解到2 * a + 2 * b = 2 *(a + b) 。 但是,当我们开始编码时,我们似乎忘记了这个简单的原理。 让我们尝试将其应用于faultyProcess : 这些只是简单的基础知识,但是我已经看到了这样的代码,这些代码是由经验不足1年的年轻开发人员以及具有8年经验的开发人员制作的。 作为后记,请干燥并检查您的代码是否存在此类错误。 如果您没有这样做,或者至少将来会避免这样做,那么请打招呼。 就是这样,伙计们。 祝您有美好的一天,无论您身在何处,都要保持干燥。

垃圾收集与自动引用计数

在上一篇博客文章中,我们了解了iOS如何使用自动引用计数(ARC)作为其对象生存期管理系统。 在这篇文章中,我尝试指出ARC与垃圾回收或更具体地跟踪垃圾回收相比的一些显着差异(更精确的引用计数和跟踪是垃圾回收的两种不同实现。换句话说,ARC是由于跟踪垃圾收集是最常见的垃圾收集类型,因此通常术语“垃圾收集”是指跟踪垃圾收集。 ARC是使用对象所有权的编译器功能。 如果对象的引用计数为零(即不再拥有所有者),则ARC会从内存中释放对象,而不是在运行时在后台查找未使用的对象。 ARC在编译时会自动注入与Objective-C运行时等效的对象,以进行保留,释放(编译器在所有应有的位置插入保留和释放)。 我有整篇文章解释ARC的工作原理。 自动参考计数的优点 对象的销毁是实时且可预测的。 它具有对对象的确定性回收(当对对象的最后一个强引用消失时),而GC在“某个时候以后”释放对象。 如果没有长时间的收集周期就不能再引用它们,则将释放对象。 这样可以更快地释放对象。 这对于内存有限的系统(例如移动设备)很重要。 这定义了GC应用程序中可能存在的一类细微的错误,这些错误由于收集器不会在“错误的窗口中”触发而不会公开。 没有后台处理,这使得它在低功耗系统中再次变得更加高效。 如果活动对象集填满了大部分可用内存,那么跟踪垃圾回收周期就会触发得太多,这需要额外的空间来提高效率。 随着可用空间总量的减少,引用计数性能不会降低。 引用计数的渐近复杂度不取决于堆的总大小。 自动参考计数的缺点 无法收集保留周期。 保留周期即使无法访问,仍将参考计数保持在零以上 需要考虑多线程引用计数。 垃圾回收(GC)是一种自动内存管理尝试,用于回收垃圾或由程序不再使用的对象占用的内存。 在存在任何垃圾回收之前,您必须手动添加要保留和释放的调用(其他语言为“免费”或“销毁”)。 有几种实现垃圾回收的策略,最常见的两种是跟踪和引用计数。 .NET和Java平台使用跟踪垃圾收集。 垃圾收集在运行时起作用。 它检测未使用的对象,并在代码的任何部分不再使用它们时将其释放。 这发生的时间间隔不确定 (在经过一定时间后,或者在运行时看到可用内存变少时),因此不必在不再使用对象的确切时间释放对象。 垃圾收集的优势 GC可以清理整个对象图,包括保留周期。 这是垃圾回收相对于ARC的主要优势,您无需担心保留周期。 GC在后台发生,因此作为常规应用程序流程的一部分,内存管理工作量减少了。 垃圾回收的缺点 由于GC发生在后台,因此无法确定对象释放的确切时间范围。 当发生GC时,应用程序中的其他线程可能会暂时搁置。 ARC与GC 苹果的Objective-C邮件列表上的一个线程 垃圾收集简史 这个故事发表在中等规模最大的企业家精神出版物The Startup中,紧随其后的是295,232人。 订阅以在此处接收我们的热门新闻。

iOS将于2018年底发布。下一步是什么? 反应原生还是颤动?

对于iOS开发人员来说,这是“黑暗模式”的一年。 我一直喜欢将所有应用程序切换为暗模式,因为我觉得iOS开发的未来比以往更加黑暗(😬只是在开玩笑) Swift 4. iOS 12. Xcode 10 最终,我们得到了一个非常稳定的Swift版本,从现在开始,我将在各种产品中轻松使用它。 我毫不怀疑Swift语法和用法角度可读性的优点 iOS的新版本🤕Meh…我对此没有任何感觉✌️从现在开始,我可以在自己的构建设置中杀死iOS 9 =] Xcode10。优质Apple🤪您一直在增加版本号(无论如何,再次感谢黑暗模式)。 我仍然讨厌情节提要。 我希望我可以使用VSCode完全替代Xcode。 Xcode吞噬了我的公羊,Xcode吞噬了我的时间。 反应本机 今年人们疯狂谈论React Native。 人们尝试一下。 人们切换到它。 人们预言了iOS的未来。 人们在谈论关于移动开发未来的疯狂话题 和。 我也尝试过🤣(是的,我是多么好奇。) 我可以告诉您,这一直是我拥有的最佳开发人员经验之一。 用VSCode和Expo开发React Native项目是完美无缺的 毫无疑问,就屏幕切换和复杂视图而言,RN应用程序的性能不如本地应用程序。 但是说句公道话,作为混合解决方案,它相当顺利 这种折衷对于任何想要快速开发周期的初创公司都是可以接受的。 无需关心Airbnb的谈话内容。 他们很有钱✌️他们做自己想做的。 扑 我对Google的这种产品感到非常奇怪。 充当游戏引擎的想法使我非常乐于学习它。 学习曲线很高,社区仍然很小。 我还要再等一年,然后再针对任何生产产品提出建议 2019年接下来呢? 不要担心iOS会在未来5年内很快上市,但是了解React Native或Flutter等混合解决方案将为您提供更多在2019年担任Mobile Developer的机会 作为iOS开发人员,我对Apple每年发布的功能感到无聊。 别指望今年在iOS开发领域会有什么很棒的伟大创新。 也许是Xcode 11中的“更暗模式”🤣 在你走之前 – 您是否知道按下👏按钮最多可以放弃50👏? 如果您真的很喜欢这篇文章,请尝试一下! 另外,如果您喜欢自己所看到的内容,并希望我写更多内容,请给我关注Medium(Hoang Nguyen)。 ✌️ 谢谢您的阅读! […]

100天学习编码。 100天制作一个应用程序。 我可以做吗?

这是我刚刚寄给自己的一段小旅程的回顾性观察。 它来自一个疯狂的梦想,渴望改变我的生活。 我希望这可以启发人们,也可以帮助人们自我思考并认为“我可以做到!” 就像我一样! 因此,快速了解我……我是两个可爱女孩的妈妈,我有一份工作(我喜欢,有点类似),但梦想在家中工作,以便我可以花更多的时间陪伴女儿。 当我开始这个旅程时,我正休产假,一个学龄的孩子,另一个睡了很多。 那给了我空闲的白日梦,这就是为什么我陷入这种疯狂的境地。 我的工作还可以,但是我真的很想避免回到9–5。 我认为我很典型,我在Facebook上花了太多时间,在Candy Crush上花了太多时间。出于某种原因,我想制作自己的应用程序不是想快速致富,而是我不确定如何找到新职业,学习新知识,但这似乎是个好主意,我可能会喜欢。 每个人都需要动力,我在这方面感到很忙。 我接下来要设定一个截止日期-那是100天的想法,这是一个不错的整数,并且足够长(我希望)能使您牢牢掌握事情并能够真正做出一些像样的事情。 我发现我在截止日期前工作得更好,而且我认为大多数人都会这样做,但这绝对需要自我激励和奉献精神,否则整个事情很容易分崩离析。 就是这样,场景已经设定好了,尽管我仍然不知道我要做什么—但是我知道随着我开始学习该编码业务,时间会随之而来。 我在家中有一台MacBook和一台iPhone 4S,于是鲁re地放弃了– Google成为了我的近亲,我走上了学习编码的好路。 我对这种外国景观一无所知,这就像在我以前一样在Microsoft Office中闲逛一样!! 当然,不久之后我就完全困惑了。 在下载了许多千兆字节并安装了Xcode之后,我感到自己已经不知所措。 我对这种外国景观一无所知,这就像在我以前一样在Microsoft Office中闲逛一样!! 按下随机的按钮看上去并不有趣,而且Apple Developer网站似乎是为知道自己在做什么的人而设计的。所以我跳下那艘船,前往YouTube。 值得庆幸的是,一个大概6岁的孩子的声音帮助我了解了Xcode的基本知识,并让我在手机上运行了一些东西。尽管它是白色的屏幕,但它至少做了视频中说的和感觉到的就像事情开始朝着正确的方向发展。 正是在这一点上,我开始了解Swift和ObjectiveC。是的,它们是不同的东西,一个与另一个不一样! 在我看来,Objective C是更好的选择,因为它存在的时间更长,因此我猜想存在更多的教程。 我想我永远不会知道这个选择是否是一个好的选择,但是我选择了它,过了一会儿它实际上变得可读了……好吧…… 数小时或数天的沮丧,希望之后会带来很多满足感… 人们曾说过学习编码就像学习外语一样。 我不同意! 学习编码涉及更多的皱眉和诅咒。 学习编码带来更多的情感。 数小时或数天的沮丧,希望之后会带来很多满足感……所有这些都被撕毁并一次又一次地反复遍历(编码术语!)。 坚持不懈是一项关键技能,逻辑可以帮助,最重要的是-在Google不能正常工作或毫无意义时能够对Google进行正确的选择! 在学习了一个基础知识并思考了我的潜力一周之后,很明显,我并不想写下一部《 Candy Crush》或什至是游戏。 我不得不保留自己的想法,并思考一些基本但有趣的东西。 也许可爱。 我和我的女儿一直在与着色应用程序Colorify一起玩,我真的很喜欢它的简洁设计和简单自然。 它轻松,简单,最后产生了“物理”效果,您可以为此感到自豪。 我开始尝试想像像我这样的新手可以实现的类似东西。 我将永远记得我那才华横溢的灵感。 那是使您感到超级兴奋和动力的一种感觉。 我从学校逃课回来,和往常一样,穿过我的长女书包,看看那天她工作的成果。 她做了一些漂亮的图画,这当然值得冰箱门用,所以我走过去,清理了粘贴在上面的所有其他杰作之间的空间,发现了一些自由的磁铁,并自豪地粘贴在上面。 当我站起来欣赏这个新的杰作时,这个想法和构想直接浮现在我的脑海里! 像许多家庭和冰箱一样,我们拥有典型的AZ磁铁,还有诗歌词,因此您可以制作有趣的句子和诗歌。 就是这样! 一个带有单词的虚拟冰箱,您可以随意拖拉以制作诗歌和有趣的句子。 幸运的是,对于这个想法是突破性的,新颖的,或者是在1000年前完成的,我并没有太在意。 感觉是一个好主意,我可以实现,或者至少在脑海中设想了它的外观和工作方式。 […]

如何创建自定义表格视图单元格(快速)

这个故事最初发布在AppMakers.Dev 在iOS中,您可以使用“自动布局”来定义表格视图单元格的高度。 在本教程中,我们将向您展示如何使Table View Cells自动调整大小。 首先,创建一个简单的TableView,它属于您的ViewController。 创建名为Table QuoteCell的自定义TableViewCell类。 在StoryBoard中打开ViewController并将CellID添加为tableViewCell标识符。 将两个名为quoteLabel和authorLabel的标签添加到自定义单元格。 向它们添加约束。 在QuoteTableViewCell类中为这些标签设置IBOutlets。 我们的应用程序将显示引号。 假设我们要在TableView中包含以下带引号的数据。 在您的ViewController中添加dataForTableView变量。 让dataForTableView = [(“我没有失败。我刚刚找到了10,000种行不通的方法。”,“ Thomas A. Edison”),(“一个人不过是他思想的产物。他在想什么,他成为。”,“圣雄甘地”),(“业余者坐下来等待灵感,我们其余的人都站起来去上班。”,“斯蒂芬·金”),(“智慧不是教育的产物,而是终身尝试获得它。”,“阿尔伯特·爱因斯坦”)] 让我们设置TableView。 我们的ViewController将包含以下代码: // // ViewController.swift // SelfSizingTableViewCells // //由Apps-Top.com团队创建 // Apps-Top.com // 导入UIKit ViewController类:UIViewController,UITableViewDelegate,UITableViewDataSource { @IBOutlet弱var tableView:UITableView! 让dataForTableView = [(“我没有失败。我刚刚找到了10,000种行不通的方法。”,“ Thomas A. Edison”),(“一个人不过是他思想的产物。他在想什么,他成为。”,“圣雄甘地”),(“业余者坐下来等待灵感,我们其余的人都站起来去上班。”,“斯蒂芬·金”),(“智慧不是教育的产物,而是终身尝试获得它。”,“阿尔伯特·爱因斯坦”)] 覆盖func viewDidLoad(){ super.viewDidLoad() //加载视图后进行其他任何设置,通常是从笔尖进行。 self.tableView.delegate =自我 self.tableView.dataSource =自我 } 覆盖func didReceiveMemoryWarning(){ […]

iOS-SOLID原则第5页-依赖倒置原则

DIP —依赖反转原理,指出: A. 高级模块不应依赖于低级模块。 两者都应依赖 抽象 。 B. 抽象不应依赖细节。 细节应取决于抽象。 我将通过提供一些常用实现示例以及该原理说明的内容来尝试解释该原理。 假设您有一个UITableViewController,可显示附近的蓝牙设备。 我们将其称为NearestDevicesViewController。 VC及其逻辑是高级模块,它使用服务层中的低级模块, BLEClient或类似的东西。 常见的实现方式是NearestDevicesViewController具有BLEClient属性(并取决于BLEClient属性)。 这种方法根本不灵活。 更改BLEClient的工作方式或更改属性以容纳另一个类可能会破坏我们的NearDeviceDevicesViewController 。 更好的方法是使用NearestDevicesViewController需求的抽象。 我们将声明一些协议,例如DevicesProvider 。 该协议将宣布两者之间的“合同”。 视图控制器将持有某种符合该协议的类型的属性,从而使其依赖于抽象(协议),并且任何寻求帮助视图控制器的低层模块都将依赖于实现协议中提到的要求。 请注意,这与Liskov替代原则是很好的,因为此“合同”让我们在不更改程序的情况下,将设备提供程序替换为其他任何子类型) 该原理试图颠覆传统方法,即高级模块依赖于低级模块。 这种方法中的高级模块拥有抽象(通过确定协议的方法),然后这些低级模块就会遵循该抽象。 使较低级别依赖于较高级别模块的要求。 如上所述,这就是低层和高层模块都依赖抽象的地方(在本例中为协议): A. 高级模块不应依赖于低级模块。 两者都应依赖 抽象 。 在DevicesProvider的示例中,我们现在可以最大程度地享受灵活性。 例如,如果现在我们想将服务层BLEClient中的类更改为服务层GPSClient中的另一类,则可以通过依赖项注入来注入它,只要它符合DevicesProvider,并且一切都应该很好。 在这里看看我们如何解耦代码。 而不是这样: 我们现在有这个: 附近的设备视图控制器未与BLEClient耦合。 这意味着我们不必同时使用它们。 每个人都可以替换为另一个人,因为它们现在依赖于抽象而不是彼此依赖。 而已。 感谢您的支持,并在下面发表评论。 如果喜欢就拍手🙂

我们的健康编码惯例以及它们如何为您提供帮助

在Mobile First,我们以成为快乐的编码员而感到自豪。 在鼓励实验的同时,我们也认识到有时最好遵循我们自己的久经考验的指南以获得最佳结果。 为了保持平台独立性,我们寻求遵循的通用规则,并且不允许自己陷入诸如制表符缩进或语言功能之类的细节中。 我们是快乐的编码员,对我们来说,这意味着…… 复制代码行时,可能是在复制错误(错误),非最佳方法或外部依赖项。 如果有问题的代码分散在您的整个应用程序中,您将无法轻松进行改进。 查看高度重复的代码也将给您带来真正的déjàvu! 始终使代码起作用并注入依赖项/参数。 在创建,理解,测试和错误修复代码时,在一堆中做太多事情是无法管理或维护的。 这就是为什么我们使用单一责任原则。 从功能到对象,甚至到整个应用程序(例如Facebook Messenger),都可以转换为各个级别。 始终将任务分解为更小的简单组件,这些组件只能访问其所需的信息。 不要让人们在您的实现内部获取肮脏的手套! 仅公开已设计并经过测试的要更改的内容。 确保您的实现已通过单元测试针对这些更改进行了测试。 从外部角度查看对象,它的协议有意义吗? 始终使用访问级别的保护,将所有内容设为私有,并在需要时进行升级。 寻找定义明确的协议。 具有全局范围的变量和函数的全局文件(称为“常量”,“助手”或“ utils”)倾向于链接系统的不相关部分,从而使代码难以重用。 单例有相同的问题。 大量使用单例使理解对象依赖性变得很困难-因为您将必须检查实现以查看其使用方式。 由于难以模拟单例依赖关系,因此很难进行单元测试。 始终倾向于依赖注入而不是全局范围和单例。 常量应保存在其所属类的范围内。 这样可以更清楚地了解哪些对象需要运行,从而使代码更易于进行单元测试。 考虑一下对象的生命周期,不要在不需要时不挂对象。 幻数和文字使我们更难理解它们对代码的影响。 它们是非描述性的,并且经常在一个以上的位置需要相同的值,因此,当您要调整该值时,需要在多个位置进行调整……而总是忘记一个位置! 参数化常量/文字,并为元素赋予有意义的名称。 我们编写的所有代码都意识到会被同行评审。 清楚地布置代码,以使其易于阅读,理解和使用描述性名称,以便您的同事可以解密所有内容。 当您在那里时,请先查看自己的拉取请求,然后再添加对等项。 使用源代码管理时不遵循某个过程可能会导致提交未经测试的代码。 它还可能导致提交遗失,进而破坏同级的构建。 遵循 git Flow :使用功能分支,重新设置基础并使用拉取请求。 创建发布分支,仅允许错误修复,并禁止从dev分支进行合并。 一遍又一遍地执行相同的代码会变得很老,因此我们在代码中寻找有用的模式。 如果有人注意到我们面前的一种模式,为什么还要重新发明轮子呢? 将通用代码拆分为可重用的可测试框架。 寻找现有框架,进行审查并做出贡献。 在事后看来,通常会有更好的方法来做某事,我们对此表示欢迎。 我们认为重做组件化代码的各个部分应该是常见的做法。 识别何时该重构。 如果一段代码偏离了其原始意图,那么重构比将其击败来提交要好! 可能只是适当地重命名的情况,但是如果有更好的方法可以将其标记为重构。 重构是件好事,这就是世界的运作方式。 相当于生活圈的编码! …因此,我们认为自己是快乐的编码员。 我们鼓励您尝试一下并创建自己的准则。 […]

使用URL方案查询canOpenURL

众所周知,Apple继续优先考虑用户的证券和隐私。 因此,毫不奇怪,Apple在iOS 9中带来了新的安全性和隐私。出于安全原因,对查询iOS 9中的canOpenURL进行了一些更改。 添加url方案以启用URL方案:-转到信息->打开url类型->添加类型。 我们通常使用openURL:函数打开外部应用程序。 通常,首先我们查询UIApplication的canOpenURL :(返回Bool)以检查URL方案的可用性,然后使用openURL:打开外部应用。 Swift代码段:- 让appURL = URL(string:“ thatapp://”) 如果UIApplication.shared.canOpenURL(appURL!){ //开放网址的代码 打印(“可以打开URL”) } 这是一个很好的功能,但是Facebook,Twitter等开发人员使用此机制获取设备中安装的应用程序列表。 苹果认为这是对隐私的侵犯,因此在iOS 9中限制了URL方案的查询。 如果您针对iOS 9 SDK进行构建和链接,则需要将应用将查询的方案列入白名单。 如果您在应用中运行上述代码,则会收到以下错误消息, -canOpenURL:URL失败:“ thatapp://” —错误:“此应用不允许查询方案thatapp” 这是因为您需要在LSApplicationQueriesSchemes项下的info.plist中将您的应用想要查询的URL方案白名单: 在info.plist中包含URL Scheme之后,一切都会好起来的。 在iOS 9中,没有50个URL方案的限制,与在iOS 8及之前版本中一样。您可以查询任意数量的应用程序,但必须在info.plist中声明它。 强烈是要在检查Apple的应用程序时检查URL方案的列表,如果他们发现该应用程序违反了安全性,他们可以拒绝该应用程序,这就是我所相信的。

Flutter,本机API和插件(2/3)

(译自法文:Flutter,API本机和插件(2/3)) “我们需要谈谈…” 在第一部分中,我们已经了解了MethodChannels的基础。 现在,我们将仔细研究语音识别通道的基本实现。 语音识别 我们的应用程序需要使用麦克风和语音识别的权限 。 在iOS和Android 7.1+上首次启动时,用户必须接受该请求。 接受请求后,主机将调用Dart方法以确认识别可用性。 从那里,Flutter可以通过在专用通道上调用“开始/收听”方法来开始识别。 在调用start方法之后,记录开始,然后主机调用onRecognitionStarted Flutter应用程序将收到: 中间成绩单(在iOS上) 并且一旦用户停止识别( stop() ),则通过onRecognitionComplete(String completeTranscription)的最终转录 第一次实施 首先,我们需要在iOS端使用Swift创建一个项目(将ObjC用作默认语言)。 Flutter CLI使您可以使用以下命令进行定义: flutter create -i swift –org com.company speech_project ` -i swift`选择iOS的Swift –org选择项目名称空间 我们也可以选择使用-a kotlin`在Android的Kotlin中编写 扑/飞镖 SpeechRecognizer类处理Flutter 主机通信。 资源资源 文献资料 Sytody应用 Speech_recognition插件 Flutter插件和软件包