Articles of swift

迅捷属性

什么是属性? 属性将值与特定的类,结构,枚举关联。 属性类型? 商店属性。 计算属性 商店属性规则。 它可以存储常量(let)和变量(Var)作为实例的一部分。 它只能使用类和结构。 注意:我们可以在store属性上提供默认值,并且可以在初始化期间为store属性修改初始值。 例:- struct FixedLengthRange { var firstValue:Int 令长度:整数 } var lengthOfrange = FixedLengthRange(firstValue:0,length:3) //范围代表整数值0、1和2 lengthOfrange.firstValue = 6 //范围代表整数值0、1和2 在这里,FixedLengthRange类具有名为firstValue的变量存储属性和名为length的常量存储属性,其值不能更改。 常量结构的存储属性。 如果我们创建结构的实例并为其分配常量。 这样我们就不能修改属性的实例,即使它们被声明为变量属性。 例:- 让 rangeOfFourItems = FixedLengthRange(firstValue:0,长度:4) //此范围代表整数值0、1、2和3 rangeOfFourItems.firstValue = 6 //即使firstValue是变量属性,这也会报告错误 计算属性规则。 1.可以定义类,结构和枚举 2.它提供一个getter和一个可选的setter,以间接检索和设置其他属性和值 如果在属性声明中将属性定义为get {},则会将该属性变为计算属性。我们可以使用两种类型的计算属性,一种是在属性内部使用get {},也可以同时使用get {}和set {} 。 如果我们将属性定义为get {},则称为只读计算属性。 例:- 使用get {} var […]

无畏和高效地使用第三方iOS框架

