Tag: 编程

Swift编程入门第10部分-代码结构,可读性和原理

在上一篇文章中,我们介绍了基本协议,扩展和下标。 开始进行Swift编程第9部分-基本协议,扩展和下标 在上一篇文章中,我们介绍了类型转换,安全展开可选内容和访问控件。 medium.com 协议具有更强大的功能,扩展功能更是如此,但是将来我们将介绍这些功能。 既然您现在知道了Swift中常用的顶级实体,我认为现在是时候讨论代码结构和可读性了。 如果您像我希望的那样一直在练习,您可能已经编写了一个相当大的程序,吃过晚饭或出去了,而当您回来时,您会觉得自己的代码有些失落。 刚开始时,这种情况经常发生。 如果分心,您会感到沮丧,因为您忘记了5分钟前写下的内容。 别担心,这发生在我们大多数人身上。 我有一个好消息,随着时间的推移,它确实变得越来越容易,需要多长时间取决于您练习的次数。 对我来说,每天大约要花6个月的编码时间。 从我醒来直到上床睡觉的时间,甚至在周末,我总是在写代码。 不要误会我的意思,这并不意味着我没有生活,我仍然出去玩得开心。 有时我会筋疲力尽,不得不停止编写代码一两天。 即便如此,我仍在阅读文章,并试图做得更好。 所以继续练习。 前几天,我开始思考,Swift中的代码结构真的没有任何东西。 一切似乎都是道听途说或遵循教程的结构。 每个人的写作风格都有自己的怪癖,没有标准化的东西。 我不是要规范代码结构 。 我想说清楚。 我只是将我所看到的所有内容和我自己的代码样式进行汇总,以帮助您提供一个起点,使您可以组织代码并轻松地理解以后再返回代码时的情况。 话虽这么说,让我们高谈一下应用程序的各个部分如何在您的Swift文件中显示。 类,协议和扩展仅是顶级实体。 最高层,我是说它们没有被花括号包围。 可以这么说,他们坐在裸露的文件上。 结构和枚举几乎总是顶级实体,但是它们也可以出现在其他结构或枚举中。 函数可以是顶级对象,但我只建议在控制台程序中执行此操作。 对于macOS,iOS,tvOS和watchOS程序,我会坚持将功能保留在类中。 常量和变量应在尽可能小的范围内声明,这意味着如果只需要在if语句中存在一个变量,则在if语句内声明它。 如果将在整个文件中使用其中任何一个,请在文件顶部声明它并提供适当的访问控制。 综上所述,我将为您提供一个示例,说明如何以代码格式布置文件,我的示例将基于放置在所有新View Controller文件中的View Controller代码段。 对于您自己以及其他阅读您代码的开发人员而言,可读性比对用户而言更为重要。 您应该努力在所有代码中都具有出色的可读性。 分手 如您所见,当您写入大量功能时,这些文件会变得很长。 因此,我倾向于将这些文件分解为同一文件夹组下的单独文件。 我见过的命名约定如下: ViewController+NameOfDelegate.swift或ViewController+NameOfDataSource.swift 这样,我知道要单击的文件应包含哪些代码,这有助于我确保该文件仅包含与其相关的代码。 使用上面的示例代码,我将提取枚举并将它们放在自己的文件中,如果我想为全局枚举创建一个名为Enums.swift文件,我可以使用//MARK:将其拆分为几个部分,以便稍后可以跳入进行更新。 如果文件中的枚举仅用于此视图控制器,则将访问控制设置为internal,但将文件与ViewController类放在同一组下。 除非协议是在模型中定义的,并且打算供其他类使用,否则我可能会取出协议及其扩展名并将其放置在自己的文件中。 如果协议具有类或结构特定的扩展名,我将使用//MARK:通过Protocols.swift文件将其逻辑上分开。 同样,我将以与Enums.swift相同的方式放置文件。 我还会撕掉该结构并将其用作名为House.swift 。 我还将它分成名为Models的组,因为它是房屋的模型。 该类及其所有方法将保持不变,但是我可以取出特定于类的扩展,并将其放置在新文件ViewController+Extensions.swift 。 只要确保将需要由扩展程序调用的ViewController.swift中的任何方法都设置为internal […]

在Swift中编写我的第一个iOS应用程序之前,我想知道什么

