Tag: 编码

泛型-我一直看到的“元素”参数是什么? (速记3)

在学习Swift的过程中,我注意到一些函数要求使用Element类型的参数。 我有点被为什么要求我们提供一个类型变量感到困惑 我从未听说过像Array这样熟悉的东西…… 例如,让我们看一下在字符串 数组上调用的append()方法。 当我们使用自动填充来完成append函数时,系统会要求您提供一个参数: newElement:Element。 因为我们已经知道数组包含字符串,所以为什么类型不是String的参数呢? append方法将接受String并打印该方法,并将新字符串添加到Array的末尾。 那么,这是怎么回事? 为什么要求我为该方法提供一个Element,但是它将接受一个String ? 让我们再思考一下数组 。 我们创建的每个数组都有可用的append()方法,但并非所有数组都属于同一类型。 与其在String Array上使用append() ,不如在Int Array上尝试一下。 真好! 即使我们的数组类型从[String]更改为[Int],我们也可以使用Element类型来传递String或Int参数。 由于数组中各项的类型正在更改,因此使用Element可以根据数组中的内容传递正确的类型。 但仍然..什么是Element ? 这是一堂课吗? 结构? 事实证明,它被称为“通用代码”。 这里直接来自Apple文档: “通用代码使您可以编写灵活,可重用的函数和类型,这些函数和类型可以根据您定义的要求与任何类型一起使用。 您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。”

使用Swift的Awesome Extension的更聪明的print()方法