当我开始职业生涯时,我在一家不允许使用第三方框架的公司里工作。 我们必须从头开始编写所有功能,以使其可以在其他项目中作为我们自己的内部框架重用的方式来构建它们。 这是一个奇怪的政策,但它可能是我作为软件开发人员曾经遇到的最好的学习工具之一。 而且,如果您认为从头开始编写功能不可行,我可以向您保证。 尽管进行了额外的工作,我们始终设法按时交付,并且该业务是可盈利的。 也就是说,我完全理解了这种情况无法承受的情况。 实际上,在我的另一项工作中,该协议正好相反:如果有一个第三方框架可以完成我们不希望使用的功能,那么我们会因浪费时间和资源进行重新发明而受到谴责。车轮。 那也是一个很奇怪的政策,但是我从使用第三方框架中学到了很多-这样做使我可以接触到其他人的代码,这反过来又为我提供了很多额外的知识和经验。 我记得那时起有那么多aha时刻。 在我的职业生涯中经历过两次极端时,我发现在两者之间取得平衡通常会给我带来更好的工作成果。 一方面,我坚信自己做事是最好的学习方法,并且从零开始编写一切都教会了我如何构建框架,可重用的模块化代码,良好的API等。 它促使我学习如何有效地编码并解决任何问题,尤其是在我的职业生涯早期,学习曲线陡峭的时候。 另一方面,选择使用第三方框架可以帮助我快速创建高质量的解决方案,使我能够向世界各地经验丰富的开发人员学习,并在遇到软件开发方面的不同见解时提高了自己的技能。 这两种工作方式都非常有价值,我希望每个开发人员也有机会体验它们。 当然,并不是每个人都可以自由地从头开始编写自己的工作,在这种情况下,通过附带项目进行尝试通常是学习的好方法。 这正是我所做的。 早在2009年,作为学习如何编写iOS应用程序的练习,我为网络和JSON,XML和HTML解析器编写了所有Objective-C实现。 为了持久性,我编写了SQLite和Core Data包装器。 我什至编写了自己的基于文本的文件存储方案,这听起来很愚蠢,但这是解决许多问题的简单方法,最终使我的客户满意。 我们非常习惯使用已知技术,以至于我们常常忘记像Core Data这样的框架在很多情况下是过大的,而自定义解决方案更便宜,构建和维护也更快。 明确地说,我还不时使用Core Data,它为更复杂的项目提供了巨大的价值。 例如,即使在过去我曾经在iPod Touch(第3代)上测试应用程序的过去,它也有助于保持较低的内存占用并保持响应式UI线程。 使用定制解决方案来做这些事情将是困难且昂贵的,尤其是在处理大量数据时。 那么,您如何在这两个极端之间找到平衡? 每次从头开始编写都是很浪费的,但是编写模块并在项目领域中重用它们是一个不错的选择,尤其是在学习时。 同时,忽略第三方框架也很浪费,这样做可能会导致您面临许多在其他人的项目中已经解决和验证的挑战。 但… 还记得解析吗? 我做。 我们很难宣布。 从今天开始,我们将关闭Parse服务,经过长达一年的时间(截至2017年1月28日),Parse将完全退休。我们很自豪能够帮助如此多的人构建出色的移动应用程序,对此我们感到很自豪,但我们需要将资源集中在其他地方。 —来自他们的 博客 解析“继续前进”,但是他们的客户继续前进又有多容易呢? 我敢肯定,你们中的许多人都受到Parse关闭的影响,这很可能是关于过多依赖第三方服务的重要教训。 但这并不总是必须像关闭服务那样极端。 例如,当您使用的服务仍然存在但不再满足您的需求时会发生什么? 长期以来,我最喜欢的REST应用程序入门框架是RestKit-与其说是REST方面,不如说是它的主要功能,而是它强大的映射框架,它允许我从JSON / XML源创建应用程序域模型而无需将该责任泄露给模型类。 我希望我可以只使用框架的那部分,但是它的体系结构使得很难分开。 令我感到奇怪的是,我无法创建自己的客户端实现,因为RestKit的许多类都在子类化AFNetworking组件(它是建立在AFNetworking 1.x之上的),因此该项目完全依赖于AFNetworking。 即使这样,我还是决定接受这些缺点并将其用于网络层。 尽管我决定仍然使用它来节省很多开发时间,但我将其隐藏在一个不会泄漏对我的应用程序依赖关系的协议后面。 我的应用程序仅使用API​​协议,并且期望返回不从Core Data,RestKit或任何框架依赖项继承的应用程序域模型。 这使得应用程序极其易于编写和编写,维护和测试,而且轻巧。 然后是苹果推出NSURLSession的那一天,而我正在从事的项目之一需要一些新功能,例如后台下载。 RestKit社区开始了有关如何移植其客户端体系结构以支持此操作的漫长讨论,但截至目前,它尚未完成。 AFNetworking […]

一个书呆子在新的Swift iOS应用程序项目中使用的第三方开放源代码框架列表。

