字符串和子字符串如何在Swift中工作

这是我在Stack Overflow( 此处 和 此处 ) 上写的两个答案的综合 。 以下所有示例均使用 var str = “Hello, playground” 在Swift版本中,字符串发生了很大变化。 从Swift 4开始,当您从String中获取一些子字符串时,您将获得Substring类型而不是String 。 为什么是这样? 字符串是Swift中的值类型。 这意味着,如果您使用一个String来创建一个新的String,则必须将其复制过来。 这有利于稳定(在您不知情的情况下,没有其他人会改变它),但不利于效率。 另一方面,子字符串是对原始字符串的引用。 无需复制,因此使用效率更高。 但是,假设您从一百万个字符的字符串中得到了十个字符的子字符串。 因为子字符串引用了字符串,所以只要子字符串存在,系统就必须保留整个字符串。 因此,无论何时完成操作子字符串,都将其转换为字符串。 let myString = String(mySubstring) 这将只复制子字符串,旧字符串可以被垃圾回收。 子字符串(作为一种类型)意味着寿命很短。 Swift 4的另一个重大改进是(再次),Strings是Collections。 这意味着无论您对集合执行什么操作,都可以对字符串执行操作(使用下标,遍历字符,过滤器等)。 在我们进一步研究子字符串之前,了解字符串索引对于组成字符串的字符的工作方式将很有帮助。 startIndex和endIndex startIndex是第一个字符的索引 endIndex是最后一个字符之后的索引。 例 var str = “Hello, playground” // character str[str.startIndex] // H str[str.endIndex] // error: after […]

在TestFlight上发布iOS应用

在模拟器或设备上测试过iOS应用之后,您可能希望将其发布在TestFlight上进行Beta测试,以邀请其他人来测试您的应用。 要在TestFlight上发布该应用程序,首先,您必须具有iOS开发者帐户。 现在,您可以开始通过Xcode发布应用了。 您需要为您的应用程序提供身份,包括显示名称,捆绑标识符,版本和内部版本。 您可以通过项目->常规->身份找到身份。 以下是身份示例。 如上所述,您需要拥有iOS开发者帐户才能发布该应用。 在这里,您需要在常规->签名中为您的应用添加签名证书。 在产品->存档中开始存档您的应用程序。 确保您已选择设备作为通用iOS设备。 我这里没有我自己的Apple开发人员帐户,我被添加为AppStore Connect中的开发人员。 如果您是应用程序管理员,管理员或代理,则可以通过单击…图标旁边的+菜单在AppStore Connect上创建一个应用程序。 填写应用信息,包括: 名称 主要语言 捆绑ID 版 SKU 完成此应用程序信息后,单击“创建”。 如果没有在App Store上创建此应用程序,则会出现错误“找不到合适的记录。 确认您的捆绑包标识符正确。” 成功归档应用程序后,该开始“上传到App Store ..”。 在“上载应用程序的符号以从Apple接收符号化报告”上选择->下一步 选择自动管理签名,然后单击下一步。 等待将应用程序上载到App Store时,Connect会弹出,显示成功将应用程序上载到App Store的弹出窗口。 使用您的帐户登录https://appstoreconnect.apple.com。 转到活动->所有构建。 现在是时候邀请内部成员使用TestFlight尝试我们的应用程序了。 转到TestFlight选项卡> App Store Connect用户>单击+添加测试器。 请注意,在App Store Connect用户中添加人员之前,您需要在“用户和角色”中添加用户。

Swift#1中的Euler项目

