如今,使用Web服务API是现代移动应用程序开发的重要组成部分。 在本文中,我想分享一种使用Alamofire和Swift 4设置网络层的简单方法。 我们将在构建API客户端时完成以下步骤: API路由器:端点构建器 API客户端:创建并执行请求 可编码:解析JSON并映射到数据结构 使用未来/承诺 使用反应式编程(ReactiveCocoa和RxSwift) 在第一部分中,我们将重点介绍请求构建器组件。 API路由器:端点构建器 具有一个提供端点的API请求构建器组件很重要。 路由器将使用HTTP method , HTTP headers , path和parameters来呈现端点 推荐的方法之一是使用Swift Enum创建我们的API路由器。 这是路由器的实现: 端点构建器 理想情况下,您有一个Constants.swift文件,可以将所有常量都放在一个位置
本文适用于刚刚开始快速开发ios应用程序的用户。 最大程度的初学者友好内容使用情节提要用于此类事情,因此我决定创建一些没有情节提要的内容。 让我们开始吧。 打开Xcode,选择File-> New-> Project。 构建并运行后,您应该看到模拟器以白色视图启动。 现在选择情节提要,您将看到一个白色的场景/视图,选择它并单击删除。 另外,删除ViewController.swift文件。 我们将从头开始。 现在,如果您运行该项目,您将看到一个空白屏幕。 如果您看到该日志,则会发现以下消息: 无法实例化UIMainStoryboardFile’Main’的默认视图控制器-可能未设置指定的入口点? 这是说该项目当前没有任何入口点。 很快,我们将提供一个控制器类作为该应用程序的入口点。 选择文件->新建->文件。 您将看到一个可用模板的窗口。 选择“快速文件”。 它将询问您文件的名称。 给SignUpController,最后按Enter。 选择SignUpController.swift文件,删除所有内容并复制粘贴以下代码。 我们要添加一个橙色视图作为200点的顶视图。 我们如何实现这一目标? 让我们为此创建一个橙色视图。 将以下代码放在viewDidLoad方法上方。 在这里,我们看到表单已经准备好了。 至此,视图部分已完成。 不幸的是,它不响应任何用户操作。 为了启用该功能,我们将以下代码添加到signUpButton: 我们以两种不同的方式为我们的注册表单提供了空文本字段验证。 现在,您可以随意进行一些复杂的验证。
有时,您希望编写一种适用于任何Optional类型的通用算法,无论包装在里面的是哪种实际类型。 好的,这可以使用免费的泛型函数轻松完成,但是例如,如果要编写Sequence扩展以删除所有nil值怎么办? 由于Optional不是协议而是具体类型,因此事情变得有点复杂,因此不能将其用作通用类型约束。 Swift中的通用协议和具体类型具有不同的用途:我们创建实例并声明具体类型的变量,而协议则可以用作通用类型约束。 类型擦除是一种在我们要声明一个能够容纳符合特定协议的任何具体类型的变量时使用的技术。 相反,我们想要的是同一难题的另一部分,我们需要一个协议,允许我们将具体的泛型用作约束。 用英语听起来这听起来很复杂,但通常情况下,用普通的Swift编写起来看起来要简单得多。 因此,这里我们只定义一个OptionalType协议,声明WrappedType关联的类型,并使Optional枚举符合该类型。 请注意,泛型类型参数不会自动满足协议要求,但是这里我们有类型推断。 为了使该协议有用,我们公开了一些基本的Optional功能: asOptional属性使我们可以访问可选的绑定语法。 ExpressibleByNilLiteral一致性允许我们使用nil进行初始化。 完成之后,我们现在可以将OptionalType用作一般约束: 如果您正在寻找可以使用Optional枚举完成的更多技巧,则应查看Russ Bishop撰写的精彩文章。
运算符重载是Swift编程语言的强大功能之一。 从本质上讲,它基本上是对任何您想要的类型使用-,+,==,/,*运算符。 另外,您可以定义自己的运算符,并在项目中使用它们。 多么酷啊? 假设您有一个新闻项目,并且正在处理一些文章: 结构文章{ 变量ID = 0 var title =“” var desc =“” init(id:Int,title:String,desc:String){ self.id = id self.title =标题 self.desc =说明 } } 让articleA = Article(id:1,标题:“ Title#1”,desc:“ Article description#1”) 让articleB = Article(id:2,标题:“ Title#2”,desc:“ Article description#2”) 让articleC = Article(id:2,标题:“ Title#2”,desc:“ Article description#3”) 现在,我们需要检查两个文章是否相同,但是逻辑是,只有id和title相同时,它们才是相同的。 可能,我们将使用if语句以老式的方式进行操作。 如果articleB.id == articleC.id && articleB.title == articleC.title { 打印(“文章相同”) }其他{ […]
在Fenrir,我们的许多开发人员都有维护已存在一段时间的应用程序的经验。 由于其中一些应用程序的规模,通常需要支持较旧的iOS版本。 当您还考虑到迁移中的小错误可能会影响成千上万的人这一事实时,就必须了解代码的内容。 推送通知是由于需要设置而难以测试的技术之一。 由于推送通知已经存在了一段时间,因此本文将不讨论如何实现它们。 取而代之的是,它将尝试阐明有关推送通知的各个方面,这些方面对于新来者可能并不那么明显,或者甚至可能被某些资深人士忽略。 其中之一是实际调用每个处理程序方法的时间。 必须先正确配置两件事,然后才能接收推送通知。 设备功能 该应用必须指定其支持的功能。 要接收推送通知,必须打开“推送通知”功能。 也可以打开的另一个功能是“远程通知” 。 可以在“背景模式”组下找到该应用程序,并允许您的应用程序在后台启动,以响应其有效负载包含“内容可用”标志的通知(也称为静默通知)。 设备令牌 获取设备令牌是必要的,以便您的服务器可以使用它来通过Apple的分发系统发送通知。 可以通过调用以下方法来检索设备令牌: 它将在您的AppDelegate方法中返回适当的响应。 但是, 调用此方法的时间取决于当前设置的设备功能。 也就是说,如果您没有启用“远程通知”功能,则必须先征得用户许可才能显示警报,然后才能检索设备令牌。 但是,如果打开,则可以随时检索设备令牌。 使用以下方法可以要求用户授予许可。 在iOS 10之前,使用UIApplication方法: registerUserNotificationSettings(_ 🙂 从iOS 10开始,使用UserNotifications框架方法: requestAuthorization(options:completionHandler 🙂 setNotificationCategories(_ 🙂 经常被忽略的是实际上有两种类型的推送通知。 “警报通知” 这些通知用于警告或通知用户某些事情。 它们可以包括警报,设置徽章甚至播放特定的声音。 仅需要“推送通知”功能。 检索设备令牌之前,需要用户的许可。 它们的有效载荷与此类似(示例摘自Apple文档): { “ aps”:{ “ alert”:“您收到了电子邮件。”, “徽章”:9 “声音”:“ bingbong.aiff” }, “ acme1”:“ bar”, “ acme2”:42 } […]
创建插座和属性 1.简介 在教程9中,我们连接了NewsTableViewCell现有出口,并输入了所需的属性。 在本教程10中,我们将为第二个图像视图创建一个自己的插座,并在其中设置图像的属性。 这与我们进行真实编码所需的时间差不多。 大多数编码工作已经为我们完成。 我们在本教程中编写的模板代码对于我们以后创建的任何其他插座和属性将基本相同。 这是很难的,而且还不那么难。 2.显示Xib和代码 X在Xcode中,在项目浏览器中选择NewsTableViewCell.xib 。 我们需要同时查看该xib文件和相应的代码文件。 👉在工具栏中,单击Assistant Editor 。 👉您应该在右侧看到NewsTableViewCell.swift代码。 如果没有,请通过单击弹出菜单来检查右侧文件是否设置为Automatic ,如图所示。 👉如果您在屏幕上需要更多空间,请使用工具栏右上角的按钮或单击“ View菜单,然后单击“ Inspectors > Hide Inspectors器”来隐藏“检查器面板”。 3.创建一个插座 👉按住Control键(在键盘上),然后从xib的第二个图像视图拖动到代码文件中的class行下方。 code Xcode为新插座显示一个弹出框。 输入插座Name作为detailImageView 。 👉单击Connect按钮。 code Xcode为我们编写连接代码,并将其连接到xib中的图像视图。 👁您不需要了解它,但是如果您感到好奇,那么创建的代码行包括: 边距中的实心圆圈表示此插座已连接至xib中的某物。 @IBOutlet在边距中创建圆,并让Xcode知道它可以连接到xib中的视图。 weak意味着该应用程序可以在不使用任何连接时释放(忘记)此连接。 var表示这是一个“变量”,可以通过代码或连接进行更改。 变量是可以更改(即更改)的属性(也称为“属性”)。 detailImageView是我们之前键入的名称,它是此变量的名称。 : UIImageView将此变量的类声明为UIImageView 。 因此,此插座只能连接到UIImageView 。 感叹号( ! )表示必须先连接此变量,然后才能使用它。 也就是说,它必须具有一个值并且不能为零。 现在,我们已经完成了助理编辑器。 我们只需要使用Assistant Editor即可同时看到xib和Swift文件,以便我们可以控制它们之间的拖动连接。 can您可以使用工具栏中的三种编辑器模式的左侧切换回Standard Editor 。 […]
本文使用RxSwift来说明其观点。 如果您不熟悉该库,则可以阅读其 GitHub存储库上的简介 。 非常感谢 Hugo Saynac 的表现,使我意识到了这个问题,并提出了我将在下面描述的第二种解决方案。 与许多语言一样,Swift允许开发人员引用实例方法,并在以后使用它引用或调用此方法。 尽管语法使它很容易利用,但其底层实现可能会导致创建一些棘手的保留周期。 在本文中,我将解释这种保留周期何时产生,是什么原因造成的,最后是避免它们的难易程度。 方法参考如何工作? 让我们考虑以下类: 要了解真正的原因,我们需要深入研究方法引用的工作方式。 这是什么意思 ? 我们需要记住, printInput是一个实例方法,因此它的引用需要知道在调用该方法时self将引用哪个值。 即使像我们的示例中那样,该方法实际上并没有使用self ,这也是正确的,并且这是很有意义的,因为子类可能会很好地覆盖该方法并在其新实现中使用self 。 这就是WillNeverBeFreed.printInput为我们提供方法引用的原因,该方法的self值尚未绑定。 它采用函数的形式,该函数以self的值作为参数,并返回对实际实例方法的引用。 因此,对该方法的绑定引用存储了一个强指针,该指针将用于self 。 当我们调用.subscribe(onNext: printInput) ,我们将绑定到self的方法的引用作为参数传递给了参数,这导致了保留周期。 两种可能的解决方案 为了解决这个问题,我们基本上需要找到一种方法的参考方法,同时又不能以很强的方式捕捉self 。 进行的第一种方法是定义一个像这样的函数: 它所做的是在一个弱变量中捕获self的值,直到实际调用该方法为止,如果仍然为self分配了值,它将在该点调用它,否则它将不执行任何操作。 然后我们像这样使用它: 另一种合理的方法是将方法声明为计算属性返回的闭包: (在这种情况下,我们在闭包中不使用self,因此不会捕获它。但是,如果使用并捕获了[weak self] ,则将指示[weak self]以避免捕获强引用) 然后,使用它的语法恰好是我们要实现的语法: 一切都是权衡 上述两种解决方案都设法解决了保留周期的问题,但是每种解决方案都有其特定的缺点。 使用第一个解决方案将使语法稍微简洁一些,但是它具有使用实际方法的优势,既可以覆盖它们又可以调用其超级实现。 第二种解决方案保留了更简洁的语法,但是是以使用闭包而不是方法为代价的,这是Swift 3所付出的代价:闭包可以在子类中覆盖,但是覆盖的闭包需要在使用之间进行选择[weak self]并调用超级实现。
它是如何开始的 2011年3月,当我为iOS开发我的第一个真实项目时,IT Buddy最初是一个IP计算器,现在被认为是真正的IT Buddy! 从第一天开始,我就考虑在IT Buddy中添加LAN扫描程序的情况,但是我的知识有限,没有任何我可以使用的开源项目。 五年后,仍然没有像样的LAN扫描程序库。 有几个可用的LAN扫描仪,但尚未投入生产。 没有适用于iOS的不错的LAN扫描程序库 很多人在StackOverflow上询问如何实现LAN扫描仪,所以我决定将所有部分放在一起(SimplePing,SimplePingHelper,LAN-Scan和MacFinder),并创建一个不错的开源库来通过iOS设备扫描网络。 。 体面的意思是: 不仅可以扫描所有子网/ 24 快速搜索而不会阻塞UI 使用默认的LAN扫描技术来ping和查询ARP表。 显示可用主机的IP和MAC地址。 根据MAC地址显示设备品牌 MMLanScan 因此,名称为MMLanScan,并且非常易于使用。 在此处下载并在您的项目中复制MMLanScan文件夹! 在您的控制器中导入MMLANScanner #import“ MMLANScanner.h” 将MMLANScannerDelegate添加到您的控制器 @interface YourViewController() 声明MMLANScanner属性 @property(nonatomic,strong)MMLANScanner * lanScanner; 开始扫描 [self.lanScanner停止]; self.lanScanner = [[MMLANScanner alloc] initWithDelegate:self]; self.connectedDevices = [[NSMutableArray alloc] init]; [self.lanScanner启动]; 实现委托方法以接收事件 -(void)lanScanDidFindNewAddressWithIP:(NSString *)ipAddress MACAddress:(NSString *)macAddress和Hostname:(NSString *)hostname; -(void)lanScanDidFinishScanning; -(void)lanScanProgressPinged:(NSInteger)pingedHosts from:(NSInteger)overallHosts; -(void)lanScanDidFailedToScan; 怎么运行的 […]
第1部分:简介和设置 第2部分:位置数据和管理依赖项 第三部分:持续集成 第4部分:流媒体位置 第5部分:网络层 第六部分:国家管理 到目前为止,我们已经为我们的应用程序创建了可靠的数据源,现在我们将致力于在数据和视图之间建立通信。 Apple官方文档提出的MVC架构对于新开发人员来说是最直观的。 这种架构足以满足简单的应用程序和小型团队的需要,但是遵循MVC的趋势是将所有代码集中到UIViewController类中,这会使您的应用程序难以理解并且容易出现错误。 首先,我想说明一下这是一个非常主观的概念,受以下因素的影响:功能的复杂性,团队规模,质量的定义和限制,组件的可重用性水平,开发人员的技术技能以及开发人员具有该架构的经验。 我个人在定义应用程序体系结构时优先考虑了3个基本原则: 组件责任:项目包含预定义的角色,避免了繁琐的类,并且添加新功能相对容易。 简便性:新开发人员第一次阅读代码时,应该能够轻松理解基本原理。 它还应该能够理解定义的模式,并在短时间内开始开发新功能或修复错误。 可测试性:顾名思义,代码应该更易于进行单元测试。 我在这里提出的解决方案不应被视为灵丹妙药,但它绝对比普通的MVC更好,而且相对容易学习。 通过选择使用ReSwift,我获得了体系结构以及数据流模式。 ReSwift的组件包括: Store:一个全局变量,代表您应用程序的当前状态。 在我们的情况下,它应该包含一个位置数组和数据获取状态(加载,完成或错误)。 视图:负责观察状态更改并基于新状态显示正确的UI。 在我们的例子中,它将是主要的UIViewController 。 行动: structs ,包含状态更改所需的有效载荷数据。 示例:一个名为SetPlacesAction的结构, SetPlacesAction包含一个公共位置数组。 Reducer:接收两个参数( Action和State )并返回新State 。 所有状态更改应集中在减速器上。 下面的代码定义了“状态”: 国家代表 这里的主要结构是FetchedPlacesState ,它必须符合StateType协议。 此结构包含一个枚举,表示应用程序的所有可能的三种状态: 加载:默认状态,表示应用程序正在等待提取所有数据。 失败:如果发生任何错误,我们使用此状态为用户显示一条人类可读的消息。 已完成:包含成功获取位置的数组 Equatable扩展仅对于单元测试是必需的。 Actions结构如下所示: 现在唯一缺少的是Reducer : 现在我们已经准备好所有代码,现在可以清楚地看到返回的State是Action和前一个State的函数。 我想在Reducer代码中指出一些细节: 具体来说,在我们的应用程序中,新状态不依赖于先前状态。 因此reduce方法仅使用action参数。 当您调用Observable方法时,它在Observable和Disposable ( subscribe方法的返回类型)之间创建了一个循环内存引用。 为了打破保留周期并避免内存泄漏,您只需要像我已经显示的那样调用disposed(by:)方法即可。 有关在此处处理袋子的更多详细信息。 您可能会注意到在此代码中闻起来不太香的是,在这种情况下, […]
自我介绍! 你是谁? 你在哪里工作? 嘿,我叫Andyy Hope,我是一位澳大利亚iOS工程师,即将在Facebook工作。 我还是墨尔本Playgrounds Conference的组织者,也是新创建的慈善计划Wu-Tang Clang的创始人。 在业余时间,我喜欢写一个技术博客,在其中我想提供一些使用Swift语言和Apple框架的技巧,并且有时我会在聚会或会议上进行演讲。 是谁或什么让您参与编程的? 在90年代后期,我被介绍给互联网,从那时起我就非常着迷。 不久之后,我遇到了AngelFire虚拟主机,它为想要创建自己的个人网站的人们提供免费服务,他们为像我这样的初学者提供了不错的模板,我利用了这些模板。 有一天,我偶然发现了一项功能,该功能使我可以编辑网页的HTML,我记得当初看到该代码时,绝对感到震惊。 自然地,我对其进行了调整并破坏了很多东西,但是它使我想学习HTML,因此我遇到了一个网站HTMLGoodies.com,该网站每天都成为我的首选,很快我就学到了一些用于编辑网页的基本HTML 。 我想从那时起我所做的一切都源于那段时间。 高中时,我一直与编程网站保持联系,制作Pokemon和Dragonball Z粉丝页面。 但是到了20年代末/ 20年代初,我就退出了编程领域,开始从事酒店业。 我花了好几年的时间才意识到这不是我想要追求的东西,最终我回到了专注于技术和编程的领域。 举办Playgrounds Conference对您的职业有何影响? 我会说它做了很多。 我记得在2015年12月的墨尔本CocoaHeads聚会上。 当时没有人认识我,我想通过与当地社区的更多参与来改变这种状况。 他们正在为房间里的人们做介绍,我举起手来做自我介绍,我向每个人提到我想成为社区中更大的一部分,但是我不知道我会继续为他们一年后。 游乐场帮助我结识了很多新朋友,结识了许多新朋友,在我们的行业中,拥有一个庞大的网络对于大多数人来说通常是一件好事。 我的许多发言人来自旧金山的公司,所以当我问他们是否可以推荐我接受采访时,他们很乐意为我提供帮助。 六个月后,我在Facebook找到了工作。 同样,在Medium上撰写大量精彩内容对您的职业有何帮助? 在Medium上写博客是一种自我学习以及向他人教授的好方法。 我发现我在写作时发现读者几乎一无所知。 做出这个假设迫使我对这个概念产生了深刻的理解,因此我可以用更简单的术语将其传达给其他人。 我写的越多,我学到的就越多。 “如果您不能简单地解释某些内容,那么您将无法充分理解它” –艾伯特·爱因斯坦 让人们给我发送评论或推文,感谢我写一篇文章,这也是一种很棒的感觉。 很高兴看到我所做的工作可以帮助他人,这确实是帮助我撰写更多内容的驱动因素。 我想这与您对博客帖子的处理类似,对吗? “如果您要教别人做比萨,请假设他们不知道奶酪是什么。”-我 我看到您最近一直在申请新工作,包括一些有关算法和CS的研究。 您为什么认为这项研究很重要? 有帮助吗? 绝对是 我不建议任何人至少在不掌握其计算机科学(CS)知识的情况下申请在美国的职位。 在美国,面试是一个漫长而艰巨的过程,应试者将在从通用CS知识到实际领域经验的所有方面对候选人进行测试。 我最近决定,我想搬到旧金山(SF),这样我就可以接近行动了,而且我不想冒险失败,而不必再等待6或12个月才能重新申请。 所以我离开了工作,回到家乡珀斯,连续学习了六个星期。 每天我都会做多个白板,在YouTube上观看众多算法视频,并且对我的CS知识有很多了解。 许多现场访谈的时间从4到6个小时不等,几乎所有您学到的知识都对您构成了质疑。 我认为,最好绝对做好准备,并全力以赴,这样您就不必冒着日后重复该过程的风险,有可能您在重新申请时会忘记很多东西,并且不得不花了几个星期再次增加。 到目前为止,您在软件行业中最难学的一课是什么? 毫无疑问,成为团队领导。 在我的整个职业生涯中,我一直都是独立开发者或与其他人一起工作。 […]