如果您是老牌产品公司的一员,通常就没有经常从头开始新项目的奢望。 不久前, Facebook 将 其混合应用程序 迁移 到了本地Objective-C。 Lyft 和 Uber 确实将其旧的Objective-C应用程序重写为现代Swift语言。 几乎没有其他人敢这样做,这是可以理解的,这是因为成本高昂,并且有可能完全重写奶牛核心业务应用程序。 我很荣幸地体验到Uber重写的感觉,我看到了它的巨大努力以及每个人需要的承诺水平。 如果可以的话,我很乐意回想一下,重新体验一下。 作为一名工程师和有抱负的技术领导者,对我来说最重要的收获是,开发团队中普遍接受的实践的选择以及底层工具和编程范例的选择对成功的开发产生了巨大的影响。软件项目。 通过尽早做出正确的决定并进行良好的沟通,开发人员团队可以取得巨大的速度并将其维持很长一段时间,而不会积聚技术债务,继续保持应用程序架构的清洁和可维护性,并且不会互相踩踏。 我最近开始了一些新的iOS应用程序项目。 最大的花费了我两年的时间,才是功能完善的本地iOS消息传递应用程序。 在进行这项工作时,我能够尝试多种方法和架构模式,并观察它们的配合情况。 这次经验最大的收获是与整个应用程序的体系结构保持一致,这与我在一家大型工程组织工作的经验100%匹配。 您无法有效地将入职部件中的MVC与Redux进行设置结合,而将VIPER(或RIB)与其他地方结合使用。 对我来说,最有效的方法是在项目开始时获得足够的速度,并在项目的整个生命周期中保持速度,这是使用一组第三方框架,这些框架具有足够的高级抽象能力,并遵循精心选择的单一架构原理,不要在应用程序的不同部分中混合抽象级别。 作为团队负责人,最好的事情是看到所有团队成员都遵循您早日制定的原则。 因此,简而言之,这是我将要在正在启动的每个新iOS应用程序中再次使用的原理和框架的列表。 RIBs架构(用于典型的面向UI的应用程序): –因为它允许应用程序的业务逻辑而不是UI树来驱动应用程序的体系结构; –因为它可以实现下面设置的代码覆盖率和依赖项注入目标; –因为它是一个简单的概念,所以使用它实际上并不需要框架,您可以通过采用仅包含4–5个协议的模式来开始使用它; 基于初始化程序的静态依赖项注入: –因为它使您的代码具有良好的隔离性,所以可以100%进行单元测试; –简化了有关代码的推理; –使其具有运行时安全性,并具有“如果可以构建,则可以工作”属性; 反应性(RxSwift)数据/事件流,用于传递数据: –因为从数据和事件流的角度考虑您的应用程序简化了其架构; 单元测试涵盖100%的业务和演示/导航逻辑: –业务逻辑类决定应用程序应导航至哪个屏幕,应向网络发出哪些请求以及应将哪些数据存储到本地数据库; –导航逻辑很难在经典的MVC应用中进行单元测试,而这正是RIB闪耀的地方; 快照测试涵盖了100%的用户界面: –因为可以采用单元测试原则来测试UI是很酷的(例如,确保长标签能很好地包裹起来,并且不会以每种受支持的语言破坏屏幕的其余部分); UI自动化测试涵盖了关键的端到端用户旅程: –创建和维护它们很困难,并且需要一些高级工具,但是它可以实现端到端的问答自动化,并最终获得巨大回报; 用于以下方面的代码生成: –模拟课程,以便您在单元测试中可以双打考试; –网​​络服务和后端模型都是由singe跨平台IDL文件生成的代码,跨系统和团队共享,因为这可以确保这些系统可以可靠地相互通信; –本地化字符串,图像和其他资源,以便有一个过程可以使您的字符串和资源井井有条,类型安全,并自动删除垃圾; 仅允许使用RxSwift调度程序使用多线程,计时器,操作队列: –使代码可以进行单元测试(不仅是原则上的,而且以可靠,快速且可控制的方式进行),并且单元测试也不易出错; 所有UI均使用特定于领域的专用语言以编程方式创建(因此,没有XIB / Storyboards!): –以便对所有代码更改进行代码审查; –从而使UI逻辑与业务逻辑分离,并避免使用Massive View Controller模式; –这样就可以使用基于初始化的依赖项注入来实例化视图控制器和视图(并避免可选的拆包); […]

如何在技术面试中提问

