Tag: swift

Swift中的枚举

在Swift中,我们具有一流的类型:类,结构,协议和枚举。 这样,我们就可以在拥有清晰可读的代码的同时创建令人惊奇的事物。 本文将为您介绍以下主题:何时使用枚举,其语法,枚举的类型,对其进行迭代,枚举的属性和方法,关联值以及比较枚举。 希望您是口袋妖怪迷。 何时使用枚举 如果需要对相关值进行分组,则可以使用枚举。 在下面的示例中,我们将创建一个Pokemon类并定义“ Type”。 (请注意,代码中的Type称为Kind) 神奇宝贝课程 { /// Pokedex号 让指数:整数 ///宠物小精灵的名字 变量名称:字符串 初始化 (索引:整数,名称:字符串){…} } 我们的Pokemon类是用pokedex编号 (索引)和name属性设置的。 我们要添加类型(火,草,水等)属性。 我们可能会考虑使用结构来定义类型。 宠物小精灵扩展名 { struct Kind { //类型名称 变量名称:字符串 } } 但是我们对这种方法有疑问。 1.我们允许任何字符串成为神奇宝贝类型 2.比较变得复杂 让 pokemonElectricType = Pokemon.Kind(name:“ Electric”) 让 pokemonElectric2Type = Pokemon.Kind(name:“ Electric”) //这不起作用😬 打印(pokemonElectricType == pokemonElectric2Type) //检查字符串var“ name”起作用 打印(pokemonElectricType.name == pokemonElectric2Type.name) //这不可能 […]

使用Swift介绍Firebase

我是为AppCoda.com编写的。 您可以在以下网址找到完整的教程:https://www.appcoda.com/firebase-login-signup/。 自从Parse开始关闭以来,已经有一些数据库试图替代用于移动应用程序的Parse,例如Firebase和Realm。 Firebase由于其易用性和速度而成为当前最受欢迎的一种。 它还可以与Android,Web和iOS一起使用,这意味着它对于大型项目非常有用,因为数据库可以跨所有主要设备进行连接。 Firebase由Google拥有,这意味着这些服务器非常可靠,并且在需要时可以提供大量帮助。 一些大型科技公司(例如PicCollage,Shazam,Wattpad,Skyscanner和其他大型初创公司)也使用Firebase,因此您可以了解Firebase的可靠性。 随着Firebase的最新更新,它变得比以往任何时候都更加强大和强大。 您可以使用AdMob在平台上赚钱,也可以通过使用通知来保持用户忠诚度,或者使用云消息传递和存储来制作功能非常强大的应用。 Firebase肯定会留在这里。 在本教程中,我们将研究其中的一个关键方面,即登录和注册。 我们还将研究重置用户密码。 我们将使用最新版本的Firebase和XCode以及Swift3。在本教程中,您需要对Swift和XCode有基本的了解。 我们需要做的第一件事是开始一个新的XCode项目,我将使用“单一视图”应用程序,但是该概念将适用于从Tab-Bar应用程序到Master-Detail应用程序的任何样式。 您可以随心所欲地调用该项目,但对于本教程,我将其称为FirebaseTutorial1 。 将语言设置为Swift,设备无关紧要,因此您可以保持通用性。 然后,您需要转到Main.storyboard并创建如下界面: 但是,为了节省时间并让您专注于学习Firebase,可以在此处下载starter项目,并且在情节提要完成后,外观应类似于此,文件也应具有此外观。 如果您想从头开始构建项目,则必须遵循以下视图控制器和过程: 1.首先,将三个视图控制器拖到情节提要中,然后向每个视图控制器添加两个按钮。 这两个按钮用于在不同的视图控制器之间导航。 假设您在登录页面上时,可以导航到重置密码页面或注册页面。 2.在两个视图控制器中,添加两个文本字段和一个按钮。 这些文本字段用于“电子邮件”和“密码”字段。 该按钮用于登录或注册。 在占位符中,将电子邮件或密码放在希望用户输入电子邮件和密码的位置。 然后,您可以更改背景的颜色,使其看起来更好一些,然后在顶部添加标签。 3.在第三个视图控制器(“重置密码”)中,添加三个按钮,一个文本字段和一个标签。 文本字段供用户输入用于重置密码的电子邮件。 4.完成UI的设计后,其余过程就是将按钮与其他视图控制器连接起来,以便用户可以在视图之间进行转换。 在这里,我建议您对segue使用“模态呈现”。 现在用户界面已经准备就绪,我们现在将项目与Firebase集成在一起。 为此,您首先需要转到https://firebase.google.com/并在Firebase中设置项目。 假设您已使用Google帐户登录到Firebase,请单击“免费入门”,然后选择“创建新项目”。 它将带您到一个为您的项目命名的屏幕。 随便命名项目,然后选择您的所在地。 Firebase为您创建新项目后,将带您进入概述。 您可以在此处选择应用程序平台,无论是Web,Android还是本例中的iOS。 您也可以在这里找到文档,并在侧面访问身份验证,存储,数据库等等。 现在选择“将Firebase添加到您的iOS应用程序”,然后将提示您输入iOS Bundle ID 。 这是您的Xcode项目的包标识符(请注意,您的包ID可能与我的不同)。 确保您正确输入了捆绑包ID,并且可以选择为应用程序选择一个昵称。 如果您的应用程序已经在App Store上发布,则添加您的App Store ID。 但是对于此演示,您不必执行此操作。 完成后,单击“添加应用”继续,Firebase将为您生成一个名为GoogleService-Info.plist的文件。 它应该自动下载到Mac计算机上。 这将带您进入下一个阶段。 按照说明将GoogleService-Info.plist拖动到Xcode项目的根文件夹中。 […]

在macOS上创建菜单栏应用

菜单栏应用程序是指位于macOS菜单栏(即状态栏)上的应用程序。 它提供对关键功能的即时访问,以及在登录会话期间始终可访问的功能。 创建状态栏项目 我们使用NSStatusBar.system().statusItem(withLength: -1)从系统请求状态栏项目。 请注意,如果状态栏已经包含许多其他状态栏项目,则可能会失败(返回nil)。 成功获取状态栏项后,您将获得一个NSButton作为要放在菜单栏上的UI元素。 您需要通过提供图像以及设置按钮的目标和操作来对其进行配置。 所有这些都应在应用启动期间完成,因此在应用委托中,我们具有: 请注意,必须使用强引用来保留系统返回的状态栏项目对象。 否则,它将在以后释放,并且菜单栏上将不会显示任何内容。 显示菜单 要显示菜单,您需要提供放置菜单对象的参考点,在这种情况下为状态栏按钮。 然后,我们创建一个鼠标事件,并使用popUpContextMenu(_:with:for:)出菜单。 信息清单设置 如果您的应用程序仅是菜单栏(类似于Dropbox macOS客户端),则需要在Info.plist中设置Application is agent = YES ,以便省略Dock的应用程序图标和左上角的应用程序菜单。 下载样例项目

我的第一个GitHub项目:方法

关于如何为您的第一个GitHub项目做出贡献的步骤 因此,您已经决定要开源 经过同仁的压力和FOMO,您已经决定要尝试这个GitHub贡献的东西,并选择了一个值得您的才华的项目。 这篇文章描述了开始GitHub之旅所需采取的步骤,以及如何继续进行下去。 步骤1:叉 好的,您已经在GitHub上选择了一个开源项目,并希望对此做出贡献。 让我们来 kgellci / Area51 适用于iOS的开源Reddit客户端完全内置于Swift中– kgellci / Area51 github.com (顺便说一句,如果您想磨练您的Swift语言和iOS SDK技能,则是一个完全rad开源的iOS项目)作为您想要的开源项目。 从哪里开始? 好的,首先,您需要分叉该项目。 这是什么,它将在您的 GitHub个人资料中以您的名字创建该主存储库(kgellci / Area51)的副本,如下所示:https://github.com/yourusername/Area51/。 您所需要做的就是,转到所需的项目存储库,然后单击“ Fork”按钮,如下图所示。 然后,GitHub会告诉您它正在以您的名字创建一个新的存储库,大约需要30秒才能完成该过程。 和瞧! 您拥有第一个分叉的存储库。 第2步:克隆 现在,您已经有了代码库,可以开始编码了。 接下来要做的就是在本地计算机上克隆存储库。 转到您的存储库(https://github.com/yourusername/Area51/),然后单击“克隆或下载”按钮,如下所示。 2. GitHub将打开一个带有HTTPS URL的小弹出窗口,格式为:https://github.com/yourusername/Area51.git。 复制该链接。 注意:如果选择复制SSH URL链接,则可能需要为本地计算机设置SSH密钥。 要了解如何执行此操作,请转到以下链接:https://help.github.com/en/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent 3.然后,打开您的终端并将目录更改为所需的位置。 4.键入git clone https://github.com/yourusername/Area51.git并按Enter。 Git将在您指定的位置创建您的项目的本地克隆。 步骤3:提交 这是该过程中最简单的步骤。 您现在所需要做的就是编写代码。 您可以打开项目的本地克隆并进行所需的更改。 然后,提交更改并将更改推送到远程存储库(https://github.com/yourusername/Area51/)。 注意:提交更改时,请记住添加结构化提交消息。 您可以在这里找到一些有关构造提交消息的有用指南:https://chris.beams.io/posts/git-commit/ 第四步:公关 好的,现在,您的更改已存在于存储库中。 接下来要做的是将您的更改发送到主存储库(https://github.com/kgellci/Area51/),以便将其集成到主代码库中。 为此,您需要做的就是打开一个请求请求。 […]

Swift解决方案:网桥

我想请您注意抽象汉堡包及其作为餐食的具体实现。 假设我们要添加一个新汉堡,您需要创建多少个其他类? 如果回答三个,那将是正确的: 两个层次 这是不直观的,但是避免这种混乱的解决方案是创建两个单独的层次结构。 这是定义在声明时的含义: 桥接模式将抽象与其实现分离开来…… “抽象”是指基类或协议。 在我们的示例中,它涉及各种汉堡类。 这些汉堡包不会被实例化,因为餐厅不会单独出售它们。 必须使用实现将它们分类为一顿完整的饭菜才能使用。 “实施”是指我们在将汉堡包加入餐边后制作的餐食类。 因此,我们将汉堡包(抽象)与餐食/面食(实现)分离,并剩下两个类层次结构。 层次结构之间的桥梁 然后定义继续说: 桥接模式将抽象与其实现分离, 以便两者可以独立变化。 现在我们有了两个单独的层次结构,我们需要一种连接两者的方法。 为此,我们为每个Burger赋予Side类型的属性。 这种“具有”关系是连接两个层次结构的“桥梁”。 我们这样做是为了使两者可以独立变化。 换句话说,我们不再需要为汉堡和面包的每个组合创建一个类。 由于它们的层次结构是分开的,因此每个新汉堡或一面只需要一个新类。 这一切似乎有点抽象,所以让我们回到代码中进行演示。 编码解决方案 我们需要针对设备和音频类型的单独层次结构。 让我们从音频类型开始: protocol AudioHandling { func handle(audio: Audio) -> Audio } class AudioEncryptor: AudioHandling { func handle(audio: Audio) -> Audio { // Encrypt and return Audio } } class PlainAudioHandler: […]

使用面向协议的编程进行通用JSON解析

澄清 : Codable,本文是关于实现可与Codable或您可能选择的任何东西一起使用的体系结构的 每个(Swift)软件开发人员最终都将需要为其iOS应用程序(或macOS)解析JSON。 在我的整个职业生涯中,我已经看到了许多关于如何解析JSON的体系结构方法。 您应该经常问自己(开发的任何功能): 您构建的体系结构是否是一种演化系统,可以在不修改基础代码/类/结构的情况下适应任何给定的更改( 如果不是,则不敏捷 ) 。 如果您的方法基于OOP,您是否保持SOLID原则不变? 服务是否为松耦合? 在最近的一次聚会中,我也参加了有关体系结构方法和原理的会议,他们展示了一张带有引号的幻灯片: 开发人员知道可以做什么。 应该做的。 那么应该怎么做……? 让我们分解一下JSON解析,即解析JSON涉及的内容: 调用一个请求到服务器并从闭包中获得响应 (例如)。 在大多数项目中,服务器端以不同的合法性响应我们的请求,因此,我们需要一个验证器来验证JSON响应的合法性,而不管我们需要解析的实际数据如何。 4xx我们可以验证JSON,否则,我们将返回错误。 解析 JSON并反序列化相关对象 从验证器 返回相关错误 。 没什么新鲜的,简单明了的🙂 我们的主要目标是编写一个小型且集中的代码,以分离上述所有步骤,并且当然要使用POP方式( 面向协议的编程 )。 我是Alamofire的忠实拥护者,因此我们假设响应是标准的DataResponse : Alamofire.request(…)。responseJSON {(resp:DataResponse )in …} 我们需要一个协议,该协议将描述我们先前细分的方法集。 我们将需要3种方法: 封装运行整个“显示”的实际逻辑的方法。 验证JSON的方法-此方法将返回内部JSON(稍后将显示一个示例)。 一种将解析我们的数据并创建实际对象的方法,该对象应该位于内部JSON内部。 公共协议ParseProtocol { ? ? )-> 吗? 扩展ParseProtocol { ? } 那返回类型呢? 由于方法begin将封装“整个”逻辑,因此它应该返回我们解析的对象以及一个Error类型,然后返回一个元组如何: func begin(forResponse响应:DataResponse […]

在Swift项目中设置C库依赖关系(第2/2部分)

选项2:使用模块映射 T L; DR 第1部分 描述了如何使用公共标头在Swift项目中设置C库依赖项。 设置C库依赖项的更整洁的方法是使用模块映射。 第一步:创建一个快速项目 Xcode->新建->项目->可可触摸框架->语言:Swift->下一步。 我将项目命名为CDependencyTutorial2 。 第二步:设置项目依赖项 我有一个名为ExampleCLibrary的静态C框架。 将ExampleCLibrary.xcodeproj拖到CDependencyTutorial2项目中。 第三步:将C库设置为子模块 选择目标CDependencyTutorial2- >常规->链接的框架和库->添加libExampleCLibrary.a 。 转到CDependencyTutorial2项目的目录,创建一个文件夹,我将其称为CWrapper,在该文件夹内,创建一个文件,并将其称为module.modulemap 。 该路径应该是您的 C标头的路径。 选择目标CDependencyTutorial2- >构建设置->导入路径 ->在modulemap的目录中键入。 对我来说是: 第四步:现在在swift项目中使用它。 选择CDependencyTutorial2项目,添加一个新的swift文件。 让我们写一些代码。 randomString是C库中的一个函数,现在可以在Swift中识别。 是的,😀成功! 简介:为了能够在Swift项目中使用C库,主要有两个步骤:在文件夹中创建module.modulemap , 导入路径应指向模块映射目录。 在第1部分中,如果我使用public标头方法,则C标头也将公开。 使用这种方法,我们就没有这个问题。 我对这种解决方案感到非常满意。 😀 您是否要下载项目? 请点击这里。 所以你怎么看? 想和我讨论吗? 这是我的推特:@humlelu。

Swift —可选的初始化

因此,您正在尝试使用可选常量创建自己的类吗? 谜 如果您是像我这样的Swift菜鸟,那么第一次尝试在类中使用一些Optional类型常量创建Swift类时,就会遇到此错误。 现在,您可能会说:“等等,我从未遇到此错误,因为我总是像所有理智的人一样初始化所有的类属性。” 啊哈! 我亲爱的想象中的理想程序员,最初的挫败感是这样的。 在Swift中必须启动其他所有类型的原因是,否则它们将具有nil值。 但是,Swift中的Optional类型可以为nil 值,我们在代码中按原样处理它们。 因此,我的推论是,Swift中的Optional类型应该可用而无需初始化。 另外,如果您使用可选类型变量而不是可选类型常量 ,则代码将完美编译,如下所示。 那么这是怎么回事? Swift为什么让我们使用未初始化的Optional类型变量而不是常量? 处理Optional类型时,Swift变量和Swift常量之间有什么区别? 揭示 变量和常量之间存在差异的原因是,Swift 变量可以隐式处理显式设置的值,而Swift 常量 每次都需要显式设置其值。 Swift中的每个类型(例如String,Int,Bool等), 除了Optional之外,都具有显式的 .None值。 但是Swift中的Optional类型具有隐式 .None值。 这意味着,对于Swift中的任何变量或常量(Optional除外),该值将显式设置为.None ( nil )。 但是,对于Swift中的任何Optional变量或常量,该值均隐含为 .None ( nil ),即,该值可以为nil但并不总是nil 。 现在,如上所述,Swift中的变量知道如何处理值的显式和隐式分配。 因此,一个类变量可以从Optional类型推断其初始值,即.None 。 但是, 常量不知道如何处理隐式值,因此无法从Optional类型推断出它的初始值(需要明确地说,“这是您的初始值”)。 结论 Swift中的类变量无需初始化即可处理Optional类型(因为它们可以处理隐式.None值),但是Optional类型的类常量将始终必须被初始化(因为它们无法处理隐式.None值,并且需要显式设置一个值)。 本文是在以下资源的帮助下撰写的: Swift可选的初始化 感谢您为Stack Overflow提供答案! 请务必回答问题。 提供详细信息并分享… stackoverflow.com 是nil和Optional。在Swift中没有相同的东西吗? 感谢您为Stack Overflow提供答案! 请务必回答问题。 提供详细信息并分享… stackoverflow.com

XCFit 7.0发布:XCTActivity,新的Xcode模板和多个CI服务支持

XCFit-7.0的新版本刚刚发布,具有一些新功能。 XCFit在版本6.0发行版中已经支持Xcode 9和Swift 4。 XCFit是Xcode for iOS应用程序中Xcode的面向全栈协议的BDD,使用Swift使用XCUITest。 XCFit允许我们使用诸如Give / When / Then格式的工具以人类可读的语言编写Swift的BDD样式API /合同级别,UI和验收测试。 在这篇简短的文章中,我们将看到XCFit-7.0的新功能。 此版本具有一些新功能,例如XCTActivity,新Xcode模板和持续集成服务支持。 我们将详细介绍以下新内容 XCTActivity支持 Xcode 9和XCTActivity支持的新Xcode模板 对XCFit的多个持续集成服务支持 UI测试通常是长时间运行的,并且在那里发生许多动作,例如,点击按钮,滑动等。到目前为止,XCTest报告显示了测试报告中的所有动作,这些动作不是特别可读。 活动是通过提供有意义的名称来将这些操作组织到组中的方法,因此XCTest结果将在结果中使用该活动名称以使其更具可读性。 您可以在此处阅读有关Apple官方文档的更多活动。 我们可以将活动分散到任何一组操作上,例如以干净状态启动应用程序 XCTContext.runActivity(名称:“鉴于我已经以干净状态启动了应用程序”) XCUIApplication()。launchArguments = [“ -StartFromCleanState”,“ YES”] XCUIApplication()。launch() } 当我们运行测试时,然后在测试报告中,我们将看到“鉴于我已经以干净状态启动了该应用程序”,因此更具可读性。 我们仍然可以通过扩展活动来访问基本操作。 XCTActivity现在支持XCFit预定义步骤。 现在,所有步骤都包装在XCTActivities中,以便可以读取Xcode报告。 您将在本文结尾的演示视频中看到这一点。 如果您使用过XCFit,那么您可能知道XCFit提供了Xcode模板,以开始使用Xcode中的面向协议的BDD。 可以使用Rubygem安装XCFit模板 $ gem install xcfit 如果您正在使用系统(预安装)Ruby(2.0),则可能需要使用sudo。 XCFit gem将用于为Xcode设置所有Xcode模板。 当前的Xcode模板具有Xcode组结构,如下所示 Feature.swift 该文件具有您的功能,它将所有可以作为验收测试实现的需求(测试)。 该文件包含Swift协议。 FeatureSteps.swift 该文件包含模板代码,该模板代码如何在功能协议之上使用Swift扩展实现给定功能的步骤定义。 它还提供了一些示例,这些示例在实现步骤定义时如何使用XCTActivity。 FeatureElements.swift 该文件包含与功能有关的所有XCUIElement。 […]

iOS和Swift Universe中的访客设计模式

(本文最初是用俄语撰写的,并在此处发布。) 访客是由四人帮(GoF)在其经典著作“设计模式:可重用的面向对象软件的元素”中描述的行为设计模式之一。 简而言之,当需要对一组不同类型的对象执行一些类似的操作时,此模式可能很有用。 或根据对象的特定类型执行操作,而不知道该类型。 换句话说,模式可以通过添加相似或具有相同来源的操作来扩展一组类型的功能。 而且,类型结构和实现不会改变。 当然,最简单的解释方法是通过示例说明其用法。 无论如何,我想修正一个事实,即所提供的所有示例和代码段并非取自我的工作经验,而是出于学术目的。 即,本文试图使您熟悉一种 面向对象的技术, 而不是讨论要解决的特殊问题。 我想说的第二件事是,这里的所有代码都是为了更好地理解而结构化的,并且可能存在各种甚至明显的缺陷。 例 假设我们有一个UITableViewController ,它使用了几个UITableViewCell子类: ClassCell类:UITableViewCell {/ ** /} SecondCell类:UITableViewCell {/ ** /} class ThirdCell:UITableViewCell {/ ** /} TableVC类:UITableViewController { 覆盖func viewDidLoad(){ super.viewDidLoad() tableView.register(FirstCell.self, forCellReuseIdentifier:“ FirstCell”) tableView.register(SecondCell.self, forCellReuseIdentifier:“ SecondCell”) tableView.register(ThirdCell.self, forCellReuseIdentifier:“ ThirdCell”) } 覆盖func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)-> UITableViewCell { / ** /返回FirstCell() / ** /返回SecondCell() […]