上周,我们和我的兄弟一起发布了我们在Swift中开发的第一个iOS应用程序。 在本文中,我想分享我对过程的看法。 这是从一个人的角度写的,他花了六年的时间在Ruby和JavaScript中构建各种Web应用程序(在规模和领域方面),而最近三个月一直在Swift中工作。 Objective-C死了吗? Swift是由Apple开发的,Apple是世界上最大的公司之一。 这意味着很多事情; 首先,苹果公司不怕对其平台进行重大更改。 所谓重大变更,也是指破坏代码的更新。 您需要注意这一点。 例如,在上一个WWDC期间,他们宣布重命名了API的较大部分。 Swift本身是对iOS开发人员以前的主要语言(Objective-C)的巨大转变。 顺便说一句,对我来说,WWDC像工作一个星期一样,赶上所有有趣的演讲和公告。 即使这样,Swift还是我见过的维护得最好的开源项目之一。 只需检查存储库及其语言建议即可。 这是否意味着Objective-C已经死了,您不需要知道吗? 的种类。 我敢肯定,您可以在Internet上找到的大多数外部库和代码示例都是用Objective-C编写的。 但是,有趣的是,当我在Swift中做更多的事情时,了解Objective-C代码的问题就会减少。 我几乎可以自然地阅读它。 您需要知道的另一个事实是内部API的大小,它很大,开始浏览时可能会感到害怕。 您基本上可以构建任何东西,并且可以访问所有移动专用功能,例如摄像头,麦克风,地理位置,加速度计,触摸屏等,比在网络上容易得多。 工具集 XCode(Apple IDE)是发生魔术的地方。 它包括在iOS应用程序开发过程中需要的所有工具:代码编辑器,界面生成器,数据库管理器,调试器,检测工具等。 不幸的是,这远非完美。 特别是Interface Builder,它提供了最多的“最新动态” 。 当我开始玩它时,我真的很感动- “哇! 我可以在诸如Sketch或Photoshop之类的图形编辑器中构建整个界面”-这不是事实。 Interface Builder更像是抽象层,用于覆盖编写的代码,而不是用于设计UI的工具。 在Interface Builder中选择一个选项并不少见,但这完全不会影响您的应用程序。 那里有很多您无法猜到的东西,您只需要了解它们即可。 这样的错误约束警告,您可以通过直接单击警告描述来解决。 另外,删除插座或动作时,切记要删除情节提要中的引用。 您在编译过程中不会收到任何警告,但是如果不删除它们,您的应用将崩溃。 您需要找到最佳位置。 根据我的经验,Interface Builder可以方便地设计应用程序流程,放置内置UI元素,并在视图控制器之间(而不是在按钮和视图控制器之间)创建序列。 将所有设置存储在代码中,并使用对现有UI对象的继承来创建自定义UI元素。 当您创建iOS应用程序时,计算机图形编程比Web应用程序要多得多。 我的建议是阅读有关向量之类的基础知识或转换的工作方式。 了解这些主题非常有用,因为您将尽快而不是稍后面对它们。 始终在真实设备上测试您的界面。 单击模拟器并用手指点击真实设备的感觉完全不同。 官方的依赖项管理器尚未发布,但是您可以在两种社区驱动的替代方案之间进行选择:CocoaPods或Carthage。 我正在使用第一个,并且没有遇到太多问题。 最后一个小技巧:不要过多地依赖撤消选项。 当您按cmd + z时,XCode不会在文件之间跳转,因此您无法直观地跟踪更改。 […]

Swift 3高阶函数简介

介绍 今天又是一天。 另一个美好的一天。 另一个迅速行动的好日子。 但不只是其他任何一天。 今天我们要进入丛林。 准备好一些Swift丛林荒野。 我最近在YouTube上观看了一些随机的动物战斗,因此本文发生在丛林中。 保持光线凉爽。 旅行愉快。 我们将讨论的主题是具有map,filter,reduce以及将这三个元素放在一起的高阶函数。 欢迎使用Wild Edition:Lio The Lion 。 前提条件 强烈建议您在开始学习之前对函数和闭包有扎实的了解。如果您确实在本文中遇到任何困扰,希望这些文章对您来说很有价值。 因此,如果您对这些文章还不确定,请务必查阅其中的任何文章。 Swift 3中的主函数 Swift 3中的闭包简介 故事 饥饿的狮子想要食物。 食物枯竭。 他的物种只剩下3个中的1个。 大地,搞砸了。 饥饿的狮子。 o 廖是他的名字。 廖是饥饿的狮子。 他会吃任何东西。 任何人。 躺在一片绿色的丛林中,看上去更像沙漠。 干无叶。 廖闭上双眼冬眠。 左眼睁开……等待中。 等待杀死。 人类也是如此。 Bon来了。 天啊 你在这里做什么? 廖把目标对准了猎物。 肉 他睁开右眼。 看邦。 茎秆 伸展他的背部。 降低他的立场。 向远处左移,落在Bon的视线之后。 廖动。 向前移动。 仍然低而动。 仍然用狙击手的稳定盯着猎物。 […]