在最近的一篇文章中,我提供了准备工作时要考虑的事项的概述。 技术面试。 该内容的一部分已扩展为视频,包括一个用于进入白板时回答棘手问题的基本框架。 即使我专门研究iOS开发 ,该过程也足够通用,因此可以应用于任何编程语言: 提出澄清问题 创建一个概念图 在伪代码中表达蛮力解决方案 使用可行的代码优化您的解决方案 检查错误或遗漏 当在时间限制下编码或处理不熟悉的主题时,遵循一组预定义的步骤变得尤为重要。 让我们看看如何使用此过程来回答以下问题: “ ..您将如何设计一个Stack类,除了push和pop方法外,它还具有一个属性计数,该计数返回元素的数量? 推,弹出和计数都应在O(1)时间内进行。” 什么是堆栈? 作为iOS开发人员,我们习惯于使用Swift和iOS SDK来构建用户界面元素,流程和应用。 这个问题提供了价值,因为候选人(正确地)假设Stack不是开发中通常使用的东西。 从候选人的角度来看,这个问题的答案可以将管理UITableViews的日常活动与UINavigationController联系起来 。 什么是O(1)时间? 这个答案将揭示人们应该如何考虑算法的性能。 通过了解恒定时间的重要性-O(1),他们将看到以相同速度执行的流程具有显着的优势-无论其输入大小如何。 即使在面试中问这个问题是最好的做法,但事先学习Big O Notaton也会带来很多好处。 大声思考 我们都听说过这个,但是在实践中,很难遵循。 在解决问题以最终找到解决方案的过程中,我们需要让面试官知道我们的想法-即使我们的想法看起来很愚蠢或半生半熟。 在大多数情况下,面试官希望您成功,因此他们将寻找机会引导您朝正确的方向发展。 没有任何口头反馈,他们将无能为力。 众所周知,这通常是在事情变得紧张而尴尬的时候。 优化您的解决方案 在面试中编写代码时,最好的做法是编写一个“可行”的基本解决方案,然后继续完善其语法和功能。 在性能方面,这通常会转化为在O(n)甚至O(n2)处构建可行的解决方案。 这个两步过程不仅提供了收集您的想法的机会,而且还使面试官知道您处在正确的轨道上。 最后,当您将代码重构为最终解决方案时,请问自己,如果必须处理1M数据行,该算法将如何执行? 重新定义问题通常可以使您的解决方案的各个部分看起来很扎实,但可以进一步加以改进。 代码 这是在Swift中实现的完整Stack类: //恒定时间操作-O(1)类Stack { var store:[T] = [] func peek()-> T? { 返回store.last } func push(_ […]

向视图添加渐变(Swift)

#步骤1: 创建一个CAGradientLayer var gradientLayer:CAGradientLayer = { 让gradientLayer = CAGradientLayer() gradientLayer.colors = [#Color1,#Color2] //您要添加的颜色 gradientLayer.startPoint = CGPoint(x:0,y:0) gradientLayer.endPoint = CGPoint(x:1,y:1) gradientLayer.frame = CGRect.zero 返回gradientLayer }() #第2步: 将此渐变图层添加到视图层 yourView.layer.addSublayer(gradientLayer) #步骤3 设置gradientLayer的框架 gradientLayer.frame = yourView.bounds 这是输出…😊

UITableView iOS中的分隔线

编辑分隔线的宽度 您可以通过更改单元格上的layoutMargins:属性来设置使表格视图的分隔线在表格中扩展到各种宽度。 这可以通过多种方式来实现。 更改特定单元格的分隔线 在表视图数据源的cellForRowAtIndexPath:方法或 willDisplayCell:方法中,将单元格的layoutMargins:属性设置为UIEdgeInsetsZero(扩展到表的整个宽度),或者设置为此处所需的值。 目标C [cell setLayoutMargins:UIEdgeInsetsZero]; //也可以使用spacerInset [cell setSeparatorInset:UIEdgeInsetsZero]; 迅速 func tableView(tableView:UITableView,willDisplayCell单元格:UITableViewCell,forRowAtIndexPath indexPath:NSIndexPath){ cell.separatorInset = UIEdgeInsetsZero cell.layoutMargins = UIEdgeInsetsZero } func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath)-> UITableViewCell { cell.separatorInset = UIEdgeInsetsZero cell.layoutMargins = UIEdgeInsetsZero } 删除所有分隔线 每个单元格之间的细灰色线可能并不完全是您要的外观。 将它们隐藏起来非常简单。 在您周围的UIViewController的viewDidLoad:方法中,添加以下代码。 您也可以在加载或重新加载表视图之前随时设置此属性(不一定需要在viewDidLoad:方法中)。 迅速: tableView.separatorStyle = .None 目标C: tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 另外,可以通过选择tableView并将分隔符(在属性检查器下)设置为None来在Storyboard或XIB中更改属性。 隐藏多余的分隔线 您可以通过在UITableView的底部设置一个空的页脚视图来隐藏空单元格的UITableViewCell分隔线: 迅速 tableView.tableFooterView = UIView() […]