我之前曾接受过Google的采访,但失败了。 面试官指出了我的缺点,算法和对OS级别的深刻理解。 我相信许多开发人员可能会想为什么我们应该学习这些东西。 我们在日常工作中几乎不能使用它们。 但是,我从另一个角度考虑。 在我的工具集中拥有这些技能会很好。 他们可以帮助我思考解决方案并解决难题。 所以从现在开始,我有一些业余时间来学习新事物。 我决定在Euler项目上玩算法难题。 问题 第一个问题称为3和5的倍数。 如果我们列出所有低于10的自然数,这些自然数是3或5的倍数,则得到3、5、6和9。这些倍数的总和为23。找到1000之下3或5的所有倍数的总和。 解 天真的解决方案是这样的: 让过滤=(1 .. <1000)。过滤器{ $ 0%3 == 0 || $ 0%5 == 0 } filter.reduce(0,组合:+) 我将其编写为两个表达式而不是一行,因为否则该表达式对于Xcode 7.3.1而言过于复杂。 但是该解决方案不可重用。 如果我们还有更多适用规则要怎么办? 例如,相反,我们想要3、5或7的倍数。 我试图编写一些帮助功能。 第一个函数是Int的扩展。 它检查一个整数是否可被另一个整数整除。 扩展Int { func divisibleBy(num:Int)-> Bool { 返回num%self == 0 } } 然后另一个函数检查给定的整数是否满足其中一个规则。 在这个问题中,规则是3的倍数和5的倍数。这将是Int-> Bool类型的函数。 我使它通用。 func满足条件(目标:T,规则:[T-> Bool])-> Bool { […]

PAPS工具:转换器

转换器使您可以将每种媒体格式(例如视频,实时照片,GIF)相互转换。 •视频—实时照片 •视频— GIF •视频—压缩视频(mp4) •GIF-实时照片 •连拍照片—实时照片 •连拍照片— GIF •连拍照片—视频 •屏幕截图(png)-压缩的屏幕截图(jpg)

iOS 11中的核心NFC已淘汰! — WWDC 2017

您可能已经听说CoreNFC已在Beta中发布,并且只能在iPhone 7和iOS 11上运行! 是Apple强迫用户迁移到最新智能手机的策略,还是一个真正的硬件问题,使iPhone 6s无法使用NFC? 这是一个悬而未决的问题,但是在不久的将来,iPhone 7将成为最受欢迎的iPhone,但仍然! 一段时间以来,当公司想要在产品上实现NFC标签读取时,总是会遇到功能退回的情况。 在实践中是什么意思? 适用于iOS App的QR Code和App方案以及适用于Android的NFC!。这次结束了! 。 好吧,它如何工作? 如我们所知,Apple有任何限制:)。 答案是不 ! 当然,除了NFC付款。 但是,您可能需要在Apple Development Portal中进行一些额外的配置。 组态 首先,您需要按照以下说明创建或修改现有的应用ID,以激活NFC读取功能 然后,您在Xcode 9(撰写此博客时为Beta)上创建一个Playground或一个新项目。 我们将创建一个名为NFCReader的小类,该类将负责处理NFC Reading处理 首先,我们将创建该类并导入CoreNFC框架。 因此,NFC阅读由NFC阅读器会话管理。 我们只是在初始化类时进行基本的初始化。 该会话具有一个代理(将在下面进行说明)和一个名为invalidateAfterFirstRead的属性。 此属性允许您的应用程序仅读取一次标签。 您是否可以激活它,这完全取决于您的App 。 完成此操作后,我们将开始会话。 考虑到实际的应用程序,此操作可能在其他位置并经过特定用户交互之后执行。 根据文档所述,CoreNFC框架会继续编译并仅在实际设备上起作用 ,这是继续之前的重要提示! 因此,这意味着您必须在目标前面的通用iOS设备上才能使用iOS 11 Beta构建或成为真实设备。 委托实施 CoreNFC具有两个主要的委托函数,可让您知道NFC数据是否已交换或会话是否无效。 然后,利用有效负载信息,您可以在应用程序中做任何您想做的事情。 好吧,这对于接收有效载荷数据和进行会话管理非常有用,但是我怎么知道我检测到周围的标签? NFCNDEFReaderSession是基于其具体类NFCReaderSession的 并拥有自己的泛型委托: 而已 ! 如您所见,在iOS中集成NFC并不复杂。 您只需要等待iOS 11发布,然后专注于NFC阅读实施和周围的动画! 啊,我几乎忘记了,但是它在Apple Watch OS […]

第1部分-RxSwift简介

