Tag: swift

苹果公司的2FA公告将中断您的所有iOS CI / CD管道。 如何准备

阅读下面的原始链接以获得更好的语法和格式。 苹果公司的2FA公告将中断您的所有iOS CI / CD管道。 如何准备 拥有Apple ID的每个人都可能收到一封电子邮件,其中指出Apple将强制执行两因素身份验证(2FA)… shashikantjagtap.net 苹果公司的2FA公告将中断您的所有iOS CI / CD管道。 如何为此做准备– XCTEQ 拥有Apple ID的每个人都可能收到一封电子邮件,其中表明Apple将开始执行两因素身份验证(2FA)… www.xcteq.co.uk 每个拥有Apple ID的人都可能收到一封电子邮件,其中称Apple将自2019年2月27日起实施两因素身份验证(2FA)。2FA的目的是增加安全性。 每个人都需要启用2FA才能使用来自Apple开发人员搬运工或App Store Connect的证书,预配配置文件和标识符。 在我们上岗之前,重要的是要了解两因素身份验证(2FA)与两步验证(2SV)不同。 请阅读本指南以了解不同之处。 在本文中,我们将探讨2FA(如果已部署)将如何影响CI / CD管道,期望内容以及如何为这一更改做准备。 iOS CI / CD管道的当前状态 大多数iOS持续交付管道都是使用Fastlane工具设置的,一次可能是正确的选择。 也许有些团队使用自定义脚本来自动化iOS部署工作流,或者有些团队完全将其外包给第三方CI / CD服务,例如TravisCI,CircleCI,Nevercode,Bitrise等。大多数时候,我们不必担心有关CI服务器用户的2FA的信息,该用户下载了证书配置文件等。我们曾经为此目的创建了一个单独的帐户,因此效果很好。 但是,此方法完全绕开了CI服务器上的2FA流程。 Fastlane工具在此处记录了最佳CI实践,它告诉我们创建一个没有2FA的单独用户,并绕过受信任的设备和SMS验证。 这种方法还使用了一些疯狂的工具和cookie来保持会话的存活。 我认为,Fastlane处理iOS CI / CD解决方案的方法不是那么安全可靠。 如果苹果执行2FA,将会发生什么? Fastlane会处理2FA吗? 我们是否需要重新设置管道,还是需要再次使用手动发布方法? 让我们尝试在这篇文章中找到所有这些问题的答案。 潜在的Fastlane解决方法 目前,Fastlane建议创建一个在CI服务器上没有2FA的用户。 Fastlane使用太空飞船工具登录到Apple开发人员门户,创建会话,cookie并将它们用作ENV变量。 当苹果公司为每个Apple ID宣布2FA时,Fastlane用户会疯狂并提出一些奇怪的解决方法来解决此问题。 您可以在此处阅读有关此Github问题的一些疯狂和超级疯狂的想法,或搜索有关此想法的一些推文。 我在网上阅读的一些疯狂建议是 使用第三方服务(例如Twilio)进行SMS验证,将其存储在数据库中并使用REST […]

anagram-go-java:Go和Java并排使用-​​旧的编码器回头看Java

