IT行业发展迅速。 对于移动应用程序开发,使用了各种编程语言。 长期以来,Objective C是用于创建OSX和iOS应用程序的主要编程语言。 如Wikipedia所述,Objective C是通用的,面向对象的编程语言。 Objective C编程语言最初是在1980年代开发的。 为了开发iOS应用,苹果在2014年带来了革命。苹果在2014年的全球开发者大会(WWDC)中推出了Swift作为一种新的编程语言。 由于Swift,开发人员找到了Objective C的替代品。Swift是一种功能强大且直观的语言,适用于iOS,OS X,电视OS和watchOS。 随着Apple删除了不安全的指针管理并引入了强大的新功能,Swift成为了Objective C的很好替代。 多亏了闭包,泛型和类型接口等许多关键功能,使用起来更加轻松。 根据RedMonk的说法,Swift将接管Objective C.2018年,Swift在十大编程语言中排名更高。 逐渐地,Swift成为开发人员的最爱。 Swift快速,安全,现代化,并在开发中实现了一定程度的交互性。 Swift有潜力创建引人入胜的,灵活的,对用户友好的应用程序。 苹果推出Swift之后,iOS世界中发生了许多争论。 Swift已成为许多组织讨论的中心。 无论是选择Objective C还是Swift,都成为开发人员永无休止的争论。 Swift是一种有效的编程语言。 为了了解Swift是更好的还是Objective C,我们需要确定Swift和Objective C之间的关键特性。毫无疑问,Swift解决了Objective C的许多缺点。即使根据Upwork,Swift是增长最快的技能适用于初创企业和自由职业者。 让我们了解为什么Swift比Objective C更好。 在Objective C上使用Swift的原因 1少代码 Swift是用于编程的更紧凑的语言。 使用Objective C,有很多导致应用崩溃的问题。 Swift减少了重复语句和字符串操作所需的代码量。 在使用Objective C时,您将需要组合两个字符串以使其冗长。 而且,类不分为两部分:接口和实现。 这样可以将项目中的文件数量减少一半,这使得处理起来更加容易。 因为在Swift中,程序员不必更新和维护两个文件。 让我们以著名的应用程序Lyft为例。 该应用已用Swift重写。 您会惊讶地发现应用程序代码从75000行增加到25000行。 与Objective-C冗长的编码相比,Swift最终使您的工作更加轻松。 2更快 与C ++一起,Swift是程序员最快的编程语言。 Swift的速度将帮助您节省成本。 例如,复杂对象的运行速度比Python中相同算法的实现快3.9倍。 它实际上比Objective C更好,后者仅比Python快2.8倍。 2014年12月,Primate […]
应用程序安全性是软件开发最重要的方面之一。 我们应用的用户希望他们的信息被保密。 我们的敏感应用程序数据不应简单地泄露出去。 幸运的是,在本文中,我们将讨论开发人员在应用安全性方面所犯的错误以及如何轻松修复它们。 将敏感数据存储在错误的位置 我从AppStore研究了多个应用程序,其中许多应用程序都在犯同样的错误,将敏感数据存储在不属于它们的地方。 如果要将敏感数据存储在UserDefaults ,则可能会UserDefaults应用程序信息的风险。 UserDefaults只是作为属性列表文件存储,位于应用程序的Preferences文件夹中。 它们会保存在我们的应用中,而不会以任何形式进行加密。 基本上,通过使用示例中的iMaczing这样的第三方mac应用程序,甚至无需越狱设备,您就可以轻松查看从AppStore下载的任何应用程序的UserDefaults数据。 这些Mac应用程序经过专门设计,可让您浏览和管理iPhone上的第三方应用程序文件。 而且,您可以轻松浏览任何应用程序的UserDefaults 。 促使我写这篇文章的原因是,我发现从AppStore安装的许多应用程序都将其敏感数据写在User Defaults上。 例如访问令牌,活动可更新订阅标志,可用硬币数量等。 从免费使用付费功能到入侵网络层等等,所有这些数据都可以轻松检索和更改,并损坏应用程序。 正确的做法 在iOS应用程序上保存数据时,请始终牢记一件事, UserDefaults旨在仅保存少量数据,例如应用程序内用户的首选项,这是完全不敏感的。 为了保存我们的应用程序敏感数据,我们应使用Apple提供的安全服务。 钥匙串服务API通过为您的应用提供一种将少量用户数据存储在称为钥匙串的加密数据库中的方法,可以帮助您解决这些问题。 在钥匙串中,您可以自由保存用户明确关心的密码和其他机密信息,例如信用卡信息,甚至是简短的敏感便笺。 您还可以存储由证书,密钥和信任服务管理的项目,例如加密密钥和证书。 钥匙串服务API 下面我们将描述如何在钥匙串中保存用户密码。 查询字典部分kSecClass:kSecClassGenericPassword指示该项目是密码,钥匙串服务可从中了解数据需要加密。 然后,通过使用创建的查询调用SecItemAdd ,将新密码添加到钥匙串中。 检索数据类似 我们可以编写一个简单的测试来确保正确保存和检索数据 如果您必须保存多个密码,一开始使用Keychain API似乎有点复杂。我鼓励您为其创建外观,以帮助您根据应用程序使用情况以最佳方式保存和修改数据。 如果您想进一步了解外观模式以及如何为复杂的子系统创建简单的包装器,那么本文将对您有很大帮助。 另外,有许多开源库使Keychain API的使用更加简单。 其中一些是SAMKeychain和SwiftKeychainWrapper。 保存密码并执行身份验证 在我作为iOS开发人员的职业生涯中,我看到相同的错误不断重复出现。 很多时候,开发人员要么将原始密码保存在应用程序中以重复使用,要么直接使用用户名和密码发出登录网络请求。 如果您将密码直接存储在UserDefault那么现在应该知道本文第一部分提供的信息UserDefault您造成多少风险。 将密码保存到钥匙串可以提高安全性,但是,再次,我们应该始终通过初始加密将密码和其他敏感信息保存到钥匙串或其他地方。 假设攻击者可以通过钥匙串安全性进行黑客攻击或通过我们的网络进行攻击,从那里他可以直接以原始文本的形式检索我们的密码。 更好的方法是存储密码,并将其用于登录请求,作为为此密码构建的哈希。 加密敏感数据 自己实现散列可能非常复杂且过大,因此在本文中,我们将使用开源iOS库CryptoSwift的帮助。 CryptoSwift是在Swift中实现的标准安全加密算法的不断增长的集合。 让我们尝试使用CryptoSwift提供的算法在钥匙串上保存和检索密码。 此方法使用帐户和密码,并将散列的字符串而不是直接字符串保存在钥匙串上。 让我们分解一下这种方法正在发生的事情 salt是用于混合密码的唯一字符串。 sha256完成类型SHA-2哈希 HKDF是基于基于哈希的消息认证码(HMAC)的简单密钥派生功能(KDF) 我们制造盐以使我们更容易受到攻击。 […]
通常,作为iOS开发人员,您可能会发现自己正在开发与API通信的应用程序。 该API可能是与您合作的公司构建的内部API,因此可能存在一些环境。 这意味着您很可能要承担在这些环境/端点中的每一个处进行构建的任务。 我们不想做的就是将这些端点放入我们的代码中,以便每次我们需要进行指向特定环境的构建时,都需要进行代码更改。 如果您想真正有所帮助,则允许组织中的人员同时运行这些不同的版本。 这意味着测试人员可以同时在同一设备上安装其暂存/ dev / live构建。 我讨论了如何在这里进行设置。 该帖子的要旨是,您要分发的每个App需要一个不同的捆绑包标识符。 这篇文章将使用该文章的原理,因此请务必阅读。 使我们的端点成为Xcode环境变量⛳️ 在执行任何操作之前,我们需要为要使用的环境准备Xcode配置。 正如我在上一篇文章中提到的,我们通过添加Xcode配置来做到这一点。 随时进行调整,但基本设置如下所示: 我通常具有生产和App Store配置,因为我喜欢区分针对生产的内部构建与提交给商店的最终构建。 这样,我可以关闭非App Store版本的分析之类的功能。 现在,您要转到目标的构建设置。 我们将创建一个新的用户定义设置,出于所有意图和目的,我的名称将称为MY_API_BASE_URL_ENDPOINT 这为我们提供了一个环境变量,该变量将根据我们运行的配置而变化。 不幸的是,我们还不能在代码中使用它,因为我们不能在Swift中使用环境变量的值。 我们可以做的是将此映射到我们的Info.plist文件。 现在,当我们想在代码中访问它时,它非常简单: 让env = NSBundle.mainBundle()。infoDictionary![“ MY_API_BASE_URL_ENDPOINT”]为! 串 更进一步🏋 我喜欢在调试配置中非常灵活,以便可以在任何给定时间调整端点。 为了获得这种行为,我们可以添加快速编译器标志,以便我们可以在代码中执行宏检查。 通常,我喜欢使用一个标志来表示调试模式和App Store模式: 现在,我们可以在调试模式下更改环境。 因此,假设我们有一个配置类,其定义我们的环境的方式如下: 结构配置{ #if调试 枚举环境:字符串{ 案例制作=“ www.galasko.com” 案例开发=“ www.galasko-dev.com” 案例分期=“ www.galasko-staging.com” } 让环境= Environment.Staging.rawValue //我们可以随时更改 #其他 让环境= NSBundle.mainBundle()。infoDictionary! [“ […]
正如任何iOS开发人员所知,网络是任何移动应用程序的重要组成部分。 当苹果公司在iOS 7中引入URLSession时,社区就敞开了怀抱。 新的API是对旧版URLConnection API的重大改进。 在Bottle Rocket,我们始终在为客户构建应用程序时试图在效率与可维护性之间寻求平衡。 因此,我们通常会直接在URLSession上从头开始编写网络代码。 从可维护性的角度来看,这非常好-使我们的网络代码与Apple的SDK保持同步非常容易。 但是,随着我们的成长,我们意识到经常需要重复编写一些通用的样板化网络代码。 我们决定编写自己的解决方案,而不是使用第三方解决方案(其中许多解决方案非常繁琐)。 我们最近以Apache 2.0许可在GitHub上开源了Hyperspace。 在构建Hyperspace时,我们有一些目标: 减少您需要手工编写的HTTP模板。 这包括定义HTTP方法,状态代码和标头之类的内容。 保持轻巧—开箱即用即可轻松便捷地处理90%的网络用例。 这包括指定您希望从请求中获取的模型类型,以便可以使用Swift 4的Codable协议的魔力自动对其进行解析。 保持简单-我们想让任何人都容易做出贡献。 整个图书馆约为600个SLOC。 将超空间添加到您的项目 将Hyperspace添加到项目中后,您将立即启动并运行。 只需将Hyperspace添加到您的Podfile中(不久将添加对其他依赖项管理器的支持): 吊舱“超空间” 定义网络请求 定义请求很简单。 只需创建AnyNetworkRequest的实例并指定您的请求参数: 让someRequest = AnyNetworkRequest (方法:.post, url:URL(string:“ …”)!, 标头:[。contentType:.applicationJSON], 正文:postBody) 注意, Model是指您的请求的成功模型响应类型。 这意味着,如果您请求的响应类型符合Decodable ,我们将为您自动处理解码。 还要注意, method和headers参数依赖于预定义的类型。 不再有容易出现拼写错误的“字符串型” API! 执行网络请求 BackendService的工作就是执行您的网络请求。 只需创建一个BackendService ,然后调用其execute()方法即可: 让backendService = BackendService()backendService.execute(request:someRequest){(结果)在 切换结果{ case .success(让responseObject): //请求成功 […]
我不是iOS开发专家。 经过一个月的学习,我最近开始在Swift中为多个行业开发应用程序。 我确实喜欢每个初学者,并打开了Apple文档,并遵循了他们的指南。 苹果公司推荐的模式是MVC模式。 我按照大家都知道并珍惜的Model View Controller的经典原理开始构建自己的第一个应用程序。 从表面上看,iOS开发中的MVC模型与我们多年来使用的模型没有什么不同。 对我来说不幸的是,我一直对软件体系结构,简洁的代码和漂亮的软件感兴趣,因此将iOS和MVC结合使用非常麻烦。 几周后,随着视觉和幕后应用程序变得越来越复杂,问题就显而易见了。 在为iOS开发时,您的视图(也称为Storyboard)是一个简单的XML文件,其中包含所有不同的组件以及它们的坐标和约束。 这样做的结果是,与实例的实际功能相比,负责实例化和管理这些视图的ViewController文件变得混乱而庞大。 您开始在同一类中查看混合在一起的不同关注点:路由,模型处理,动画,视图填充…都在一起💀。 这种使用起来令人困惑和痛苦的方法,通常被称为Massive View Controller综合症。 于是去寻找其他选项,然后在此处输入MVVM 。 MVVM模式或模型视图ViewModel围绕应将模型处理和视图处理分开的想法而展开。 这样可以实现更好的可测试性,可读性并易于开发。 为此,我们将ViewController分为二。 View (仍然继承自Apple ViewController类)将填充视图并管理动画。 屏幕上显示的所有内容均受其控制。 ViewModel负责与API,数据库和其他信息源进行交互,并提取与其相应视图有关的信息。 实例化视图时, View将自身绑定到其ViewModel并将根据ViewModel提供的数据进行更新。 有多种方法可以实现这一点,但是Swift提供的我的首选方法是通过闭包。 为了说明这一点,让我们想象一个打印当前日期的愚蠢视图。 我们可以从设计ViewModel开始: 简单的ViewModel示例 这里, ViewModel公开了一个变量和一种方法。 fetchDate()方法将获取当前日期并为其分配一个私有变量。 每次设置此变量时,都会调用一个可选的公共方法updateDate 。 此方法是一个公共变量,可以通过View设置这样的方法: 简单检视 实例化ViewModel , View会将其闭包简单地附加到其ViewModel的公开变量,然后触发获取。 如果需要,setupView方法将使用初始内容填充视图。 当获取成功完成并且在fetchDateFromApi函数上updateDateClosure了回调时,将updateDateClosure并更新标签。 所有这些异步且易于维护。 唯一令我烦恼的是, View仍然必须通过prepareForSegue和其他方法来处理路由。 在实现表示和模型处理之间的清晰分离之后,我们不能简单地乐于在这种情况下进行路由。 为了解决这个问题,我创建了一个简单的路由器协议(与旧接口的Swift等效): 基本但清晰的路由器实现 viewController的init方法是一种便捷的init方法,无需查找相应的Storyboard 。 枚举和协议只是为了清楚起见。 但这使我们可以在文件中简单引用此路由器: 将路由器添加到先前的类中 […]
在上一篇文章中,我们介绍了基本协议,扩展和下标。 开始进行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 […]
在本文中,我将向您介绍如何使用情节提要上的UIButton实现自定义设计的Google登录按钮。 使用Cocoapods创建Pod文件,然后安装Pod进行Google身份验证。 pod’GoogleSignIn’ 转到https://developers.google.com/identity/sign-in/ios/start-integrating获取AuthO ID。 如果尚未创建Firebase项目,请在此步骤之前创建它。 在项目导航栏中单击您的项目名称,然后转到“目标”->“信息”->“ URL类型”。 然后,点击“ +”按钮,并将您反向的客户ID添加到“ URL方案”。 您可以从“ GoogleService-Info.plist”中REVERSED_CLIENT_ID的列表名称中获取反向客户ID。 为了实现实际的登录功能,您可以像下面的代码那样编写。 AppDelegate.swift func application(_ application:UIApplication,didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:Any]?)->布尔{ FirebaseApp.configure() 返回真 } func application(_应用:UIApplication,打开url:URL,选项:[UIApplicationOpenURLOptionsKey:任意])->布尔{ 让处理= GIDSignIn.sharedInstance()。handle(URL,sourceApplication:options [UIApplicationOpenURLOptionsKey.sourceApplication] as?字符串,注释:[:]) 退货处理 } ViewController.swift 导入UIKit 导入Firebase 导入GoogleSignIn类ViewController:UIViewController, GIDSignInDelegate,GIDSignInUIDelegate {覆盖func viewDidLoad(){ super.viewDidLoad() GIDSignIn.sharedInstance()。delegate =自我 GIDSignIn.sharedInstance()。uiDelegate =自我 } //使用Google窗口 @IBAction func googleSignIn(sender:AnyObject){ GIDSignIn.sharedInstance()。signIn() } func sign(_ signIn:GIDSignIn !, didSignInFor用户:GIDGoogleUser !, […]
更新用户界面示例 为什么要远程配置 从文档 无需更改应用程序的行为和外观,而无需免费发布应用程序更新,无限制的每日活跃用户。 您应该在firebase中有一个iOS项目。 如果您想设置Firebase,可以检查 一下 创建参数 您可以将参数创建为键和值,例如将show_label作为键,将true作为值创建,但是最佳做法是创建JSON具有相关值以将Internet请求限制为Firebase 将值设为login_screen且该值为JSON与此屏幕具有相关值 在GitHub中进行项目 dimohamdy / RemoteConfigExample 通过在GitHub上创建一个帐户为dimohamdy / RemoteConfigExample开发做出贡献。 github.com 参考 Firebase远程配置| 火力基地 无需更改应用程序的行为和外观,而无需发布应用程序更新,而无需任何费用,每天无限制的活动… firebase.google.com 关于作者 这是我的GitHub,投资组合和其他内容,如果您有任何疑问或与我联系电子邮件,请与我们联系。 dimohamdy –概述 @Integreight的iOS开发人员,当前为@Iqraaly。 在Twitter上以@dimohamdy找到我。 – dimohamdy github.com 艾哈迈德·哈姆迪(@dimohamdy)| 推特 Ahmed Hamdy(@dimohamdy)的最新推文。 iOS工程师👨🏻💻 @iqraaly和@ 1sheeld。 #区块链爱好者… twitter.com
第1部分 什么是NSNotification? NSNotificationCenter对象(或简称为通知中心)提供了一种在程序内广播信息的机制。 NSNotificationCenter对象本质上是一个通知调度表。 addObserver:selector:name:object:或addObserverForName:object:queue:usingBlock:方法 2.委托和通知之间的区别? 代表就像电话一样,您可以知道哪个班级正在向哪个班级传递消息。 通知就像无线电广播一样,其中一个类别触发的通知不会被准备收听/捕获通知并相应执行操作的任何类别或所有类别接收。 3. NSRunLoop? NSRunLoop对象处理来自窗口系统,NSPort对象和NSConnection对象的源输入,例如鼠标和键盘事件。 NSRunLoop对象还处理NSTimer事件。 您的应用程序既不创建也不显式管理NSRunLoop对象。 每个NSThread对象(包括应用程序的主线程)都有一个根据需要自动为其创建的NSRunLoop对象。 如果需要访问当前线程的运行循环,请使用类方法currentRunLoop进行访问。 4.强,弱和保持周期? 这些是与内存管理引用计数和所有权有关的属性。 强属性:当任何对象A对其他任何对象B都有强引用时,则意味着A需要B通过将其引用计数加1 ..在内存中存在,而在相同情况下B对A的引用具有弱属性,则意味着A引用了A而不需要在内存中保存其引用计数。这样,它还可以管理保留释放周期。 5.如何使用核心运动/核心位置获取两点之间的估计时间? 使用CoreLocation,我们可以计算从一点到第二点所花费的时间。 在每个位置点的核心位置,我们也有时间戳记。 使用此时间戳,我们可以计算对象的速度。 6.什么是核心数据以及核心数据和SQLite之间的区别。 两者之间存在巨大差异。 SQLLite本身就是一个数据库,就像我们拥有MS SQL Server一样。 但是CoreData是一个ORM(对象关系模型),它在数据库和UI之间创建一个层。 它加快了交互过程,因为我们不必编写查询,只需与ORM一起使用,并让ORM处理后端。 对于大数据的保存或检索,我建议使用Core Data,因为它具有处理设备处理速度较慢的功能。 7. Nsurlconnection与nsurlsession? NSURLConnection组成基础URL加载系统的一组相互关联的组件:NSURLRequest,NSURLResponse,NSURLProtocol,NSURLCache,NSHTTPCookieStorage,NSURLCredentialStorage及其同名NSURLConnection NSURLRequest对象被传递到NSURLConnection对象。 委托(遵从以前的非正式协议和协议)作为NSURLResponse异步响应,并且从服务器发送所有关联的NSData在将请求发送到服务器之前,先查询共享缓存,并且根据策略和可用性,缓存的响应可以立即透明地返回。 如果没有高速缓存的响应可用,则发出带有为任何后续请求高速缓存其响应的选项的请求。 在与服务器协商请求的过程中,该服务器可能会发出身份验证质询,该挑战可以由共享cookie或凭据存储或连接委托自动处理。 已注册的NSURLProtocol对象也可以拦截传出的请求,以根据需要无缝更改加载行为。 除了同义的类NSURLSession外,NSURLSession还引用了一组相互依赖的类。 NSURLSession由与以前相同的部分组成,包括NSURLRequest,NSURLCache等,但是用NSURLSession,NSURLSessionConfiguration和NSURLSessionTask的三个子类替换了NSURLConnection:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。 NSURLSessionTask是一个抽象子类,具有三个可直接使用的具体子类:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。 这三个类封装了现代应用程序的三个基本联网任务:获取数据(例如JSON或XML)以及上载和下载文件。 8.使用仪器,为什么要使用? 仪器用于检查内存消耗和其他原理图。 9.了解MVVM,VIPER和其他吗? 遵循https://auth0.com/blog/compare-mvvm-and-viper-architectures/ 10. Swift比Objective-C有什么好处? Swift更容易阅读。 Swift更易于维护。 Swift更安全。 Swift与内存管理统一。 Swift需要更少的代码。 […]
Swift范围比NSRange更复杂。 如果您想尝试了解这种复杂性背后的原因,请阅读此内容。 我将仅向您展示如何创建它们以及何时使用它们。 封闭范围: a…b 即使b是类型的最大可能值(如Int.max ),此范围运算符也会创建一个同时包含元素a 和元素b的Swift范围。 封闭范围有两种不同类型: ClosedRange和CountableClosedRange 。 1. ClosedRange Swift中所有范围的元素都是可比较的(即,它们符合Comparable协议)。 这样您就可以访问集合中范围内的元素。 这是一个例子: let myRange: ClosedRange = 1…3 let myArray = [“a”, “b”, “c”, “d”, “e”] myArray[myRange] // [“b”, “c”, “d”] 但是, ClosedRange不可计数(即,它不符合Sequence协议)。 这意味着您不能使用for循环遍历元素。 为此,您需要CountableClosedRange 。 2. CountableClosedRange 这与最后一个相似,除了现在还可以迭代范围。 let myRange: CountableClosedRange = 1…3 let myArray = [“a”, “b”, “c”, “d”, “e”] […]