RxSwift是Swift的被动扩展。 反应性扩展是观察者模式,迭代器模式和函数式编程的最佳创意的结合。 反应性扩展适用于Java,Scala,C#,C ++,JavaScript,Python,Clojure,Kotlin等。 RxSwift的编程模型类似于针对其他语言存在的反应式扩展,并且不止一组API。 这是一种构建响应,弹性,弹性和消息驱动的应用程序的新方法。 什么是反应式编程? 反应式编程是使用异步流或可观察序列(或简单的序列)进行编程。 它涉及流,其转换以及随之而来的绑定。 状态更改/新数据作为流传递,您可以观察和处理。 任何事物都可以是一个流:变量,事件,属性,请求/响应等。您可以收听任意数量的流并做出反应。 仅仅观察流是没有用的。 提供了用于转换任何这些流的工具。 您可以将任何这些转换链接起来,然后完全创建一个新的流。 并且,您可以将流绑定到属性,UI元素等。这使得编写和构建异步程序更加容易。 考虑以下代码: var health = 100.00 var playerCritical = health <= healthCutoffValue 如果playerCritical {//做某事} else {//做另一件事} 在此,变量playerCritical取决于健康状况是否小于临界值。 我们检查播放器是否很关键,并根据它进行一些工作。 但是,当玩家稍后在游戏中变得至关重要时,会发生什么呢? 也许,当播放器很关键时,您需要执行一段代码。 这就是反应式编程的用处 。您可以订阅playerCritical,并且当值更改时,将传递当前的流(或值),并在达到临界值时执行代码。 看看程序的数据流变得多么简单。 并且如前所述,任何东西都可以是流。 这只是一个简单的示例,但是在以后的系列中,我们将看到有关Rx的全部功能以及特定于iOS / macOS开发的更多内容。 反应式编程的好处 那么,Rx有什么好处? 为什么要在项目中使用它? Rx使您可以使用不可变的定义和纯函数以可靠的可组合方式处理流的快照。 您可以使用自己的处理程序轻松地将程序组成清晰的输入/输出函数 Rx帮助构建异步程序以对新数据/事件做出反应。 它使您可以编写高性能的代码来处理大量的流/事件。 使用提供的工具,您可以轻松编写高度交互的应用程序 可以很容易地推断出异步程序的功能以及处理程序对异步流的工作方式。 数据流清晰,您可以轻松理解代码块的工作方式 您可以轻松管理整个应用程序的状态。 Rx提供了在各种异步流之间共享状态的工具-如果您想 用Rx编写的代码非常具有说明性,因为定义是不可变的,并且只有流随时间变化,从而减少了副作用 Rx轻松让您绑定到UI元素,以更少的工作始终代表最新的应用程序状态 […]

核心数据刷新第1部分–快速杀死–中

核心数据刷新器第1部分 什么是核心数据? 核心数据是一个对象图管理框架,用于管理潜在的大型对象实例图以持久化数据。 它以持久状态存储数据,因此当应用程序重新启动或重新启动设备时,数据就可以在那里访问。 核心数据不是对象关系映射器(ORM)。 Core Data和SQLLite有什么区别? SQLLite是一个对磁盘上存储的对象进行操作的数据库,而核心数据对内存中存储的对象进行操作。 为了实现其图形管理,Core Data恰好使用SQLLite作为磁盘存储。 可以使用其他关系数据库来实现。 为了实际使用Core Data,首先让我们创建一个托管对象模型,该模型描述Core Data表示磁盘上数据的方式。 数据模型是一种数据库架构,因为Core Data使用SQLite数据库作为持久存储。 此外,Core Data经常使用术语“管理”。 例如,此处以类的名称使用NSManagedObjectContext,managed,它是指Core Data对Core Data对象生命周期的管理。 · 实体 -核心数据的类定义。经典示例是Employee或Company 。 在关系数据库中,实体对应于一个表。 · 属性是附加到特定实体的一条信息。 本质上是实体的属性之一。 在数据库中,属性对应于表中的特定字段。 关系-多个实体之间的链接。 实体是类定义,管理对象是该类的实例。 因此, NSManagedObject是该实体的实例,单个对象存储在Core Data中。 NSManagedObject可以是数据模型中的任何实体,采用任何已定义的属性和关系。 此外,为了使NSManagedObject访问您在数据模型中定义的特定属性,您必须使用键值编码(KVC)。 KVC注意事项 : KVC是Foundation中的一种机制,用于使用字符串间接访问对象的属性。 在这种情况下,KVC使NSMangedObject在运行时的行为或多或少像字典。 键值编码可用于从NSObject继承的所有类,包括NSManagedObject 。 您不能在不源自NSObject的Swift对象上使用KVC访问属性。 最后,为了将数据从持久性存储中获取到托管对象上下文中,您必须获取它。