昨天,我摸索了一个简单的面试问题。 这是我第一次使用coderpad.io(聪明的主意),也许是我第一次有人在编码时看着我的肩膀,而没有允许一两个StackOverflow。 面试官真的希望我用Java做到这一点,这让我感到不安,我已经使用Go编码了一段时间,并尝试使用Go进行编码。 我用注释将其伪编码出来,然后迅速间隔一下如何在Go中从字符串中获取该死的字符。 叹。 所以,我决定写这篇文章作为减轻自己对自己的失望的pen悔。 我现在正在为多种项目使用3种不同的语言:Go,Python和Swift(很好,Swift 3)。 老实说,我只是不保持这三个语法的全部一致性,我在编码时会进行很多模式匹配/复制/粘贴,并且很少再逐个关键字地将其键入。 我想,我上一次这样做是在1988-1992年的时间范围内使用Objective-C。 现在,当我使用这些微模式时,我的编码要好得多,并且在整个代码库中一切看起来都一样。 面试结束不到5分钟,我就可以使用Go版本了。 然后,今天早上,我以为,经过了这么多年,我又回过头去做同样的事情,被翻译成Java。 我猜想花了太长时间,但这让我想起了过去十年来我忘记了Java的东西,而我却忽略了它。 它也显示了一个有趣的案例,其中可以比较Go和Java,而Go表现得很好(IMHO)。 以及“ map:hashtable”一词; 它是“ Go:Java”,因此Go中的地图几乎是Java中的Hashtable。 恩比恩? 杰,好的。 测试数据: anagram(aab,aba)= true anagram(aab,cab)=否 anagram(aab,abdcefghijklmnopqrstuvwxyz)=否 //而且我知道,我知道(您是行家)符文**, //但他说,不,只是一个简单的字符串。 首先,我决定将字谜决定放到一个函子中。 // 走 func anagram(x,y string)bool { // Java public boolean anagram(String x,String y){ //’x’是第一个字符串 //’y’是第二个字符串 //如果它们是彼此的字母,则返回true //否则返回false。 我在两个特殊情况下进行了几次快速检查,以使例程短路:1)如果X等于Y(因此字符串相同),则返回true。 (在字谜的某些定义中,这可能并非严格正确 )。 2)如果两个字符串的长度不同,那么它们不是字谜,则返回false。 现在,在Go世界中,有两种方法可以声明map:hashtable ,其中键是字符串,值是整数。 但是基本思想是键/值存储库之一,将其作为键的值,然后当您通过键要求时将其取回。 (我记得Dictionary是Java的东西,不是吗?还是它一直是抽象类型?但是现在我知道Dictionary已过时了,请改用Map接口。) // […]

iOS上的证书固定技术

嗨伙计! 今天,我们将讨论安全性。 为了完全理解此处介绍的这些概念,我需要提供一些有关SSL / TLS如何工作的背景知识以及其他内容。 当然,这不是一个深入的探讨,它只是在开始主要主题之前的简单说明,如果您已经知道,没关系,只需退出本部分并转到下一部分。 在最后,我们将看到一个如何在iOS项目上进行证书固定的实际示例,让我们开始吧! 它是什么? SSL / TLS确保通过HTTPS(即,基于SSL / TLS的HTTP)对客户端-服务器通信进行透明加密。 加密基于公共密钥基础结构(简称PKI)。 这是透明的,因为应用程序层对此加密过程一无所知,网络基础结构会处理一切,因为程序员我们只是编写应用程序请求,因此将带有纯文本的标头和正文放在请购单中,而网络基础结构则可以完成所有工作我们。 握手 在发送任何应用程序数据之前,服务器和客户端就如何加密/解密数据进行协商,此过程称为握手,在下图中,您可以看到有关此过程的简化视图: 握手后 此时,如果有人尝试检查在数据传输中客户端和服务器之间交换的消息,那么任何内容都不会被人类读取,所有流量在传输过程中都会被加密,即,仅从客户端和服务器的角度来解密。 证书验证过程 在握手过程中,服务器将提供数字证书,并且客户端需要基于预定义的信任证书颁发机构列表(也称为受信任的根CA存储)信任证书颁发者。 在安全连接上,如果所提供的证书是由未知的颁发者颁发的,则通常浏览器会显示警告⚠️,供用户决定是否必须继续进行连接。 默认情况下,在连接中断的情况下,应用程序上的此行为是不同的。 您有可能在设备上将自签名证书设置为受信任,在这种情况下,客户端将在后续连接中信任此证书。 中间人袭击 如果您的连接不是通过连接到原始服务器,而是通过另一台伪装成原始服务器的服务器,将会发生什么情况? 从Imperva Incapsula网站上看到有关中间人攻击的简要描述。 中间人(MITM)攻击是一个通用术语,指的是犯罪者将自己置于用户与应用程序之间的对话中-进行窃听或假冒其中一方,使其看起来像是正常的信息交换进展中。 在这种情况下,攻击者可以看到所有流量,并且可以捕获所有信息。 它是什么? 通过以上介绍的背景,我们可以更好地了解什么是证书固定。 众所周知,在握手过程中,服务器将出示必须由客户端信任或不信任的证书。 证书固定技术在于将目标的服务器证书保存在应用程序捆绑包中,并且仅对此信任。 我们的例子 让我们看一个实际的源代码,为此,我创建了一个在Heroku和一个客户端iOS项目上发布的存根身份验证剩余服务。 在发布本文档时,生成的证书尚未过期并且服务已启动。 当然,随着时间的推移,我无法保证,但是如果您正确地理解了这一概念,则可以更改证书和主机名以成功获得自己的服务。 在我们的示例中,我们将使用post方法访问以下URL https://floating-stream-25740.herokuapp.com/authentication/login来提交如下所示的请求: POST /身份验证/登录HTTP / 1.1 主持人:floating-stream-25740.herokuapp.com 内容类型:application / x-www-form-urlencoded 缓存控制:无缓存 id = user&password = pass 通知的ID或密码无关紧要,它仅用于测试。 […]