使用Kitura的Server Side Swift入门

服务器端Swift在iOS开发社区中正在蓬勃发展,现在是时候打破其他编程语言和框架的束缚,并以我们心爱的Swift语言实现一切。 有几种服务器端Swift框架可用,但最受欢迎的三个框架如下: 汽 Kitura 完善 有时我介绍了Vapor框架。 这篇文章讨论了如何开始使用Kitura,Kitura是IBM的服务器端Swift框架。 先决条件: Xcode 8或以上 斯威夫特3.0 使用Swift Package Manager安装Kitura软件包: 第一步是使用Swift Package Manager安装Kitura软件包。 在此之前,您需要初始化Swift Package Manager。 创建一个名为“ hello-kitura”的文件夹,然后使用终端进入该文件夹。 一次,在文件夹中初始化Swift软件包,如下所示: 运行“ swift build”命令来构建代码,如下所示: 构建完成后,您可以使用以下命令运行可执行文件。 世界您好! 当您执行代码时,它将在“ main.swift”中运行所有代码。 如果打开“ main.swift”文件,则会发现以下代码行。 打印(“ Hello World”) 这确认您的包已成功初始化。 现在打开您的Package.swift文件,其中包含您需要在应用程序中使用的所有软件包。 默认情况下,Package.swift将包含以下代码行。 导入PackageDescription 让包=包( 名称:“ hello-kitura” ) 如此,您可以看到Package.swift文件没有引用任何包或依赖项。 让我们对其进行修复,并添加对Kitura项目的依赖。 除了Kitura,我们还添加了对HeliumLogger的依赖。 HeliumLogger用于记录从Kitura生成的事件,对调试请求非常有帮助。 对Package.swift文件进行上述更改后,跳至终端并运行以下命令。 快速构建 这将触发构建并下载Package.swift文件中包含的所有依赖项。 一切完成后,您可能会看到类似以下内容的内容。 最后一步是生成Xcode项目,以便您可以在自己喜欢的编辑器中开始使用Kitura应用程序🙂 迅捷包generate-xcodeproj 这将生成Xcode项目。 您可以使用以下命令从终端打开Xcode项目。 […]

在Swift中以函数方式计算两个数组的差

本周,我遇到了我的朋友MateuszMaćkowiak提出的挑战,以解决他创建的diff函数中的问题。 给定两个数组,他的目标是检索: 通用元素:两个数组中的元素。 插入的元素:不在第一个数组中但在第二个数组中的元素。 删除的元素:不在第二个数组中但在第一个数组中的元素。 不过有一个陷阱。 元素不可比较,也不可等于 ,并且第一个数组的元素可能与第二个数组的类型不同。 但是,该函数将接收compare闭包,该闭包从第一个数组中获取一个元素,从第二个数组中获取一个元素,并告诉它们是否相等。 他向我展示了他的解决方案: 输入数据为: 让a = [Int](0 … 1000) 令b = [Int](750 … 1500)

开始进行Swift编程第14部分-错误处理

在上一篇文章中,我们讨论了泛型。 开始Swift编程第13部分-泛型 以前,我们介绍了类型别名,属性观察器以及“自我vs自我”。 medium.com 这是很难获得的信息,但这就是我们练习的原因。 仅仅因为我写了这个系列来进行教学,并不意味着这足以让您掌握所教的一切。 您可能从我的一篇文章转到另一篇相关文章,但我不会反对您。 事实上,我鼓励您继续从不同的来源学习。 我感谢通过阅读和/或鼓掌阅读每篇文章的人们所表现出的忠诚度,但我的首要目标不是要获得人气。 这是为了确保当您完成我的一篇文章时,您学到了一些新知识。 无需赘言,我们开始。 您是否曾经去过厨房准备食物并意识到没有干净的盘子? 您有几种选择: A.放弃晚餐 B.到餐厅去,或者 C.洗碗,然后在家修理晚餐 这些决定不仅影响您,而且影响您所喂养的人们。 选项A是最简单的解决方案,但每个人都饿着肚子,看着你成为晚餐的救星。 选项B也很容易,但价格昂贵,需要做一些不必要的额外工作,而且味道并不总是像家庭自制菜那样好。 选项C是一条艰难的道路,但如果您希望自己的食物品尝到自己想要的口味而又少有抱怨,并且希望没有破损的菜肴,那它就是最好的解决方案。 那么,所有这些与错误处理有什么关系? 一切! 当您决定尝试晚餐时,您调用了一种方法。 那么我们如何抛出错误呢? 可以通过在函数声明中的参数之后附加throws来引发错误。 但是,如果我们想从抛出函数返回错误字符串怎么办? 我们有一个选择,我之前已经暗示过。 为我们提供了针对Apple的所有错误的localizedDescription ,但它不仅神奇地读取了文本fileOpenError并提出了“无法打开文件”文本。 我们必须告诉它要提供什么。