Swift:运算符优先级和关联性➕➖✖️➗

ลำดับความสำคัญก่อนหลังของ运营商 运算符的优先级和关联性เนื้อเน้นๆอยู่ล่างๆ 社交网络社交网络社交网络社交网络社交网络pantip等。 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1–1 + 1 + 1 + 1 + 1 + 1×0 ถ้าเจอแบบนี้กันคิดว่าผลลัพท์ของโจทย์นี้คือเท่าไหร่??? ก็มีตั้งแต่อบของแต่ละคนก็มีตั้งแต่0,14,16,17,…แค่วงเล็บหายนี่เถียงกันไม่มีที่สั้นสุดจะคูณก่อนบวกก่อนหรือลบก่อนจะทำหลังไปหน้าหรือหน้าไปหลังนู้นนี่นั้นแต่ละคนแต่ละคนท 555555คำถามคือแล้วอแล้วนไหนมันเป็นเป็นคำตอบที่ถูกหละ? วิธีการหาคำตอบจึงต้องมีหลักการคิดที่แน่นอนเช่นคิดเครื่องหมายไหนก่อนซ้ายไปขวาหรือขวาไปซ้าย ➡อบที่ถูกต้องจริงๆของโจทย์ข้อนี้ก็มีหลายคำตอบ➡️ เนื่องจากหลักหรือวิธีคิดก็มีหลายรูปแบบ……#เอ้าาาาาาา😱แบบนี้ก็ได้เหรอ Blogาอยากทราบเนื้อหาเรื่องนี้อย่างละเอียดแนะนำให้อ่านBlogของพี่NuuNeoi NuuNeoI –ทำไมต้องคูณหารก่อนบวกลบ? มาย้อนความหลังกันกับเรื่องราวของ操作顺序 数学运算符运算符运算符运算符运算符运算符运算符… nuuneoi.com แล้วเกี่ยวกับการเขียนโปรแกรมยังไงหละคุณ? 💻 dingน่นอนการ编码ก็จำเป็นต้องมีหลักการคิดเหมือนกันแต่สิ่งที่แตกต่างก็คือภาษาSwiftนั้นมีหลักและการดำเนินกนการที่ตกลงไว้แล้วรนรั้นดังน คำนวนหรือจัดการกับแต่ละ运营商อย่างไหร่ตัวอย่างเช่น 变数= 2 +((3%4)* 5) น่าจะนึกออกว่าnumber = 17🍌ๆ🍌ๆาแบบนี้หละ 变数= 2 […]

Swift:运算符:

操作员คืออะไร? มีอะไรบ้าง? งนการเขียนโปรแกรมเรเองพื้นฐานมากและควรเข้าใจอย่างมันอย่างดีเลยคือเรื่องOperatorหรือตัวดำเนินการซึ่งมีหน้าตาปรปาณนี้ + – * / => <%! ? Operatorาใครเคยเขียนยรโปรแกนมก็าจะคุ้นเคยกับเครOperatorองหมายพวกนพวกนอย่างดีOperatorา SwiftาษาSwiftจะมี运算符พื้นฐานส่วนใหญ่เหมือนกับภาษาCมีแตกต่างบ้างเล็กน้อยซึ่งเป็นส่วนที่เพิ่มเติมเข้าไปตัวอย่างเช่น范围运算符..< … nil合并运算符?? เป็นต้น งระเภทของ运算符ในภาษาSwift ู่ออกเป็นหลักๆอยู่3ประเภท 一元 二元 三元 1,一元运算符 逻辑非运算符! 一元减运算符- 一元加运算符+ 按位NOT运算符~ aryารทำงานของ一元运算符คือการกระทำหรือดำเนินการบน 目标เดียว☝️ เท่านั้น…..เอ้างงดิ555😱ดูตัวอย่างดีกว่า运算符ที่เป็นUnary aryนเครื่องหมาย ! var IAmCool = true IAmCool =!IAmCool <-焦点 งไม่ายหลังพึ่งรู้ว่าตัวเองไม่Cool(เรื่องสมมุติ😎)เลยใช้操作员! falseนCาfalseาตัวแปรเป็นค่าตรงกันข้าม假ค่นได้ว่ามีการกระทำการกับตัวแปร IAmCool เท่านั้น(มองเฉพาะ !IAmCool ) ! จึงเป็น操作员แบบ一元 2.二元运算符 ด้วยความที่คำว่าBiขึ้นต้นมาก็น่าจะเดาได้ว่าการทำงานของtargetสระเภทนี้จะกระทำบนtarget สองตัว✌️ ตัวอย่างเช่นเครื่องหมาย = var name =“ Kolathee” nameนได้ว่าเกี่ยวข้องกับทั้งตัวแปร名称และ字符串“ […]

找到内存泄漏的根源。

我真的很喜欢Emilien Stremsdoerfer的内存泄漏文章,并想在结尾部分进行扩展。 您可以启用称为Malloc堆栈日志的功能,这将使Xcode内存调试器能够找到导致内存泄漏的确切代码行。 去年在Visual Debugging WWDC会话中几乎没有涉及到这一点,我认为我应该与错过它的人分享。 启用Malloc堆栈日志记录: 首先,您需要启用Malloc堆栈日志记录。 这是每个scheme都启用的功能,因此您需要在用于运行/调试项目的任何scheme上启用它。 通常,您将需要在Run scheme执行此操作: 现在,您将拥有一个升级的内存调试器。 如果在应用程序运行时单击可视调试器,则可以浏览内存泄漏,如下所示: 都是一样的,但是如果您查看右侧面板,现在就可以直接跳到导致泄漏的行: 我必须重申Emilien Stremsdoerfer关于内存调试器有点误导的观点。 在我的特定情况下,问题的根源最终是来自缺乏弱声明的第三方框架的委托-Xcode并未将其列为泄漏。 但是,由于有了内存图,我得以对其进行跟踪并提交了框架的PR。 我还要提及的是,在调试内存泄漏时应打开和关闭此选项。 启用Malloc堆栈日志记录后,使用调试器逐步调试时,某些属性未完全记录下来,这会使调试代码变得困难。 祝您调试愉快! 👍🏼 www.daniel-williams.co

没有情节提要的Swift中的字符串本地化

不久前,我迅速发表了一篇有关字符串本地化的类似文章。 该博客文章将对其进行改进。 创建一个.strings文件以在其中存储本地化的字符串。 在我们的例子中,它们是KZ.strings,EN.strings。 下一步,我们创建名为LocalizationLanguage的枚举,以便在进行本地化操作时更加类型安全。 它的原始值将为String类型。 实际上,要存储我们应用程序的当前语言,我们应该可以将其存储在某个地方。 如果是iOS,则为UserDefaults 。 它是我们应用程序中一些初始用户数据的本地存储。 我们可以轻松地存储String,Date,Data等类型的值。但是我们需要存储一个枚举,这里需要一些解决方法。 如上所示,我们的枚举具有类型为Int的属性索引 。 为了将语言存储在UserDefaults中,我们将存储其rawValue ,因为在UserDefaults中可以保存其String类型。 使LocalizationLanguage枚举符合Codable(Decodable&Encodable)协议。 因此,在这里,我们只有一个名为LanguageManager的类,可以分隔应用程序内的职责。 最后,使用称为localized()的本地化方法扩展String类型。 而已! 谢谢!