Swift 4.0数据类型转换基础

您阅读了我的上一篇文章,这有点令人不解。 iOS SDK,Xcode IDE和Swift语法的每个方面都经过精心设计,因此,为什么文档在词汇上如此密集,背后却有着超现实的光彩。 我认为最有效的学习方法是将所学内容分解为可管理的组件。 对于那些没有Apple计算机的人,本周您将不需要一台计算机。 您只需要使用它。 继续并在新标签页或窗口中打开此链接,或使其并排打开,如下所示! 好吧,我们知道Swift是Chris Lattner在他的最高机密实验室中起草的完全酷的编程语言。 但是,自成为开放源代码以来,Swift的普及程度已大大提高,甚至Google也在帮助该语言的发展。 现在,比以往任何时候都更是学习敏捷的好时机。 即使您不了解面向对象的编程。 在我的博客中,我将帮助您学习基础知识,面向对象的编程等等。 让我们开始! 进一步学习的下一步是从学习基础开始。 我们需要学习Swift的组成。 Swift是使用变量和常量构建的。 日常程序员用来在Swift中构建Facebook之类的一些基本数据类型是String,Float,Int,Bool,Double和Optional。 您已经准备好开始编写第一行代码。 在Swift Sandbox或Xcode Playground中,编写以下代码行。 var firstMessage:String =“你好,世界! ”让收入= 100 varggyBank:Double 让大脑年龄:整数= 80 var age = 24 //您可以在此处输入您的年龄。 存钱罐=双倍(大脑年龄/年龄*收入) let balance =“我的新收入是$ \(piggyBank)。” firstMessage + =余额 打印(firstMessage) 恭喜你! 您已经编写了前几行代码。 现在,让我们回顾一下您写的内容。 按照编程领域的惯例,您的第一条消息包含一个字符串值“ Hello,World!”。 ”。 firstMessage的末尾有一个空格,但稍后会介绍。 您隐式地将常量收入声明为整数,并将其分配为100。然后,您声明了数据类型为Double的变量piggybank。 接下来,您明确声明了一个整数常量brainAge,并为其分配了80的值,然后再声明您的年龄(或我的😈)。 现在,您为piggyBank分配了一个值。 […]

在iOS 11中检测屏幕捕获