Swift编程:模块化更好

通过模块化代码库满足单一责任原则。 我们通常会在很短的时间内开发一个应用程序,但是非常复杂。 为了达到交付目标,最好使用一些pod依赖项。 SJProgressHUD曾经是模块化的依赖项,用于显示Cocoapods上可用的弹出窗口或加载过程。 替代者是SVProgressHUD,MBProgressHUD,JQProgressHUD。 例如,让我们选择SJProgressHUD。 我们可以在每个地方附加SJProgressHUD.show() ,例如UIViewController类,AppDelegate类,Presenter或Controller(如果使用的是MVP / MVC),也可以附加在Model类中。 一切正常,但我们违反了软件开发原则:请勿重复。 如果我们将其放在模型上,则另一个问题是违反单一责任。 该模型不负责显示进度视图。 如果我们未能在模型类和视图类之间定义边界,那么由于零件之间的紧密耦合,下一个问题将会严重。 您的意大利面条代码必须重构。 有许多解决方案可以对其进行重构。 首先,我们从UIViewController创建一个扩展类。 在扩展文件中,添加一些将用于处理加载视图的函数,例如showLoading() , showError()和showSuccess() 。 导入SJProgressHUD 类UIViewControllerExtension { 扩展UIViewController { func showWaiting(消息:字符串){ SJProgressHUD.showWaiting(消息) } func showError(消息:字符串){ SJProgressHUD.showError(消息) } } } 创建扩展后,只要在UIViewController上,我们都可以从任何地方调用showWating(“getting doctors, please wait…”) 。 让我们看一下问题,实际上并不是UIViewController的所有派生类都需要知道这一点。 例如,我们的AboutVC仅显示应用程序版本。 //无需导入SJProgressHUD 类AboutVC:UIViewController { func viewDidLoad(){ } func viewWillAppear(){ //这里很神奇… wa可以在每个UIViewController的任何位置调用它。 //但是幸运的是AboutVC不需要了解它。 showWaiting(“请稍候…”) […]

为iOS应用程序打造反光工厂– Vincent Pradeilles –中

非常感谢 BenoîtCaron 引起了我的注意,并提出了我将在下面描述的技术的相当一部分。 iOS应用程序是复杂的软件。 如今,不太可能运行到聚合了一百多个视图控制器的应用程序中。 当您考虑到其中的某些可能只能通过特定的业务场景访问的事实时,通常会遇到这样的情况:在屏幕上显示特定的控制器非常困难。 这种情况可能会威胁到应用程序的质量,尤其是在要求开发人员检查每个屏幕(例如,确保它们在iPhone X上能正常工作)的时候。 一个非常方便的工具是调试视图,从中可以实例化任何控制器并将其显示在屏幕上。 那么我们如何实现这样的工具呢? 一个好的起点 第一步是弄清楚如何实例化任意控制器。 幸运的是,这将成为简单的部分,因为该功能已经通过Foundation的public func NSClassFromString(_ aClassName: String) -> Swift.AnyClass? 基本上,再加上一些代码,开发人员可以从其类的名称实例化一个对象。 所以现在我们只需要在我们的应用程序中列出所有视图控制器。 如果没有其他选择,我们可以将它们手动存储在.plist文件中,但是这种方法的缺点是每次创建,删除或重命名类时都需要手动更新,这很繁琐且极易出错。 利用Objective-C运行时 您可能没有意识到这一点,但是每个iOS应用程序都在轻量级运行时环境上运行。 关于此运行时,可以说很多话,如果您想详细了解它,请随时查看Apple提供的文档。 就本文而言,我将解释限于以下事实:iOS应用程序启动时,其所有与Objective-C兼容的类都在运行时加载,并且只要应用程序处于活动状态,它们就会一直存储在该位置。使此运行时成为从中检索所有视图控制器列表的绝佳来源。 我们如何在实践中实现这一目标? 首先,我们从导入与运行时交互的API开始: 处理更高级的用例 我们所取得的成就非常好,但是在大多数情况下,使其真正有用仍然很简单。 当您考虑它时,我们能够实例化视图控制器,但是我们无法为它提供任何类型的初始数据。 在一个现实世界的项目中,这个问题很可能会导致交易中断,因为许多视图控制器可能依赖于先前屏幕传递的一些初始数据。 那么我们如何改善呢? 首先,我们需要一种让控制器提供其用例列表并处理其中一个用例的方法。 为此,我们声明一个协议: 结论 自反编程是一个功能强大的工具,使用它的这个特定实例也不例外:只需几行代码,我们就可以组建一个易于包含在现有应用程序中的工厂,并允许其开发人员实例化任何从一个好的调试视图中查看控制器。 当确保旧版应用程序在iPhone X上流畅运行时,无疑会令人欢迎的工具是这样的工具,但是当您想要对该应用程序的一部分进行非回归测试时,它也很方便。令人讨厌的复杂。 如果您想在项目中使用以上代码,请随时在我的GitHub上使用。