尊敬的所有iOS开发者和读者, 我的这篇文章将尝试向您介绍Swift语言在扩展方面的功能。 对于新手, 扩展为现有的类,结构,枚举或协议类型添加了新功能。 苹果 尽管在Objective-C中也可以使用扩展/类别。 但是Swift在这方面已经赋予了更多权力。 因为在Swift中,我们也可以创建原始数据类型的扩展,例如Int,Float Double。 所以我在说什么很棒的扩展。 我们一直在使用NSLog或Print来打印变量的值以进行调试。 print(“Trying to print \(someVar)”) 另外,我们可以从Xcode控制台使用po命令来查看变量的值。 我们也可以将p和fr v用于相同的目的,请阅读更多。 丑事: 我发现丑陋的是在变量前写了NSLog(“或print( ,在变量后写了”) 。这有点使我的Raftaar在编写代码时遇到了麻烦 。 因此,如果我们只将po()放在变量后,那会不会更聪明 。 喜欢 someVar.po() ,它将打印在控制台上, 代替 NSLog(“%@”,someVar) or print(“Trying to print \(somevar)”) 那就是我们今天要做的。 好吧,这里的主要目标是能够在任何类型的变量上调用po() 。 当我尝试创建扩展时,我正在考虑使用AnyObject创建on。 但是幸运的是我们无法在AnyObject上创建扩展。 经过一番研究后,我意识到所有非原始类型iOS框架的基类都是NSObject 。 所以这是价值十亿美元的扩展extension 扩展NSObject { func po() { 打印(个体经营) } } 现在,只需在String , Array , […]

分解AppDelegate(Swift 3)

在Xcode中,当您创建一个新的单视图项目时,您马上就可以在项目文件夹中找到一些文件。 这些是构建项目的良好起点-您可以将它们视为开箱即用运行项目所需的基本代码模板。 当然,如果您运行,则只会看到白屏。 让我们仔细看看AppDelegate.swift并查看该文件中发生了什么,以便我们了解它的作用以及为什么需要它。 我们看到的第一件事是我们正在导入UIKit框架。 Apple文档可以为我们提供有关框架功能的更多信息: 构建和管理适用于iOS和tvOS的应用程序的用户界面。 响应用户交互和系统事件,访问各种设备功能,启用辅助功能,并使用动画,文本和图像。 在watchOS应用中,启用辅助功能并使用字体和图像。 通过看到这已导入-我们知道AppDelegate类需要与用户界面建立某种连接。 @UIApplicationMain 接下来是“ @UIApplicationMain ”。 这是怎么回事? 尽管在上一行中,但它实际上是AppDelegate类声明的一部分。 它称为属性。 将此属性应用于类以指示它是应用程序委托。 使用此属性等效于调用UIApplicationMain函数并将此类的名称作为委托类的名称传递。 这就是说,您可以将此属性用作在自定义类上调用UIApplicationMain函数的简写。 那该功能做什么呢? 在main入口点调用此函数以创建应用程序对象和应用程序委托并设置事件周期。 在运行应用程序时,它需要知道从哪里开始执行代码。 可可触摸在UIApplicationDelegate的实现上使用@UIApplicationMain属性而不是main.swift文件来标记入口点。 由于在采用UIApplicationDelegate协议的AppDelegate上调用了“ @UIApplicationMain ”,这意味着AppDelegate充当了该应用程序的主要入口点。 现在,该应用程序知道从哪里开始,它创建的是UIApplication类型的单例 。 单例为在iOS中运行的应用程序提供了集中的控制和协调点。 然后,您的自定义类(AppDelegate)成为该UIApplication单例的委托 。 这个名字开始变得有意义了…… 类声明 现在让我们看一下AppDelegate类的其余声明。 我们可以看到它是UIResponder的子类,并且采用了UIApplicationDelegate协议。 让我们看看赋予类的功能是什么…… 首先让我们看一下UIResponder。 UIResponder类为响应和处理事件的对象定义一个接口。 它是UIApplication , UIView及其子类(包括UIWindow )的超类。 这些类的实例有时称为响应者对象,或简称为响应者。 一般有两种事件:触摸事件和运动事件。 触摸的主要事件处理方法是touchesBegan(_:with:) , touchesMoved(_:with:) , touchesEnded(_:with:)和touchesCancelled(_:with:) 。 这些方法的参数将触摸与其事件相关联(尤其是新的或已更改的触摸),因此,当所传递的事件在多点触摸序列的各个阶段中进行时,响应对象可以跟踪和处理这些触摸。 每当手指触摸屏幕,在屏幕上拖动或从屏幕抬起时, UIEvent生成UIEvent对象。 事件对象包含针对屏幕上所有手指或从屏幕上抬起的所有手指的UITouch对象。 […]

驯服iOS中的大量控制器第3部分

欢迎来到“ 驯服iOS中的大量控制器 ”的最后一部分。 强烈建议您先阅读本系列的第1部分和第2部分,然后再继续本文。 在前面的文章中,我们将UITableView控件的数据源提取到了一个单独的类“ ShoppingListDataSource ”中。 这将所有数据源功能从ShoppingListViewController移到了数据源的指定类中。 这项技术极大地帮助我们减小了控制器的尺寸,并将其放置在正确的位置。 当用户选择购物清单时,他/她被发送到杂货项目屏幕,在该屏幕上显示所选购物清单的所有相关项目。 这意味着我们需要为杂货项目创建一个单独的数据源。 GroceryItemsDataSource看起来与ShoppingListDataSource完全一样,唯一的区别是GroceryItemsDataSource将处理GroceryItem类型的商品,而不是ShoppingList,如下面的屏幕快照所示: 一种替代方法是创建适用于所有类的通用数据源和数据管理器类。 通用的UITableViewDataSource和数据管理器: 通用的TableViewDataSource将独立于类实体,单元格或与对象关联的数据管理器/数据提供程序的类型。 UITableViewDataSource的声明如下所示: class TableViewDataSource :NSObject,UITableViewDataSource,FetchedResultsDataProviderDelegate { 如您所见,TableViewDataSource是一个通用类,您可以在其中传递单元格和实体的类型。 由于我们正在使用CoreData,因此我们的实体类继承自自定义协议ManagedObjectType,这是我们的自定义类型。 TableViewDataSource初始化程序采用所有必需的参数,如下所示: init(cellIdentifier:String,tableView:UITableView,dataProvider:FetchedResultsDataProvider ,cellConfigurationHandler:(CellType,Entity)->()){ self.cellIdentifier = cellIdentifier self.cellConfigurationHandler = cellConfigurationHandler self.dataProvider = dataProvider self.tableView = tableView super.init() } 需要注意的一件事是dataProvider参数,它也是FetchedResultsDataProvider的通用类型。 让我们检查ShoppingListTableViewController中的代码,该代码声明了数据源和数据提供程序。 私有var dataSource:TableViewDataSource ! 私人var dataProvider:FetchedResultsDataProvider ! 接下来,我们将使用适当的信息初始化dataSource和dataProvider属性。 覆盖func viewDidLoad(){ super.viewDidLoad() self.dataProvider = FetchedResultsDataProvider(managedObjectContext:self.managedObjectContext) self.dataSource […]

RxSwift和您可以使用响应式编程完成的出色工作-第一部分

我第一次听说反应式编程,这就是我的样子: 第二,第三和第四次也没有太大不同。 而且,即使我是第一次从事一个具有一些响应式代码的项目,也不要让我开始……那个表情在我脸上呆了整整两周! 现在我知道,很多人第一次遇到反应式编程时,都会有与我相同的感觉。 我也认识很多人,在经历了最初的不良印象之后,他们再也没有去研究它了,因为这听起来像是付出了太多的努力才开始使用。 但是我可以告诉你的事实是,我不认识一个人,在最终了解了它的工作原理之后,他才后悔参加了反应式编程。 现在我知道在线上有足够的资源来处理反应式和RxSwift的理论和复杂性,还有很多关于如何使用Rx进行各种操作的教程(我在其中最后放了一些链接)的帖子)。 不,我不会再编写有关流和可观察对象如何工作的教程或解释。 我想做的是提供一个简单,清晰,几乎没有理论的摘要,概述您可以使用RxSwift进行的操作以及为什么要使用它。 由于Rx有很多内容,我将在3个博客文章系列中对此进行细分。 让我们开始第一部分! 第1部分:数据绑定,控制事件和手势识别器 数据绑定 “数据绑定”听起来像是花哨的单词中的另一个,使事情听起来很漂亮,但这确实非常简单。 假设您有一个需要用户在文本字段中输入其名称的应用。 当他们这样做时,您要向他们打招呼,说“你好,\(名称)”。 很基本吧? 在非反应式应用程序中,应将UITextFieldDelegate协议添加到视图控制器,并实现textFieldDidEndEditing方法以跟踪用户何时完成其名称的书写,这时应设置标签的文本以对该名称问好。 不幸的是,与代表打交道可能会很烦人。 如果您有多个文本字段怎么办? 您将必须添加检查以确保用户已完成编辑正确的文本字段。 而且,如果客户决定在用户​​输入姓名时(而不只是在完成文本字段编辑时)更新标签,该怎么办? 在反应式中,这种行为可以通过数据绑定来实现。 简而言之,您想将用户在文本字段中提供给您的数据绑定到另一个UI对象(标签)。 使用RxSwift,没有比绑定数据更简单的了。 在我刚才提到的情况下,这将是这样的: var nameField = UITextField() var helloLabel = UILabel() 覆盖func viewDidLoad(){ nameField.rx.text.map {“ Hello \($ 0)”} .bindTo(helloLabel.rx.text) } 让我们分解一下:首先,我们获取文本字段的文本,然后将其映射为要在标签中设置的格式。 在这种情况下,它只是意味着在文本(又称用户名)之前添加一个问候,由于map是一个闭包,因此可以简单地称为无名闭包参数( $0是第一个参数, $1是第二个参数,依此类推)。 然后,我们将该映射文本绑定到标签中的文本。 就是这样,工作完成了! 没有委托,没有if语句,只有一点简单明了的代码。 现在,我知道您在想什么:这很重要,但实际上有多少应用程序会执行此类操作? 我只能告诉您的是,不要卡在示例中。 能够将数据绑定到视图非常强大,只需考虑一下:您可以根据天气改变视图的backgroundColor,根据一些数据,使用一些非常简单的逻辑,根据用户的位置在商店应用中导航用户可能会改变。 再说一次,我不会对理论进行过多介绍,但这是背后的主要思想。 2.控制事件和手势识别器 […]

如何从头开始在Swift中实现MVVM模式

在深入研究代码之前,这里是对该模式的快速介绍。 MVVM代表模型,视图,视图模型,这是一种特定的体系结构,其中视图模型位于视图和模型之间,提供模仿UI组件的接口。 通过“绑定”值(将逻辑数据链接到UI)来建立此连接。 在iOS应用中,这种MVVM方法中的View元素通常是UIViewController本身。 这种方法的好处是代码变得更加模块化,易于维护和测试。 现在让我们进入代码。 模型 与api模型匹配,这是我的两个结构开始。 struct CurrencyRate { let currencyIso : String let rate : Double } struct Converter { let base : String let date : String let rates : [CurrencyRate] } 我还创建了一个特定的服务来创建一个api请求以及我的Converter实现的解析器协议。 您可以在该文章末尾的Github存储库中找到这些源代码。 这并不是真正与MVVM相关的,因此我将直接进入我们的ViewModel和绑定系统。 视图模型 首先,为了能够将ViewModel的值绑定到View,我们需要具有可观察模式的元素。 在iOS中,我们可以使用KVO模式添加和删除观察者,但我认为我们可以使用“ didSet”观察者做得更好。 让我们记住,我们要随着时间的推移执行特定的代码,而该代码已更改。 我们还可以假设我们的对象可以有多个等待更新的观察者。 为此,我创建了一个类,其中包含一个观察者及其更新时要执行的代码的字典(此处为闭包)。 在这里看起来像什么。 typealias CompletionHandler = (() -> Void) class DynamicValue […]

Swift 4.2可降解:异构集合📚

继去年发布Codable协议之后,许多iOS开发人员一直在忙于删除沉重的自定义JSON解析器,并在模型层中将它们替换为对Decodable的流畅且轻量级的构造……我也不例外:在最近的项目中作为一个客户,我很高兴增强大型应用程序的模型层,其目标之一就是完全符合Codable。 挑战1:嵌套的异构集合 最初,过渡到Decodable的过程很顺利(“祝您删除代码愉快!” )。 但是,自定义JSON解析器的删除导致重要的类类型映射的删除-原本功能强大的Codable协议未直接支持Codable 。 为了举例说明我在说什么,请考虑以下几点: 在这种非常简单的情况下,我们有一个超类Pet,它被两个类Cat和Dog继承,从而允许一个人拥有一个超类Pet的单个集合,而集合中的实际对象是Pet, Cat or Dog类型。 从JSON解码Person对象时会发生问题,因为“宠物”列表中的对象不是同一类型: 宠物列表将在Person初始化程序中像这样解码: container.decode([Pet].self, forKey: .pets) ,但这样做将检索超类Pet对象的列表,从而失去所有子类属性。 用Cat或Dog代替Pet也是不够的,因为我们对每种不同的类型(包括它们各自的属性)都感兴趣。 同时使用JSONSerialization反序列化JSON以使用类型区分JSONSerialization进行映射,似乎完全消除了使用Codable的好处,因为这是使用旧JSON解析器完成的方式。 解决方案:集中类映射 幸运的是,我并不孤单地遇到这个问题:Tom Stoffer写了一篇很棒的文章,介绍如何处理嵌套在Decodable对象中的异构列表。 尽管此解决方案在某种情况下是好的,但对于大型项目而言,这并不是一个非常干净的解决方案,因为我们可能会重复类型映射代码,因此我们可能会遇到多个对象相同的异构列表。 为了解决这个问题,我们可以将类型信息(映射)提取到类家族的集中位置。 这可以通过利用快速枚举上的函数来完成。 目标是通过公开用于检索正确映射的类型的函数以及JSON有效内容中类型鉴别符的键,来创建一个表示相关类家族的枚举。 因为我们希望解决方案尽可能通用,所以我们可以编写一个协议来定义所需的公开信息: 注意:仅在您为鉴别器使用不同键的情况下,才真正需要鉴别器类型。 (在我正在从事的项目中,我有两个不同的键)。 此外,鉴别变量是静态的-稍后会详细介绍。 ClassFamily协议允许我们创建一个描述任何对象族的枚举。 让我们看一个例子,说明我们的Pet案例的枚举是什么样的: 太好了,这个枚举现在描述了我们的宠物对象家族! 然后,我们可以直接在Person类的可解码的初始化程序中使用它,如下所示: 但老实说,此解决方案仅提取了映射,并没有真正使初始化程序更简洁。 因此,为了解决这个问题,我们将在KeyedDecodingContainer:的扩展中创建解码函数的泛型重载KeyedDecodingContainer: 这样做可以使我们极大地清理Person的初始化程序: 我们已经完成了可解码对象的嵌套异类列表的解决方案-干净整洁,不是吗? 但这不是全部… 挑战2.异构集合作为返回类型 …如果异构集合未嵌套在Decodable对象中怎么办? 例如,考虑以下情况: Person的Pets集合不是属性,而是在运行时通过API调用从服务器获取的: 在这种情况下,问题仍然存在: [Pet]类型的解码将导致带有名称的未知宠物的列表。 使用Cat或Dog也是不够的,并且为了像Tom Stoffer的方法一样,我们不像在Person类的初始化程序中那样具有带键控容器的Decoder对象。 令我惊讶的是,我在Stackoverflow或其他地方找不到很多类似情况的信息,然后返回反序列化JSON以读取鉴别符类型,然后进行解码,这对我来说是不可接受的。 解决方案:包装器类! 因此,经过数小时的类型推断问题和编译错误,我设法使用包装器类和一些枚举提出了一个通用解决方案。 这个想法是能够通过利用相同的类家族枚举来使用与嵌套集合相同的方法。 为此,我们必须围绕可解码类(及其子类)创建一个包装器类,然后可以将其映射到正确的类型。 让我们看一下如何实现它。 包装器必须是可解码的,以便我们使用JSONDecoder直接对其进行解码。 此外,它需要保留对我们希望创建的对象的引用。 […]

Swift 3:使用单行输入的自定义UITextField

嗨,大家好! 这将是一篇简短的提示与技巧样式文章。 今天,我正在尝试(幸运地成功)构建了一个包含一个底线的自定义UITextField。 我敢肯定您之前看过,或者至少看过类似*的东西。 它并不复杂,但是使用自动布局时会变得棘手。 让我们看看如何首先制作这样的UITextField,您要做的就是创建扩展 扩展UITextField { func setBottomLine(borderColor:UIColor){ self.borderStyle = UITextBorderStyle.none self.backgroundColor = UIColor.clear 让borderLine = UIView() borderLine.frame = CGRect(x:0,y:Double(self.frame.height)—高度,宽度:Double(self.frame.width),height:height) borderLine.backgroundColor = borderColor self.addSubview(borderLine) } } 您可能想知道那里到底发生了什么,我将立即解释! 在我们设置透明背景并为文本字段禁用边框后,将创建UIView。 然后,将其框架设置为高度等于1.0的线,并通过以下y点计算将其放置在文本字段的底部 Double(self.frame.height)—高度 接下来是设置背景颜色,并准备添加子视图。 很简约! 现在,对于那些想要使用自动布局的人来说,棘手的部分是: 你不敢打电话 setBottomLine(borderColor:UIColor) 在ViewDidLoad()中,由于当时尚未应用所有自动布局规则,因此导致行为不确定。 要使其正确,只需调用viewDidLayoutSubviews()函数中的方法 覆盖func viewDidLayoutSubviews(){ 让lineColor = UIColor(红色:0.12,绿色:0.23,蓝色:0.35,阿尔法:1.0) self.myTextField.setBottomBorder(borderColor:lineColor) } 而已! 请让我知道这对你有没有用!

iOS 11应用开发:创建Spotify克隆免费Udemy课程。

音乐是所有应用商店中最大的应用类别之一。 他们有潜力获得可观的收入。 了解使用流行的编程语言Swift 2构建功能齐全的iOS音乐流应用程序所需的基本概念,工具和功能。还学习如何设置自己的服务器以及上传最终将要播放的音乐。 您将学到的东西 Xcode安装和设置 iOS上的基本流功能 如何设置服务器(免费或付费) 如何使用PHP在服务器上自动对音乐文件建立索引(无需PHP经验) 如何使iOS应用与服务器通信 如何添加锁屏控件 如何添加锁屏媒体信息 如何处理电话等音频中断 如何在iOS上创建表视图和自定义表视图单元 动态地向您的应用程序和远程数据库添加更多数据 在Facebook上分享歌曲信息 跟踪我们的远程数据库 触手可及的强大技能 通过学习创建iOS应用以及PHP和MYSQL后端,您将对潜在雇主产生难以置信的价值。 将这两种技能结合在一起是开发人员被雇用为初创公司的第一原因。 这些创业公司需要这些信息,并愿意为此付出代价! — — — — 奖金 — — — – 您不仅可以学习iOS应用中流音乐的来龙去脉,而且该课程还包括大量奖励。 我教您如何创建和设置执行以下操作的功能齐全的服务器: 自动扫描新上传的音乐并将其添加到MYSQL数据库(无需您输入任何内容) 生成允许您的应用访问后端的PHP文件 — — — — — — — — — — — — — — 内容和概述 本课程无需编程知识,但会有所帮助。 如果您是一个完整的初学者,请参加我的其他课程(适用于完全和完全初学者的iOS应用)。 您将被带往以下过程: 如何在免费或付费服务器之间进行选择 如何在iOS上编写简单的流功能 如何向您的应用程序添加高级音频功能 […]

使用Swift Codable协议提取JSON片段

可编码协议确实有助于简化开发人员的生活。 它使我们能够将JSON响应转换为模型对象,而无需经历解析每个对象的繁琐过程。 我们如何在Swift中使用Codable协议? 为了更好地理解这个概念,让我们开始尝试一些编码示例: Flickr 搜索JSON示例: { “ title”:“最近上传带标签的searchtag”, “链接”:“ https:\ / \ / www.flickr.com \ / photos \ / tags \ / searchtag \ /“, “描述”:“”, “已修改”:“ 2014–05–06T05:45:56Z”, “生成器”:“ https:\ / \ / www.flickr.com”, “项目”:[{ “ title”:“ Bird \ / Pleasanton-CA”, “链接”:“ https:\ / \ / www.flickr.com \ / photos \ / geziyozbiz \ […]