Tag: swift

面向协议的UITableViewCells

这篇博客文章展示了如何通过使用面向协议的编程 (POP)作为子类化或组合的更好替代方法来实现一组UITableViewCell变体。 准备? 我们走吧! 给我看看细胞! 在构建我的Cast Player应用程序时,我需要添加几个设置页面,以允许用户在应用程序中进行一些调整,并包括指向“发送​​反馈”表单和一些“关于”屏幕的链接。 这是最终结果: 从上面的屏幕中,我们可以识别六种不同类型的单元格: 总体而言,这些细胞具有以下特征(或行为): 单元格突出显示 显示标题 显示人类可读的字节数 我们如何去建立一组能很好地代表这六个细胞变异的类呢? 第一步是列出网格中的所有单元格类型和所需特征: 从上表可以看出: 所有细胞都没有采用这些特性。 一些特征是某些细胞所必需的,而其他细胞则不需要。 这意味着构建UITableViewCell类层次结构在这里无法正常工作。 实际上,这些单元格类型都不是基础类的理想选择。 该怎么办? 🤔 协议和扩展! 好极了! 幸运的是,这篇关于Swift 2.0中Mixins和Traits的精彩文章可以为我们指明正确的方向。 直观地讲,协议和扩展对于该用例确实可以很好地工作,但是如何在此处正确使用它们呢? 这个想法是我们可以使用协议为每个特征定义接口 ,并提供带有扩展的默认实现 。 然后,我们可以创建非常小的UITableViewCell子类,并使它们仅符合所需的协议。 在另一个名为“面向协议的MVVM简介”的精彩演讲中,探讨了一个非常类似的问题。 让我们看看它是如何工作的! 有了协议和扩展,我们可以编写第一个特征TitlePresentable : 在代码中,这表示为: 注意 : HighlightableTableViewCell是通过子类实现的唯一特征,并且可以用作三种其他单元格类型的基类。 一旦为给定类型选择了基类,则只能通过协议扩展来添加其他特征。 结论 使用Swift协议和扩展作为增加行为(特征)的一种方式,可以在我们的类的设计中取得重大胜利,并有助于保持层次结构的平坦。 🚀主要优点: class媚的阶层阶层 生成的API /类可以更轻松地扩展 与添加和删除代码相比,添加和删除协议一致性更容易 减少代码重复 欢迎反馈 这篇文章中介绍的解决方案对我和我的特定用例都非常有效-我希望这个实际示例可以帮助我比起初时更好地理解如何使用协议扩展。 如果您知道这样做的更好方法,请在评论中告诉我! 注意 :这篇文章首次出现 在 2016年6月18日发布的 […]

Swift中的设计模式:第二部分-行为设计模式