我的要求是限制用户录制视频,因为我的应用中的所有视频仅适用于付费用户。 如果我的应用程序处于活动状态,我想限制屏幕录制。 我找不到任何解决方案可以防止仅针对我们的应用进行屏幕记录(或屏幕截图)。 这是操作系统级别的功能,不能被覆盖( 我找不到任何解决方案。如果您对此有所了解,请发表评论 )。 因此,唯一的解决方案是在发生屏幕录制时暂停或停止播放器。 幸运的是,iOS为此提供了解决方案。 iOS 11的UIScreen可用的实例属性名为isCaptured (以快速captured isCaptured )。 它是一个Boolean值,指示是否将屏幕内容克隆到另一个目标。 // Obj-C @property(nonatomic, readonly, getter=isCaptured) BOOL captured ; //迅速 var isCaptured : Bool { get } 我还使用了mirroredScreen属性,该属性检测屏幕是否被外部显示器镜像。 因此,其想法是检查这些 bool 值,并在其中任何一个为 true 停止玩家 。 我必须创建一个通知,该通知将在bool值变为true时帮助我们进行通知。 该代码在ObjC中,非常容易理解。 看看下面的代码。 这是正在运行的应用程序的gif。 而已。 ! 请享用!! 如果您喜欢阅读这篇文章,请分享并给予鼓掌,以便其他人可以找到它! 您可以在Medium上关注我以获取新文章。 另外,在LinkedIn上与我联系。 如果您有任何评论,问题或建议,请随时在下面的评论部分中发布它们!

XCODE显示标签栏可帮助快速处理多个文件

我们许多iOS开发人员都不了解Xcode中的标签栏内容。 因为默认情况下,当我们启动Xcode iDE时不显示选项卡栏。 我最近也想通了。 虽然可以在一个窗口中单击顶部箭头来回移动,但是对我来说,选项卡是更快工作的最佳方法。 如果在Xcode中看不到标签栏,请单击查看->显示标签栏 它确实有助于更快地工作。 最近,我正在开发一个新项目,当我在类文件中编写某些功能时,在一个选项卡中打开了文件,在另一个选项卡中,我为其中一些功能编写了单元测试。 同样,通过单击键盘上的CTRL + TAB,您可以轻松地在选项卡之间来回切换。 资料来源:http://thinkdiff.net/ios/xcode-show-tab-bar-helps-to-work-on-multiple-file-quickly/

构建自定义Xcode Instruments软件包