有效地使用第三方库#decoupling

我最近读了我的一位同事的推文,说: “我们应该以更容易删除功能的方式设计类! 这表明事情真的脱钩了” 每次将第三方SDK /库添加到项目中时,请查看是否可以为其添加包装,并在应用程序中使用该包装。 这使您可以灵活地更改或更新库,而无需将来进行大量更改。 让我们来看看我们在上面讨论的情况下该如何做。 因此,我们将创建一个包装器(我们将其称为MAAnalyticsManager),这就是它的外观 现在,无论何时需要跟踪页面视图或事件,都可以直接在包装器或管理器上调用该方法,而不必直接调用MixPanel。 而且,如果以后需要更改为其他Google Analytics(分析)SDK,则只需更改一个文件即可。 那不是很棒!!

Swift 4中的编码和解码

我知道我知道你一定像Swift 4 WTF! 不用担心,Swift 4尚未发布,但是您仍然可以使用Swift开发快照来体验Swift 4的功能。 如果您有兴趣安装Swift 4快照,请查看此链接。 有许多不同的方案,您要将类转换为数据表示形式。 一个非常普遍的需求是当您想将JSON数据作为HTTP正文发布时。 最常见的方法之一如下所示: JSONSerialization类负责返回Data对象,然后可以将其作为HTTPBody传递给请求。 Swift 4中的JSONEncoder和JSONDecoder Swift 4引入了JSONEncoder和JSONDecoder类,它们可以轻松地将对象转换为编码的JSON表示形式。 查看以下示例: 注意,使用了新的Codable协议,该协议使Language结构可编码和可解码。 更高版本的JSONEncoder类用于通过使用encode函数执行编码。 就像编码一样,解码也非常简单,如以下代码所示: 很简单吧! 通过使用协议和扩展,我们甚至可以使它更简单。 让我们创建一个自定义的Serializable协议,它将为我们执行编码。 可序列化 使用JSONEncoder和JSONDecoder很好,但是我们当然可以使它更无缝地执行编码和解码。 代替创建JSONEncoder的实例,类或结构应该能够自己编码。 看一下下面的Serializable协议,所有对编码感兴趣的模型都可以遵循该协议。 代替在每个类或结构中分别实现序列化功能,我们将使用协议扩展的功能来创建默认实现。 上面的代码将给您以下错误: 游乐场执行失败:错误:MyPlayground.playground:8:36:错误:参数类型“ Self”与预期的类型“ Encodable”不符 返回尝试? encoder.encode() 问题在于“自我”不是可编码的。 我们可以通过使Serializable协议符合Codable协议来轻松解决此问题,如下所示: 现在,您可以使用新的Serializable协议轻松编码模型,如下所示: 确保您的语言模型符合“可序列化”协议而不是“可编码”协议。 我相信,在构建依赖于网络服务并发布编码数据的应用程序时,Swift 4中的这些新进步将真正使开发人员受益。 我可以担任高级iOS开发人员。 如果您有兴趣,请在此处查看我的简历。 如果您喜欢这篇文章,那么您可能会对我的课程“ iOS精益控制器的完整指南 ”感兴趣。 本课程涵盖许多有用的架构模式,以构建更好的iOS应用程序。 享受74%的折扣,请单击以下链接: https://www.udemy.com/a-complete-guide-to-lean-controllers-in-ios/?couponCode=MAKEMELEAN