在该系列的第一篇文章中,我讨论了创意设计模式。 现在,我将描述另一组称为行为设计模式的模式。 行为设计模式处理对象之间的交互方式。 它描述了对象之间如何进行通信,以及如何在不同对象之间破坏任务的步骤,从而提供了更大的灵活性并使得代码更具可测试性。 让我们跳到以下10个行为设计模式: 1.责任链 责任链是一种行为设计模式,可让我们在一系列处理程序之间传递请求,其中每个处理程序都决定处理请求或将请求沿着处理链传递。 有一个名为“ 级别”的枚举将“体育”管理细分为三个级别:州,国家和国际。 首先,让我们创建一个名为Sports的类,它将仅保留当前的体育管理水平。 然后,我们有了称为GameManagement的协议,该协议可以沿处理程序链传递责任。 StateSportsTeam , NationalSportsTeam和InternationalSportsTeam类实现了此协议。 如果运动级别不属于他们的管理层,他们会将责任转移给更高的管理层(或管理人员链)。 在操场上运行代码: 让 stateSportsTeam = StateSportsTeam() 让 nationalSportsTeam = NationalSportsTeam() 让 internationalSportsTeam = InternationalSportsTeam() stateSportsTeam.nextLevelManagement =国家运动队 nationalSportsTeam.nextLevelManagement = internationalSportsTeam let sports1 =体育(级别:Level.international) stateSportsTeam.manage(sports:sports1) let sports2 =体育(级别:国家级) stateSportsTeam.manage(sports:sports2) let sports3 =体育(等级:Level.state)stateSportsTeam.manage(体育:sports3) 输出: 由国际体育管理公司管理 由国家体育总局管理 由国家体育总局管理 2. 命令模式 在命令模式中,将执行命令的类(称为Invoker )与产生命令的类( ConcreteCommand )和知道如何执行该命令的类( Receiver […]

核心数据iOS Swift

2.创建项目后,您将获得“ CoreData.xcdatamodeld”,我们将创建模型实体和其他用途。 3.单击CoreData.xcdatamodeld创建一个实体。 点击“添加实体”按钮创建实体。 4.添加属性 现在,我们有了Entity和attribute,所以让我们开始将数据添加到Core Data中。 #将数据添加到核心数据 func saveData { 卫队让appDelegate = UIApplication.shared.delegate为? AppDelegate else {返回} // 1 让managedContext = appDelegate.persistentContainer.viewContext // 2 让实体= NSEntityDescription.entity(forEntityName:“ YourEntityName”,在:managedContext中)! 让person = NSManagedObject(实体:entity,insertInto:managedContext) // 3 person.setValue(nameValue,forKeyPath:“名称”) person.setValue(ageValue,forKeyPath:“ age”) // 4 做{ 尝试managedContext.save() people.append(人) let alert = UIAlertController(标题:“成功”,消息:“保存成功”,preferredStyle:UIAlertController.Style.alert) alert.addAction(UIAlertAction(title:“ Ok”,样式:UIAlertAction.Style.default,处理程序:nil)) self.present(警告,动画:true,完成:无) }将let错误捕获为NSError { //打印(“无法保存。\(错误),\(错误.userInfo)”)} } #从核心数据中检索数据 func getData(){ var […]

构建旅行照片共享iOS应用

你好! 我想向您展示如何构建相对简单的照片共享应用程序:将您的图像放置在当前位置的地图背景上。 您还可以添加一条短消息和您的姓名,以得到如下所示的图像(这样,您就可以将自己在很棒的假期中所拜访的东西吹嘘给朋友): 要遵循本教程,您需要一台装有xCode的Apple计算机和一个Apple开发者帐户。 创建项目 打开xCode并创建一个名为PicTravel的新项目。 选择“ 单一视图应用程序”模板: 给项目起一个名字,我们选择了PicTravel但是您可以选择其他喜欢的名字。 还要填写项目的组织名称和组织标识符: 最后一步是将新创建的项目保存在Developer文件夹中。 建立介面 在左侧面板中,打开Main.storyboard 。 这是我们构建应用程序界面的地方。 从右侧面板的底部拖动ImageView并将其放置在场景的中心。 调整其大小,使其覆盖所有内容(将其捕捉为出现的蓝线)。 如下图所示,使用约束对话框将ImageView固定到场景边距: 我们将使用它为应用程序的主屏幕放置背景图像。 从此处下载背景图像,然后从左侧面板中打开Assets.xcassets项,单击底部的“ +”按钮,然后添加一个名为Background的新图像集。 将下载的图像拖到“ 1x”占位符上,以得到这样的结果(在本教程中,我们将不使用“ 2x”和“ 3x”占位符,但是如果需要,可以为其添加更大分辨率的图像)。 现在,回到Main.storyboard ,选择ImageView ,然后从Attributes Inspector中选择Background图像,然后将Content Mode设置为Aspect Fill 。 现在是时候将新图像添加到我们的资产中,用于将要添加的“拍照”按钮了。 从此处下载图像,在Assets.xcassets中创建一个名为Button的新图像集,然后将图像拖动到1x占位符中,就像我们之前在背景中所做的那样。 接下来,在Main.storybord ,将一个按钮拖动到场景的中心。 将“ 类型”设置为“ Custom ,清除“ 标题” ,并将“ 背景”设置为我们刚刚创建的“ Button图像。 从“ 大小”检查器中 ,将的按钮设置为,并将高度设置为115 。 为按钮的with和height添加两个新约束(每个115),然后从Alignment Constriants中将按钮在容器中水平和垂直对齐。 现在,我们为用户的名称和消息添加两个文本字段。 如下图所示,将它们放置在下面的约束中。 不要忘记蓝色的指南,这些指南使您更容易放置。 要在两个元素之间创建约束,可以按住Ctrl键并拖动到另一个,然后从出现的弹出窗口中选择所需的约束类型。 对于消息文本字段: […]

使用Firebase Cloud功能实施DeviceCheck

(这不是教程) DeviceCheck是iOS 11引入的,它使开发人员可以检查用户是否处于四个自定义状态之一。 所有状态均由开发人员决定。 引入DeviceCheck是为了允许开发人员在所有开发人员的应用程序中正确识别和分类其用户,而无论用户是否删除了他们的任何应用程序。 有许多用途,但通常与货币化和社交有关。 如果您提供应用内新用户交易并希望确保用户无法删除,重新下载和再次访问该交易,则DeviceCheck是您的解决方案。 如果您提供社交应用程序,并且想要确保违反您条款的用户无法长时间访问您的服务(直到他们获得新手机),DeviceCheck是您的解决方案。 在DeviceCheck之前甚至今天,开发人员将在Apple的视野中实施一般或高度可斥责的识别用户的方法,其中最大的例子是Uber直到2017年左右。 一般的解决方案之一是为每个用户使用唯一的,但不是永久的,有时甚至是不存在的广告标识符。 另外,一些开发人员会将信息存储在钥匙串中,但是一旦删除该应用程序,该信息就会被删除。 高度谴责实际上涉及访问每部电话的唯一IMEI /序列。 DeviceCheck已成为各方的完美答案。 它为开发人员提供了永久性,但确保了隐私,使Apple和用户都感到高兴。 开发人员在实施它时遇到的问题。 DeviceCheck要求与Apple的服务器通信,这意味着您必须拥有一台服务器才能完全实现它。 对于在大型公司以外工作的开发人员,花时间了解实施情况可能没有吸引力。 实际上,实施可以非常简单,并且无服务器。 对于我自己的项目(社交),我之所以坚持不懈,是因为用户的质量对于应用程序的成功是不可商议的。 所需的只是Firebase Cloud Functions,Firebase数据库和Node.js。 实施DeviceCheck所花费的大量时间涉及熟悉JavaScript,请求承诺和Apple的错误代码。 因为不仅在服务器之间,而且在数据库之间都会有很多来回回响,所以逻辑确实不是那么简单。 但是,一旦完成,这无疑会让您感到无比的成就。

知道如何进行单元测试的绝佳过程(您的Swift代码)

我将向您展示一种方法,该方法可以确定应测试的内容以及一些概念,使编写测试时的生活更加轻松。 在我职业生涯的某个时刻,我知道单元测试的重要性,但是我不知道如何测试代码。 许多人都面临着同样的问题。 我们阅读了有关如何开始的文章,但仍然很难将我们学到的东西应用到我们自己的代码中。 通常,我们没有那些仅对两个参数求和并返回结果的函数,我们在许多示例中都可以看到它。 好吧,我遇到了一个过程,这对我来说真的很容易。 我要说的第一件事是,您无需更改体系结构即可开始单元测试。 当某些开发人员听到某种结构可以使代码更具可测试性时,这是一个错误。 然后他们等到转移到这种新的编码方式开始编写测试。 让我们不要那样做! 如果要测试现有代码,则可能需要重构某些部分,但绝对不要更改您的体系结构! 消息是对象在面向对象的世界中彼此交谈的方式。 您希望对象执行方法时将消息传递给该对象。 获取属性值是相同的,并且适用于其他所有条件! 知道要测试什么的过程包含三个简单的步骤 ,并且都涉及消息。 1.确定消息的类型 消息有两种可能的类型:查询和命令。 这可能很明显,但是查询是当您要求某事时,而命令是当您告诉它要某事时。 查询具有返回值,但是在命令没有返回值时却不会更改任何状态,但是会产生一些副作用。 查询 =返回什么,什么也没改变 命令 =不返回任何内容并更改某些内容 2.标识消息的来源 一条消息可能有三个来源:传入,传出和发送给自己。 传入 :当一个对象从外部(另一个对象)接收到消息时。 传出 :当对象向外部发送消息时。 自我发送 :猜猜是什么?! 当对象向自身发送消息时。 3.遵循以下图表: 哦! 多么棒的图表! 对?! 保持这种状态直到对您自然。 第一个例子是采用Equatable。 该函数具有返回值,并且不会更改任何状态。 这是一个查询! 它是公共的,可以由另一个想知道两个Wallet是否相等的对象调用。 进来! 传入查询:声明结果。 传入查询非常简单。 您有一个预期的结果,然后调用该函数并断言它(如果它返回了预期的结果)。 (单词sut代表sut系统。在下面的示例中也将使用它) 第二个例子:在loadView之后,您想确保您的插座正确钩住! 他们在这一点上不应该零。 该函数没有返回值,调用后应设置出口。 因此,它有副作用。 所以,这是一个命令! (副作用是直接公开的,因为出口是sut上的财产 ) 该模块是公共的,可以从外部调用。 […]

Swift解决方案:复合

复合模式涉及集合和单个对象的树层次结构。 在上面的插图中,我们有一个文件夹和mp3的目录。 文件夹仅包含文件数组。 每个文件夹的集合可以包含mp3和其他文件夹的混合。 该插图很好地对应于我们定义的每个部分: 层次结构->目录 收集对象->文件夹 单个对象-> mp3文件 它允许客户以相同的方式对待每个层次结构元素。 层次结构中的所有文件共享一个公共接口,而不管它是文件夹还是mp3。 例如,mp3和文件夹都是可以重命名,移动和复制的文件。 因此,可以合理地期望符合要求实现类文件行为的协议。 重要的一点是,客户可以统一对待小组和单个部分。 在使用每个文件之前,无需经常对其进行类型检查。 这是使元素派生自相同协议或基类的直接结果。 UML 组件 :为集合和单个对象提供公共接口的抽象。 树中的所有元素都必须派生自组件协议或基类。 基元 :以前称为“单个对象”。基元只是树中不包含子级成分的成分。 Composite :以前称为“集合对象”。Composite是包含组件数组的对象。 虽然Composite对象和Primitive对象共享相同的接口,但是Composites包含其他方法来管理其子级。 请注意:有几种方法可以引用我们的具体组件: 我个人更喜欢“复合”和“原始”这两个术语。接下来,让我们进入代码吧! 实作 在我们的示例中,我们将向公司部门分配奖金,最终将其发放给员工。 在这种情况下,部门和员工分别充当我们的组合和基元。 零件 protocol Payee { var name: String { get } var bonusAmount: Double { get } func receive(bonus: Double) } 首先,我们为复合对象和原始对象创建一个Payee协议。 这将是我们统一对待他们的手段。 雇员 class Employee: […]

Xcode 7离线视图

当使用情节提要板时,Xcode 7在Interface Builder中引入了许多改进。 情节提要参考 ,改进的Unwind Segues和Segue子类化是有用的工具,将有助于使用情节提要构建和维护复杂的应用程序。 有关这些主题的所有详细信息,可以在WWDC 2015的“故事板的新增功能”部分中找到。 在此会话中强调的一项重要的小功能是能够在任何视图控制器的场景基座中添加“脱机视图”。 如果您需要呈现一个仅在其容器视图控制器显示后才显示的复杂视图,那么您很可能使用了以下两种方法之一: 在单独的xib文件中定义视图并加载它,如下所示: 让myView = NSBundle.mainBundle()。loadNibNamed(“ MyViewNib”,所有者:self,选项:nil).first! 如! UIView self.view.addSubview(myView) 将视图定义为容器视图控制器层次结构的一部分,可能使用alpha = 0或在主视图范围之外,然后响应某些事件而显示视图。 使用单独的xib文件方法,我们必须使用上面的代码以编程方式加载视图。 如果需要将IBAction和IBOutlet直接链接到视图控制器,则可以通过将视图控制器类指定为xib文件的文件所有者来实现。 尽管这可行,但它需要几个配置步骤,如果我们可以在其视图控制器旁边看到该视图,并且能够直接链接IBAction和IBOutlet,那就更好了。 所有这些都可以通过将视图直接添加到IB中的视图控制器的层次结构中来完成,但是最终我们可以将多个视图彼此并排堆叠,并且在视觉上由于它们彼此重叠而变得难以使用。 离线视图通过将所有内容保留在同一画布中,同时清楚地显示视图控制器及其离线视图,从而大大提高了故事板的清晰度: 要将离线视图添加到视图控制器,只需将UIView(或子类)拖到视图控制器场景停靠区中,它将显示在其上方。 同样,可以根据需要添加多个脱机视图并将其链接到视图控制器。 新添加的视图可以通过CTRL +拖动到View Controller的源文件中,作为IBOutlet链接: 显示视图 如果编译并运行该应用程序,即使调试器显示已设置了相应的IBOutlet,也将看到该视图不可见。 这是因为离线视图不会自动添加到视图层次结构中。 为了显示视图,我们需要自己添加它(例如,在@IBAction方法内部): self.view.addSubview(offlineView) 如果再次构建并运行,我们将看到该视图出现在主视图的左上角,并且其大小与在“界面”构建器中指定的宽度和高度匹配。 查看尺寸 以上所有都是很棒的-但是如果我们希望离线视图成为与其超级视图范围相匹配的叠加层,该怎么办? 从Xcode 7.0 beta 3开始,无法告诉IB添加后,脱机视图应扩展到容器视图,因此我们需要以编程方式进行此操作。 幸运的是,我们的朋友自动版式可以为您提供帮助。 我们可以编写一个简单的UIView扩展类,以将所有视图锚点约束到其超级视图边缘。 有关如何完成的信息,请参见本要点。 有了这个扩展,我们的视图可以像这样锚定到超级视图的边缘: self.view.addSubview(offlineView)//这是我们的@IBOutlet offlineView.anchorAllEdgesToSuperview()// UIView扩展方法 警惕的读者会注意到,以编程方式添加约束时,translatesAutoresizingMaskIntoConstraints设置为false。 WWDC 2015的第2部分“自动布局的奥秘”部分对此做了很好的解释。 结论 脱机视图是Interface […]

Swift / Objective-C桥接中的循环引用

任何拥有两年以上历史的iOS / MacOS项目都必须处理Swift和Objective-C的混搭 ,在这种环境中,不同的语言会试图共存。 但是,这种和平可能会受到某些特殊条件的威胁,在某些特殊条件下,由于歧义性,无法正确建立两种语言之间的桥梁,例如在循环引用的情况下。 以这种情况为例: ObjcMainClass由符合Swift编写的ComponentProtocol的对象组成,因此需要导入ProjectName-Swift.h生成的文件 ObjcMainClassTests是用于测试ObjcMainClass组件的Objective-C单元测试类。 它将使用符合ComponentProtocol的StubComponent对象,以控制要测试的公共方法的执行流程。 StubComponent是在单元测试目标中定义的,并且需要包含@testable import ProjectName代码才能找到协议定义。 由于StubComponent位于单元目标中,并且是用Swift编写的,因此ObjcMainClassTests必须导入ProjectNameTests-Swift.h生成的文件。 尝试运行单元测试,您得到的是“在ProjectNameTests-Swift.h中找不到模块ProjectName”错误: 在采用模拟单元测试方法的项目中,这种情况可能很常见,其中将新Swift接口的具体存根传递到现有的Objective-C实体。 最好的解决方案是减少Objective-C和Swift代码之间所需的桥梁数量。 尝试将模块或对象图迁移到Swift,或在计划迁移本身之前在Objective-C中临时编写协议和存根。 第二种方法显示在Github上的演示项目中,您可以在此处找到失败和通过的场景:https://github.com/matsoftware/TestObjcSwiftCircularReference。 桥接愉快☺

逐步指南以安装XCODE进行IOS开发

在本教程中,您将学习如何在MacBook中安装Xcode。 来源:iosDevelopers.org->在此处阅读原始内容 什么是XCODE? Xcode是macOS的集成开发环境,其中包含Apple开发的一套软件开发工具,用于为macOS,iOS,watchOS和tvOS开发软件。 这是开发Apple应用程序所需的唯一软件。 在本完整的iOS开发课程中,您将仅使用此软件。 XCODE是您的武器。 XCode不仅支持Swift,还支持其他编程语言,例如C,C ++,Objective-C,Objective-C ++,Java,AppleScript,Python,Ruby,ResEdit等。 XCODE的费用是多少? 作为Apple开发人员,您不会经常听到这个词,但是Xcode是免费的。 因此,现在您无需花一分钱就可以继续学习。 但是,是的,在学习了基础知识之后,如果您想将应用程序上载到appstore,则需要一个开发者帐户,该帐户的费用为$ 99。 我们将在稍后讨论。 现在,您可以继续使用它。 如何安装XCODE? 您需要按照以下步骤在MAC中安装Xcode:- 检查您的MAC版本。转到屏幕左上方的Apple图标,然后单击Cick-> About this MAC。 现在,您可以看到您的MAC版本。 Xcode 8的最低系统要求为OS X 10.11.5或更高版本(El Capitan),或者理想情况下,您应该运行macOS Sierra(10.12)。 如果您仍在运行早期的操作系统,则需要立即更新操作系统。 2.在您的MAC上打开Appstore。 3.搜索XCODE。 4.单击Xco​​de下方的GET按钮,然后等待其安装。 大约大小为4.8GB,因此如果您仍在使用2G,则可能需要一些时间(当然不是我) 5.安装完成后,单击应用程序中的XCODE图标并启动它。 6.轰! 您已准备好摇滚。 现在,您已经在MAC上成功安装了Xcode,并且所有设置均可用于启动Swift。 因此,让我们进入下一章。 到时候那里见 注意:我们在第1章中讨论了Swift的一些基础知识。如果您错过了该章,请在这里阅读:单击此处获得第1章。 如果您喜欢我的教程,并且想学习iOS和Swift,请访问我的博客www.iosdevelopers.org 现在,Namaste! 🙂