如果您曾经构建过iOS应用程序,则可能遇到了必须代表用户存储敏感信息的情况。 为此,Apple的钥匙串服务就是您的最佳选择。 since自从iOS SDK的第一个公开版本(iOS 2.0)以来,钥匙串服务就已经成为Apple安全框架的一部分。 与UserDefaults不同,钥匙串为您提供了一种安全的方式来在加密的数据库中存储密码,信用卡信息甚至便笺。 在我职业生涯的早期,由于苹果提供的API不友好,我被告知要使用框架包装Keychain Services。 尽管我当时对第三方框架提供的界面感到非常满意,但我还是想了解该平台提供的服务的来龙去脉。 您可以在下面阅读有关我的学习内容。 钥匙串服务包括两个主要部分:一个加密的数据库(由SecKeychain类表示)和插入到数据库中的项(由SecKeychainItem类表示)。 在iOS中,只有一个钥匙串存储(封装了您的iCloud钥匙串),除了CRUD操作之外,没有API可以创建或操作默认钥匙串。 钥匙串会自动同时与设备锁定和解锁,因此无法进行未经授权的访问。 另一方面,在Mac OS中,您可以创建和管理自己的钥匙串存储(安装时会创建4个:登录,iCloud,系统,系统根-您可以在钥匙串访问应用程序中对其进行浏览)。 SecKeychainItems是隐藏在Security框架内的不透明类型,由两部分组成: 数据和一组属性 ,这些属性有助于标识和存储元数据或控制对存储项的访问。 当将要插入新项目时,钥匙串服务首先加密数据,然后将其与公共属性包装在一起。 请参见下图。 由于SecKeychainItems处于隐藏状态,因此Apple提供了一组API以使用CFDictionary类型与钥匙串进行交互。 您可以添加,修改,删除和搜索特定的钥匙串项,甚至可以修改其访问控制。 这些是特殊类型的属性,用于定义如何处理钥匙串项目。 截至2018年,共有5种物品类别: 通用密码项目 互联网密码项目 证书项目 加密关键项目 身份项目 每个类都支持一组特殊的属性。 您可以通过单击上面提供的链接来检出它们。 Apple定义了一组键值对,以帮助您使用字典为键链项目设置属性。 这些键值项按上述钥匙串项类型分类: 常规项目属性键 密码属性键 证书属性密钥 加密密钥属性密钥 认证类型值 关键类别值 同步性值 还有很多 … 现在,为了帮助您更好地理解这一点,我将向您展示如何将Internet密码存储在钥匙串中。 观察到我将密码用作钥匙串项目的数据,并使用了另外三个属性来提供其他信息。 在我的示例中, kSecClass告诉我们要存储在钥匙串中的项目的类型, kSecAttrServer是服务器地址属性,特定于Internet密码类型的项目,而kSecAttrAccount拥有特定Internet服务的帐户。 一旦将数据安全地存储在钥匙串中,您就可以通过它们的属性来查询这些项目。 存储有关特定元素的足够信息将帮助您将搜索结果范围缩小到要查找的内容。 使用kSecAttrLabel,您还可以标记商品,以便以后更好地找到它。 让我们看看如何检索数据。 要更新或删除项目,可以使用更简单的查询,而无需让Keychain返回任何属性( kSecReturnAttributes , kSecReturnData […]
大家好! 我参加过2018年东京尝试!Swift大会,那真是太棒了,不仅因为它在东京,这是我第三次在东京参加会议,但这是我第一次参加iOS大会,与会的令人惊讶的人们一直是其中的一员我作为开发人员的职业生涯中最伟大的经验。 我们迟到的第一天,我们的航班延误了,他们丢了一个我们的行李T_T。 当我们第一次参加会议时,我们真的很兴奋,我们想见到来自世界各地的人们,他们的态度与我们相同,有数百人出于一个原因,揭露他们与我们心爱的语言有关的工作迅速。 因此,我们抓住了徽章并进入了大厅,真是太神奇了。 真的很拥挤,每个拿着Macbook的人都在等着第一次演讲。 传给我们的感觉就像……天哪,我们正在尝试!迅速的东京! 我们是这样的: 当我们第一次进入大厅时我们的脸 这些是我最喜欢的一些演讲: 我最惊讶的演讲之一。 诺曼在演讲中介绍了SwiftNIO,它是一个跨平台的异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端,例如Netty,但是为Swift编写的。 听到苹果一位软件工程师的来信,我感到非常兴奋。 这次演讲真是太神奇了,健太郎向我们展示了他是如何通过使用机器学习以一种凉爽的方式提高漫画分辨率来实现的。 人群就像:“哇!”,当他按下应用程序中的按钮时,分辨率提高得如此之快,以至于您可以看到面孔和字母上的改进。 我对这次演讲印象深刻,想开始学习。 (剧透警报:我正在研究“ iOS的Tensorflow教程”系列:P,但那是另一个故事)。 3月3日,他们组织了研讨会,我去了: 在本研讨会中,我们正在使用结构和分类来比较可变性,不变性与值类型和引用类型。 我们创建了一个简单的战斗应用程序,在其中我们与邪恶的生物进行战斗,同时还了解了价值和参考类型之间的差异。 如果您可以边玩边学,那么您做对了。 我们的老师是最好的 在这里,您可以找到我们在研讨会上遇到的简单问题: 游戏:https://swift-quest.github.io/battle-en.html GitHub:https://github.com/tarunon/try-erasure 好吧,我只是想向您展示一些您可以期待的演讲,如果您参加此类活动。 我想与您分享我的经验,并鼓励您,如果您正在启动iOS或您有经验,但是从未经历过此类事件,则必须开始这样做。 您将遇到真正的好人,非常了解的人,您将意识到如何提高自己以像在那儿讲话的人那样。 对我而言,我感到鼓舞,因为我看到伟大的人谈论他们的POC或他们想与我们分享一些发展,我希望有一天成为其中的一员。 我将尽全力确保这种情况发生。 我回到家不仅学到很多东西,而且有动力推动自己走得更远,这真是太好了。 现在,我正在考虑下一次会议将要召开,但是我肯定会考虑明年再来尝试Swift Swift Tokyo。 我要感谢NatashaTheRobot和所有组织者使这次活动成为可能。 我为离开东京感到难过,但我知道我迟早会回来的。 如果您想了解更多关于尝试! Swift Tokyo 2018讲座或获取2019年版门票,您可以在这里找到链接: 试试吧!迅捷 尝试! 斯威夫特东京2018会谈 希望您喜欢这篇文章,感谢您的阅读。
打开终端类型后: cd“ projectDirectoryName” 然后按Enter。 通过同时按住命令和空格以启动查找器,可以轻松完成此操作。 然后键入项目名称,并将项目文件夹拖到终端中,以便它自动输入项目目录名称。 之后,您可以使用以下命令创建Pod文件: 荚初始化 在XCode编辑器中打开pod文件,并添加以下代码行: 目标“ YOUR_APPLICATION_TARGET_NAME_HERE” pod’GoogleMaps’ pod“ GooglePlaces” 结束 之后,保存pod文件,并返回到终端以及项目上的目录位置。 然后运行命令: 吊舱安装 吊舱安装完成后,关闭XCode并恢复与.xcworkspace的会话以进行项目中的所有持续开发。 第2步:获取Google Maps API密钥并添加到应用程序 这是获取Google Maps API密钥的链接:https://developers.google.com/maps 获取API密钥后,打开XCode应用程序并导航到AppDelegate.swift添加: 导入GoogleMaps 将以下内容添加到application(_:didFinishLaunchingWithOptions :)方法中: GMSServices.provideAPIKey(“ YOUR_API_KEY ”) 对于places API: GMSPlacesClient.provideAPIKey(“ YOUR_API_KEY ”) 在ViewController中添加以下内容: 导入UIKit 导入GoogleMaps 类ViewController:UIViewController { 覆盖func viewDidLoad(){ super.viewDidLoad() //创建一个GMSCameraPosition来告诉地图显示 //在缩放级别6处协调-33.86,151.20。 let camera = GMSCameraPosition.camera(withLatitude:-33.86,经度:151.20,缩放:6.0) 让mapView = GMSMapView.map(withFrame:CGRect.zero,camera:camera) mapView.isMyLocationEnabled […]
假设您希望定义一系列看起来相同的结构。 例如: 并且假设您要避免代码重复 。 如果您使用的是类,则可以使它们成为同一类的所有子类 。 但是有充分的理由避免在Swift中使用子类。 特别是它们在通用协议一致性方面表现不佳,这是我完全避免在我的大多数代码中完全避免它们的一个原因。 您可以尝试使它们全部符合特定协议 ,但不能通过协议扩展添加存储的属性或初始化程序(可以添加初始化程序,但它需要调用另一个必需的初始化程序)。 这是一个不错的解决方案,并且为复杂的代码库提供了一个出奇的灵活解决方案:使用特定的类型参数将它们全部变成相同的通用结构,即使这些类型参数是空结构: 这些说明符类型称为“幻像类型”,它们出奇的强大。 这个想法也适用于更复杂的场景。 在下面的示例中, x和y的类型变为通用类型,并且为每个结构分配了不同的静态名称。 或者,您可以使Unit成为Specifier本身的关联类型🙂
SequenceType和CollectionType具有一个很酷的名为lazy属性。 Apple将lazy定义为:“一个包含与该序列相同的元素的序列,但是在其上懒惰地实现了某些操作,例如map和filter 。” 最好用一个例子来说明。 假设我们有以下代码: //创建一个包含1到1,000的数字的数组。 变数= [Int]() 数字+ = 1…1_000 让newNumbers =数字 .filter {$ 0%2!= 0} //已执行1,000次 .map {$ 0 * 10} //执行500次 打印(“ \(newNumbers.last)”) 如果要访问newNumbers的最后一个元素或任何元素,则必须执行构建newNumbers数组所需的每一个计算。 那是`filter`的1000次迭代,而map另外500次。 现在,更懒惰的: //创建一个包含1到1,000的数字的数组。 变数= [Int]() 数字+ = 1…1_000 让newNumbers = numbers.lazy .filter {$ 0%2!= 0} //仅执行3次 .map {$ 0 * 10} //仅执行1次 打印(“ \(newNumbers.last)”) 这次,我们只完成了filter三个迭代,以及map一个迭代。 因为我们使用了lazy序列属性,所以实际上返回了一个新类型( LazyMapBidirectionalCollection ),而不是简单的数组。 […]
WebCollector是一个可以在iOS上拍摄网页完整屏幕截图的应用程序。 当前总下载量为29.4万个单位。 我收到了用户的电子邮件。 我无法在iOS 11上使用WebCollector。请更新… 因此,我决定通过接收此电子邮件来续订。 仅支持32位设备 太多的旧图书馆 所有代码均由Objective-C编写 火力基地 我决定将Firebase用作后端系统。 数据库是Firestore ,联系人是Cloud Functions , Firebase存储上的图像。 RxSwift 我使用UIStackView制作了一个工具栏,因此可以将RxWebKit的isHidden属性绑定。 代码是这样的。 webView.rx.canGoBack.map {!$ 0} .bind(发送至:topToolbar.backButton.rx.isHidden).disposed(发送方:disposeBag) webView.rx.canGoForward.map {!$ 0} .bind(发送至:topToolbar.forwardButton.rx.isHidden).disposed(发送方:disposeBag) webView.rx.loading.bind(发送至:topToolbar.reloadButton.rx.isHidden).disposed(发送方:disposeBag) webView.rx.loading.map {!$ 0} .bind(发送至:topToolbar.stopButton.rx.isHidden)。disposed(发送方:disposeBag) 。 。 。 我做了这样的扩展,然后我就可以轻松截图了。 XCTestCase扩展名{ func屏幕截图(_命名为:字符串){ XCTContext.runActivity(named:named,block:{活动在 让屏幕截图= XCUIScreen.main.screenshot() 让附件= XCTAttachment(屏幕截图:屏幕截图) attachment.lifetime = .keepAlways activity.add(附件) }) } } 我将午餐与UITest一起使用,因此可以使用视图名称启动ViewController目录。 导入XCTest 导入LunchTest 最后一个类OtherViewControllerTest:XCTestCase,ViewControllerTestable { […]
设计模式是针对软件工程问题的不同解决方案。 没有它们就可以构建软件 但要困难得多。 我将发布有关设计模式的三部分系列。 在这篇文章中,我将讨论创意设计模式。 创建设计模式是处理对象创建机制的设计模式,试图以适合情况的方式创建对象。 对象创建的基本形式可能会导致设计问题或增加设计的复杂性。 创新设计模式通过某种方式控制此对象的创建来解决此问题。 资料来源:Wikipedia.org 在这里,我们将讨论五个创新设计模式以及如何快速使用它们。 这种类型的设计模式用于通过克隆称为原型的现有对象来实例化新对象。 您会看到Apple类实现的Fruit协议的抽象克隆函数,该函数实际上返回当前对象本身。 让我们在操场上运行上面的代码。 //创建原型 let prototype = Apple(count:4)//创建现有对象的副本 让redApple:Apple = prototype.clone()为! 苹果 redApple.count // 4 //添加自己的属性 redApple.set(价格:“ $ 2”) redApple.price // $ 2 //创建现有对象的副本 让greenApple:Apple = prototype.clone()为! 苹果 greenApple.count // 4 //添加自己的属性 greenApple.set(价格:“ $ 4”) greenApple.price // $ 4 • 克隆对象时,该对象的所有属性都将复制到 另一个对象。 •当您需要创建对象而又不知道该类的层次结构时,应使用此设计模式 这是最常用的设计模式。 基本上,它只是抽象对象的创建。 […]
本文应该是很久以前写的,但碰巧的是,当您玩得开心时光飞逝。 我的前同事约翰·桑德尔(John Sundell)去年(2017年)进行了一场路演,但他一直在质疑我们如何进行开源并为此获得报酬。 现在是时候揭开秘诀了。 它可能不像您想的那样秘密。 开源是我非常关心的事情,实际上,我在2017年Mobil时代谈到了这一点。 一切如何开始 在加入公司之前,Hyper的开源就开始了。 它基于这样一个简单的前提:如果我们要使用开放源代码,那么我们也应该做出贡献,通过帮助现有项目或在Hyper的保护下创建新的开放源代码。 害怕做开源 当我申请Hyper职位时,我会给你一个秘密,我从来没有做过iOS应用程序,反正做得不好。 哎呀,我什至不知道使用表视图时出队,更不用说我曾经公开发布过任何代码了。 我输入了一个全新的域。 但是,我确实有OS X开发方面的业余经验。 数周以来,我感到害怕,因为我被贴上欺诈的标签,比进入后的轿车门缩回更快,被赶出了公司。 对我来说幸运的是,Hyper是一个超级办公的好地方,其核心是协作和知识共享。 我很快学会了正确地完成工作所必须要做的事情,但是我仍然有一个很大的恐惧,那就是公开地与公司的核心价值发生冲突,这就是对开源的恐惧。 我不能全神贯注于会带来什么,我只是将其视为发现我作为蛇油推销员的另一种方式。 进行开放源代码开发的领先者是Web团队,他们在Ruby on Rails上投入了大量资金,并生产了与社区自然共享的出色宝石。 碰巧,我为Hyper发布的第一个开源软件是一个名为singleton-rails的红宝石,我的同事Tim Kurvers承担了繁重的工作,我或多或少只是将其推到rubygems.org。 即使在这种情况下,我仍然很害怕在公开场合露面我的名字。 早在2014年,“过去”就被吓呆了。 如果我可以放心,我会拥抱他,告诉他一切都会好起来的。 说明开放源代码无所畏惧,但值得拥抱,美好时光已经来临。 然后,我将摘下他的锡箔帽子,称赞他的头发。 “宇宙不会围绕你旋转!” —将来我给过去的我一些建议 我知道很多人对此感到害怕,当这样的事情出现在Twitter上时,谁能责怪他们。 我知道作者对该推文没有害处,但很快就升级为在线嘲讽。 我什至为在Slack上开个玩笑而感到内,,因为它缺乏排序对我的OCD造成了伤害。 但是,即使我的评论是私人的,我也应该知道得更多。 如果这确实使我感到困扰,那么我本可以进行PR来纠正问题,而不是取笑别人的源代码。 我当然不希望任何人对我这样做,如果他们在我的代码中找到了任何恶作剧,我很希望PR来解决。 如何开始 在Objective-C和Swift过渡期间,我们的团队完成了迄今为止最大的项目之一。 一个明显的问题暴露出来,我们选择哪种语言。 我们对此进行了许多回合,来回跳动,弹出了不同的论点,这些论点被无效和纠正。 最终,我们登陆了Swift。 这给了我们在社区中编写纯Swift框架的独特位置,这在当时是一个真正的热门话题。 我们是由四个开发人员负责该项目的,因此决定将项目拆分为不同的功能,并为应用程序的每个部分组成微型团队。 每个功能都有自己的规范,我们共同检查了所有这些规范,并一致决定可以将哪些部分提取到框架中。 通常会导致规模扩大的两个主要原因,第一个是“我们能否在其他应用程序中利用此功能”这个问题的结果,另一个是:“如果这是它自己的组件,它将加快开发速度。”
切るだけで简単 SwのSwift ・ iOSコラムパブリケーションションショ书かせてもらうことになりました。よろしくお愿いします。 详解Swift Swfitについて解说した本“详解Swift”の新しいバージョンが出ます。このバージョンはSwift3に対応しています。 现在は断片的な情报ならWeb上で得ることが多いのですが,本のようにまとまっているものも便利な事件はあると思います。私自ある分野に关してまとめて情报を仕入れたいときは本のほうがいいです。他言语でがりがり书いて来た人が配置転换でSwiftが必要になり,基本的を文法にざっと目を通る场合などにも适していしてと思います。 キュ音问题 现在,私が持っているものはSwift2対応のものです。これは表纸侧も里侧も2枚がのり付けされてくっついた作りになっています。 2枚がくっついているせいで本を开いたときに内轮差のようなものが歪みを発生させ, キュッ と音が鸣ります。これが多少気になります。 静音化 たいた2枚の内,构造の纸を切ることでこの音を无くすことが出来ます。そのやり方を绍介します。 の开いた状态にして切断するラインの上端と下端に印を付ます。纸の端から等距离になるようにします。 印る付けたら定规をあててカッターで切ります。切るときは外侧の纸まで切。いように,间に厚めの纸を挟むようにして下さい。 音を无くすという目的を果たすには1ラインで十分ですが,デザイン的な面白さを追求したい人は2ラインがおすすめです。私は2ラインにしています。 2ラインにしたときに切り取ったものはしおりにすると统一感が出ます。 私はカバーを付けないのでアドバイスは何も出来ません。 今度出るSwift3に対応したものはどうなっているでしょうか。もしこの作りになっていた偶尔は,またこの方法が使えると思います。 な,くっつけてあるのは何か理由があるんでしょうか?正当な理由があってそうしているのであればこの记事は不适切なものとなります。その点,ご理解ください。
我正在创建一个简短的教程,说明如何从照片库中获取图像并将其显示在故事板上。 这将要求用户许可,然后自动显示图像。 本教程将从库中获取第一张图像并显示它。 我们将使用PhotoKit ,有关更多信息,请阅读Apple指南。 我们首先创建一个名为loadImage的新方法,该方法将返回可选的UIImage 。 我们将使用此方法来抓取图像以显示在屏幕上。 将其设为可选,以防万一我们无法从照片库中获取任何图像。 创建一个用于获取照片资产的管理器对象。 PHImageManager会缓存资产图片,从而使我们重新请求的资产能够更快地加载。 默认方法返回管理器对象。 接下来,创建类型为PHFetchResult的fetchResult 。 此类为我们提供了从Photos fetch方法返回的资产的有序列表。 PHAsset实例表示我们将检索的图像。 fetchAssets方法将检索图像。 选项使我们可以对获取的资产进行过滤和排序,而fetchOptions是接下来要创建的方法。 我们实例化PHFetchOptions类。 此类将使我们能够从获取的资产中过滤,排序和管理结果。 sortDescriptors属性指定获取的对象的顺序。 我们将使用一组键路径和排序顺序来使用NSSortDescriptor数组。 我们将使用creationDate键根据资产的创建日期对资产进行排序。 您可以在此处了解有关关键路径的更多信息。 请求选项方法将返回PHImageRequestOptions 。 我们将使用此方法来影响图像的传递方式。 我们将isSynchronous的布尔值设置为true。 此属性使我们可以设置图像的质量或获取请求的传递速度。 我们返回requestOptions ,我们将在loadImage()方法中使用此方法。 让我们回到我们的loadImage方法并添加以下代码: 我们将创建一个可选图像,并在没有功能的情况下返回该属性。 使用requestImage查找指定的资产。 我们将使用之前创建的fetchResult对象通过使用object(at :)方法来获取特定索引处的资产。 我们还指定了图像尺寸和内容模式,该模式告诉我们如何使图像适合请求尺寸的宽高比。 我们将创建的requestOptions()方法传递给options参数。 这说明了我们的请求将如何处理。 创建一个保护声明,以确保我们的img不为空,否则我们只将图像返回nil。 然后,我们将最终返回我们的形象。 接下来,在情节提要中。 将ImageView添加到View Controller中,然后将插座连接到您的swift文件。 @IBOutlet弱var imageView:UIImageView! 现在,我们将创建一个处理用户权限的photoAuthorization方法。 此方法将检查用户是否向我们授予了访问照片库的权限,如果获得我们的授权,我们将运行其余方法。 如果没有,我们将只打印一份声明。 如果愿意,可以使用UIAlertController提示警报消息。 这会检查我们当前的授权状态。 PHPhotoLibrary对象代表“照片”应用程序管理的整个资产集。 switch语句用于检查我们的状态并确定我们应该做什么。 如果身份验证成功,我们将使用loadImage方法将图像返回到imageView出口。 […]