世界新闻自由DPRK <US <立陶宛:排序,pickerviews和scrollviews

前几天,我在看新闻,发现了一个有趣的事实。 显然,根据《无国界记者》,美国在180个新闻自由国家中排名41。 显然,我要做的第一件事就是确保“无国界记者”不仅仅是朝鲜宣传机器的一部分。 我主要是通过确定他们的网站在不到3年的时间内加载并且拥有漂亮的图表这一事实,确定记者无国界实际上不是我们亲爱的领导人金正恩的卫星组织,所以我想了解更多。 基本上,他们提出此清单的方式是向许多专家分发调查表,然后将他们的回答与评估期间内针对记者的虐待和暴力行为数据结合起来。 您可以在此处阅读有关该过程的更多信息。 作为一个千禧一代,我自然地认为,北欧的所有天堂,抱歉的避风港,在新闻自由上都比我们的公司经营,喜欢特朗普,筑墙反乌托邦更重要最终跻身榜首的国家。 正如我最近很酷的孩子们所说的那样,我错误地认为自己是一个“有识之士”的人,我以为外面的某些人可能和我一样震惊。 在过去的几天里,我从事了一个项目,该项目以几种不同的方式显示了许多国家的人口统计信息。 您可以在github上找到它的代码。 这主要是为了让我从纽约搬到加利福尼亚后的一个礼拜后重新回到游戏中。 我遇到的三个有趣的事情是排序,选择器视图和滚动视图。 找不到合适的API,我将一些奇怪的15个国家/地区及其排名硬编码到我的主视图控制器中。 我有一个帮助方法实例化我的国家,每个国家都有:名称,新闻自由等级,GDP等级,识字率等级,国旗图像,总人口等级,人口密度等级,出生率等级和人均军费等级。 在我的初始视图控制器中是表格视图,我希望用户能够根据他们选择的人口统计对国家进行排序。 我选择了选择器视图作为选择的工具,因为我认为它看起来很时髦。 使用选择器视图就像将其放置在情节提要中的所需位置,设置与视图相关的约束,然后将视图控制器设置为选择器视图的委托一样容易。 使用委托时,记住在接口处添加委托选择非常重要: 选择器视图有两种方法需要使用: 第一个是确切描述选择器视图中有多少列。 第二个描述选择器视图中有多少行,我将其设置为每个国家/地区拥有的人口统计类别的数量。 第三种方法为您的选择器视图填充每一行的首选文本或图像。 快速提示:如果您想弄圆任何东西的边缘,这非常简单 如果我滚动到识字率等级,然后单击提交按钮,我的国家将以识字率的升序重新排列。 排序过程本身很简单。 它所需要的只是一个NSSortDescriptor,您可以在该数组上使用它根据该数组中对象的特定键对其进行重新排列。 完成我的初始视图后,我希望用户能够从表格视图中选择一个国家,并将其切换到另一个视图,以显示特定于国家/地区的统计信息。 所需要做的就是从表格视图的原型单元格到另一个视图创建一个序列,并传递要用于填充目标视图控制器的特定国家/地区对象的数据。 确保在目标视图控制器的.h文件中,为期望接收的对象类型添加一个属性。 成功配置了我的应用程序的基础知识之后,我想添加另一项功能,即人口统计信息的直观表示。 因此,我在主视图控制器中添加了一个“浏览”按钮,该按钮与一个表视图控制器结合使用,该列表控制器列出了每个国家/地区的人口统计类型。 当按下其中一个表格单元格时,它会选择另一个具有图像的视图控制器。 我希望图像具有一定的交互性,因此将其置于滚动视图中。 现在,滚动视图对于刚开始的用户可能会有些棘手,所以让我引导您完成整个过程。 步骤1:将滚动视图拖到视图控制器上,并使其达到所需的大小。 我想缩小视图的尺寸,因为我希望它可以占据整个屏幕。 步骤2:将视图或图像视图拖到滚动视图上。 步骤3:使用方形领带战斗机将imageview约束为滚动视图。 步骤4:将imageview的高度和宽度限制为滚动视图。 进行此操作时,请确定您是否希望用户能够垂直水平滚动或同时使用这两者。 我希望用户能够水平滚动,因此我将imageview相对于滚动视图的宽度限制设为3。 步骤5:如果要允许放大和缩小,请确保在滚动视图的“属性”检查器上设置最大和最小缩放属性。 步骤6:使ViewController成为滚动视图的委托 第7步:添加一种简单的缩放方法 确保在要缩放的特定滚动视图中返回特定内容。 如果在一个视图控制器中有多个滚动视图,则就像在方法中添加if语句一样简单 步骤8:退后一步,享受工作 好吧。 关于排序,选择器视图和滚动视图的非常基础的教程。 希望您能学到一些东西,下周再见,还有更多有趣的事实,以及编码小知识。