在AppSpector,我们经常使用集成的工具(当然是我们自己的代码,包括核心部分-移动SDK)来调试客户端应用程序。 我们一直使用适用于特定平台的各种工具来加快调试速度,并使开发过程更容易且容易出错。 因此,当我们发现WWDC 2018大会410“创建自定义工具”时,我们迫不及待地想要使用新的API进行构建。 如果您只有锤子,那么一切看起来都像钉子。 值得构建自定义Instruments软件包的问题不久就出现了。 AppSpector iOS SDK的核心部分是一个消息传递模块,简而言之,它负责iOS和我们的后端之间的双向流量交换。 SDK发送大量事件,描述主机应用程序的行为和各种操作,还接收来自后端的请求。 流量足够大,需要压缩,因此我们从一开始就实现了它,现在所有消息都在SDK和后端进行了压缩/解压缩。 在某个时候,我们决定将压缩算法从LZ4更改为基于字典的zstd,并可能对我们的数据类型提供更好的压缩。 众所周知,测量任何变化的能力对于安全有效地将它们引入至关重要,因此我们决定创建一个内置机制来跟踪压缩率和性能。 当然,定制乐器是最佳选择。 潜在的工具如何提供帮助 实际上,通过简单的日志记录就可以轻松实现几乎相同的目标,但是我们想要的以及适用于Instruments的是数据采样和可视化。 想象一下,一百个消息中的单个消息遇到压缩问题,其压缩率非常低,您需要执行某些操作(例如建立蓝牙连接)才能在真实设备上触发它。 在日志中搜索此消息可能会很痛苦。 即使您使用某种服务从设备收集和保存日志消息,并且消息具有预先计算的压缩率,也不是完全可以的。 但是就像在WWDC会话上的那个家伙一样看交互式图形,能够保存收集的数据并以后比较两次运行,建立自定义选择规则以识别和聚合具有某些属性的消息-看起来很棒。 从技术上讲,Instruments是最强大的调试平台之一DTrace的前端。 它是从Sun Solaris进入OSX的,详细描述它可以占用整本书(实际上是这样:https://www.amazon.com/DTrace-Dynamic-Tracing-Solaris-FreeBSD/dp/0132091518)。 DTrace使用以D语言编写的特殊跟踪程序(称为探针)进行操作。 在Apple推出Instruments软件包之前,您可以通过编写自己的D脚本作为数据提供程序并将其包装在Instrument模板中来构建自定义乐器。 我们将使用os_signpost API向我们的仪器提供数据。 项目设置 为了方便起见,我们将构建一个示例项目来说明一个简单的Instruments软件包。 除了在示例项目中用于模拟压缩和解压缩消息大小的随机生成的事件值之外,我们的压缩配置文件工具的工作方式相同。 我们建议克隆示例项目并在阅读时参考它。 Xcode提供了一个新的目标类型,称为“ Instruments Package”,位于“ MacOS”->“ Other”部分下。 目标模板没有任何作用,只是添加了一个扩展名为.instrpkg的文件,它实际上是一个描述我们的仪器布局和功能的XML文件。 构建软件包的大部分工作只是用原始XML编写。 让我们希望我们能够尽快得到一些特定于任务的编辑器,例如InterfaceBuilder或CoreData模型编辑器。 仪器架构 我们将构建的工具将使用os_signpost调用作为数据提供者。 该API允许定义事件的开始和结束,还可以传递一些格式化的字符串以及开始和结束调用。 就像使用“ scanf()”一样,通过根据字符串的格式解析该字符串来获取在Instruments端的事件数据。 我们将在Swift中使用os_signpost(),如果您使用Objective-C编写代码,则应使用os_signpost_interval_begin / os_signpost_interval_end调用。 要开始使用这些API,我们需要实例化“ log”实例,因为os_signpost使用os_logging子系统发送消息和唯一的路标标识符: 静态let log = OSLog(子系统:“ com.package”,类别:“行为”)static let […]

APP变薄

Apple在iOS 9.0+(WWDC 2015)中引入了App Thinning。 在本文中,您将获得App Thining的简化概述。 App Thinning通过使用iOS 9.0+中可用的一些API来减小应用程序的大小。 这涉及使用称为切片 , 按需资源和位码的三个过程中的一个或三个的组合。 应用切片 如今,为iOS生态系统开发的大多数应用都是通用的。 换句话说,一个应用程序可以安装在所有设备上,无论是iPhone还是iPod,都不需要为每个设备安装单独的应用程序。 启用应用程序切片可让应用程序开发人员根据要为其下载应用程序的设备打包资产。 如果同一用户在其他设备上下载相同的应用程序,则仅会下载在该设备上运行所需的资产。 按需资源 可以使用关键字来标记诸如图像和声音之类的资源,并根据标记以组的形式进行请求。 ODR支持更快的下载速度和更小的应用程序大小,从而改善了首次启动体验。 让我们考虑一个带有关卡的游戏的例子。 游戏可以将资源划分为多个级别,并仅在应用程序预期用户会移动到下一个级别时请求下一个资源级别。 同样,仅当用户购买相应的应用内购买时,应用才可以请求应用内购买资源。 位码 位码是已编译程序的中间表示。 它允许Apple重新优化应用程序二进制文件。 可以从Xcode启用和禁用它。 默认情况下,位码设置为YES ,对于iOS是可选的,但对于watchOS和tvOS是必选的。 转到项目的构建设置->确保您位于“所有”选项卡上。 搜索启用位码并设置为是/否分别启用/禁用位码。

如何在iOS中将一个测试目标文件用于两个应用目标?

我搜索了许多解决此问题的方法之后写这篇文章。 但是我找不到解决我问题的合适方法。 实际上,问题是“我的应用程序中有两个目标分别为SampleB2B和SampleB2C 。 这两个目标相似,只是变化不大。 因此,当我尝试为两个目标编写XCTestCase时,我认为两个目标都有一个测试目标文件。 因为所有测试文件都是相似的。 因此,考虑为两个目标编写一个测试文件。 但是我找不到一种对两个目标使用相同的测试文件的方法。” 这是我在项目中使用测试用例文件的方法,以同时将测试用例文件用于两个目标。 请按部就班。 最初,我只有一个目标,后来又改变了要求。 因此,我需要再创建一个目标。 因此,我只是从现有目标复制来创建另一个目标,然后重命名以区分这两个目标。 完成后,将类似于下面的快照。 我有两个上述目标,有一个测试目标是在创建项目时创建的。 现在,我在“ SampleTests ”文件夹中有一个测试用例文件。 所以我需要使用相同的文件来测试两个目标。 所以我做了以下。 因此,现在,我们需要从上面的窗口中再创建一个测试目标。 不要从“文件”->“目标”创建测试目标。 如果要从中创建,则它将为新创建的创建测试目标文件夹。 实际上,在开始测试时,测试文件需要位于同一测试目标文件夹中。 这导致在两个测试目标中创建重复文件。 两个测试目标文件夹下的两个文件中的文件内容相同。 我想以更好的方式做到这一点。 因此,我尝试了其他任何方法来将相同文件用于两个测试目标。 因此,右键单击现有的目标SampleTests,然后单击重复。 然后重命名测试目标,以区分并重命名所有目标的Info.plist,并在“ 对应目标”->“构建设置”->“ Info.plist”文件名中提供相应的Info.plist文件路径。 一旦完成,它将像 现在,我有两个目标,其中两个是测试目标,一个是测试文件夹和测试文件。 2.为两个测试目标选择相应的主机应用程序,如下面的快照。 3.在两个测试目标的活动编译标志中添加标志,以在运行时区分当前目标。 选择测试目标->构建设置->活动编译条件,如下面的快照。 在B2B测试目标中添加B2B标志,在B2C测试目标中添加B2C标志。 它将在步骤5中使用。 4.在添加或创建新的测试用例文件时,请确保为两个测试目标都添加了文件。 也检查现有文件的目标成员资格 。 5.在测试文件顶部添加以下代码。 导入项目模块取决于当前的目标。 #if B2B @testable导入SampleB2B #其他 @testable导入SampleB2C #万一 如果要基于目标更改测试用例文件,我们可以使用同一段代码来区分。 6.单击目标和编辑方案,然后添加测试目标,如下所示。 对两个目标都执行此步骤。 为相应的应用目标添加相应的测试目标。 […]

收藏查看Swift 4-iOS11

今天,我们将在Swift 4 iOS 11 Xcode 9中讨论集合视图, 步骤1:建立新的Xcode专案 步骤2:创建MVC文件夹(Model View Controller) 在controller文件夹中,创建新的可可触摸快速文件(UIViewController),将其命名为MainVC,在View文件夹中,创建新的可可触摸快速文件(UICollectionViewCell) 步骤3:打开Main.Storyboard 从对象库拖动集合视图 将Class CollectionViewCell连接到我们的单元格 在单元格中添加名为proLbl Label,并通过单击将其连接,然后在键盘上按Control键并拖动到CollectionViewCell View中 步骤4:打开Controller — MainVC.swift 将UICollectionViewDataSource和UICOllectionViewDelegate添加到类中,然后添加这两个支持功能 func collectionView(_ collectionView:UICollectionView,numberOfItemsInSection部分:Int)-> Int { //返回section的行数。 } func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath)-> UICollectionViewCell { //返回配置的单元格对象。 } 添加一个数组变量以显示collectionViewCell中的数据 //创建一个包含我们的数据的数组 var array = [“第一个单元格”,“第二个单元格”,“第三个单元格”,“第四个单元格”,“第五个单元格”] 编辑numberOfItemsInSection函数以返回array.count func collectionView(_ collectionView:UICollectionView,numberOfItemsInSection部分:Int)-> Int { 返回array.count } 编辑cellForRowAt函数以返回单元格 func collectionView(_ collectionView:UICollectionView,cellForItemAt […]