VIPER-S:编写您自己的体系结构以了解其重要性(第1部分)

最初发布于ThinkAndBuild:http://www.thinkandbuild.it/viper-s-writing-your-own-architecture-to-understand-its-importance-part-1/ 在为我的应用程序使用VIPER几个月后,我开始研究自己的体系结构:我想为自己的需求创建更好的东西。 然后,我开始与同事Marco交流思想。 他站在Android的一面,但我们需要讨论以找到共同点,并取得一致的结果。 我们“有点”失败了,最终得到了与VIPER真正相似的东西,但是! 我现在正在应用程序中使用的是这个VIPER的修订版,因此我不会认为这是一次失败的尝试。 更像是VIPER的自定义版本。 通过这一途径,我学到了很多关于体系结构的知识,因此我决定与一系列文章分享经验。 我想重点关注两件事: •为获得完整架构而做出的决策,突出了基本原理和疑点(其中有些仍然存在) •我最终使用的体系结构显示了代码和一些实际示例。 从现在开始,我们将此结构称为VIPER-S 。 这里的S代表语义,因为我试图获得一种更清晰的命名方式,赋予角色和通信更多的意义,并添加了一些规则来提高代码的可读性和编写性。 让我们的建筑师 让我们开始一个问题的旅程。 为什么需要架构? 这个问题有很多不同的答案,但最相关的是: •清楚了解我们的代码(并简化其维护) •轻松分配职责(并简化团队工作) •提高可测试性(并简化您的生活) 牢记这些答案,并怀着深远的目标感,我们可以开始规划架构。 我是“ divide-et-impera”的忠实拥护者:对我来说,这是一种生活方式。 这就是为什么我将首先确定所有领域和角色 ,将在这些领域工作的参与者以及这些参与者之间如何交流的原因。 这些元素将定义我们的体系结构的支柱,因此,清楚地了解它们是什么真的很重要。 域是一个大集合,其中包含职责范围的所有逻辑。 角色只是这个角色的一小部分,它更加具体,可以确定确切的需求。 角色是实现所有功能以满足角色的代码元素。 让我们列出并描述我为构建VIPER-S而确定的领域和角色。 体系结构域:用户界面 通过用户界面域,我们向用户显示信息并与他们进行交互。 让我们看看该域的角色。 角色:显示UI信息 这是一个真正的“愚蠢”角色。 到达该域的数据已准备就绪,可以使用,无需进一步处理。 它只需要向下发送到最终的UI元素,并具有以下功能: func display(date:String){label.text = date} 如您所见,在上一步中,date属性可能已从Date转换为String。 我们仅在此处显示现成的信息 。 标签显示一个字符串,因此我们希望收到一个字符串。 角色:处理UI事件 这是另一个不太主动的角色,实际上,我们在这里仅拦截用户交互或应用程序生命周期事件。 通常在UI target-action中调用负责该角色的参与者 : @IBAction func save(){eventsHandler.onSave()} 建筑领域:数据 […]

为iPhone X更新您的应用

众所周知,苹果终于在11月3日在多个国家/地区发布了iPhone X,客户的需求空前。 在欧洲领先的餐厅预订服务TheFork,我们一直在花一些时间来更新iOS应用程序,以便与新设备完全兼容,以便及时发布。 在此过程中,我们发现了许多有趣的提示和技巧,我们希望与您分享。 iPhone X在以前的iPhone迭代中提出了许多重要的新界面更改: 非20点状态栏高度,这是自2007年推出原始iPhone以来的首次 新的屏幕尺寸,分辨率为2436 x 1125像素,宽高比约为19:9,与上一代iPhone中的16:9不同 这意味着像素面积为812 x 375,即与iPhone 6相同的屏幕宽度(以磅为单位),但是具有新的像素密度,因此需要“ @ 3x”分辨率的图像 屏幕顶部和底部存在新区域,iPhone臭名昭著的“缺口”和其他UI元素可能会与应用程序重叠。 这包括手柄,它代替了“主页”按钮 因此,大多数开发人员将需要执行许多干预措施以适应其应用程序–这些干预措施可能会使您想起2013年iOS 7所需的那些干预措施。 特别是最棘手的挑战将是那些依赖于硬编码的20点状态栏大小和/或不考虑顶部和底部布局指南的自定义视图组件的人。 说实话 ,iOS 11现在不推荐使用topLayoutGuide和bottomLayoutGuide ,但是,如果您的应用程序已经使用了此API,则使您的应用程序符合iPhone X所需的工作将不再那么麻烦。 如前所述, topLayoutGuide和bottomLayoutGuide现在已成为历史,Apple现在建议“改为使用UIView的safeAreaLayoutGuide属性 ”。 通过情节提要 要在情节提要板上启用safeAreaLayoutGuides ,请仔细检查“文件检查器”面板中的“使用安全区域布局指南”是否已打开。 接下来,对于触摸屏幕顶部或底部的每个约束,您必须确保使用“安全区域”进行设置。 您可以通过单击约束值右侧的箭头来检查此信息。 如果要修改现有约束,只需选择它,然后选择“安全区域。底部”(或“区域顶部”)作为第一项或第二项,如下图所示。 请注意,Xcode 9中的Storyboard本身支持安全的布局指南,最值得注意的是,它将为您管理与旧版iOS版本的兼容模式。 这意味着,无需进一步更改,您的应用将退回到旧手机的传统底部布局指南。 以编程方式 使用自动版式 如果您的应用程序使用AutoLayout,则遵守安全区域的最佳方法是采用safeAreaLayoutGuide提供的锚点 。 假设您在视图底部有一个按钮,您不想被本机的“句柄”重叠。 然后,您可以编写: myButton.bottomAnchor.constraint(等于:view.safeAreaLayoutGuide.bottomAnchor,乘数:1.0) 由于safeAreaLayoutGuide在iOS 10或更早版本中不可用,因此我们将在UIViewController和/或UIView上添加扩展,以公开在旧版本和较新版本的iOS上均可使用的API。 动态变化 在某些情况下,您可能想在事件发生后更新插图。 例如,当尚未加载视图时, safeAreaInsets可能仍为空。 同样,当您的界面旋转时,插图会根据“缺口”的位置而变化。 您还可以使代码通过使用AdditionalSafeAreaInsets动态地更改safeAreaInsets。 在上述所有情况下,将调用UIViewController上的回调方法viewSafeAreaInsetsDidChange或UIView上的safeAreaInsetsDidChange 。 […]