在上一篇文章中,我们讨论了相等和可比较的协议,我们将研究另一个更快的协议,即Hashable。 Hashable是一种协议,它提供了使用自定义类的对象作为Dictionary或set中的键的功能,按照APPLE定义的可哈希值: 提供整数哈希值的类型。 许多内置类型提供哈希值,或者我会说它们符合哈希协议,包括字符串,整数,浮点数和布尔值,甚至是集合。 注意: 当您定义一个没有关联值的枚举时,它会 自动 获得可 Hashable 一致性。 如果您使用Hashable协议使一个类符合并且该类的实例相等,即a == b,则a.hashvalue == b.hashvalue也将适用,但相反情况并非如此。 按照苹果: 哈希值不能保证在程序的不同执行中相等。 不要保存哈希值以供将来执行。 哈希协议是从等同协议继承而来的,因此您需要同时遵守这两个协议。 让我们借助示例来了解事物:- 我们将使用rollNumber创建一个名为“ Student”的快捷类。 现在我们需要添加可哈希的 弹出有关可哈希和等值一致性的错误。我们将重写“ ==”运算符以实现等值一致性,并提供hashValue,hashValue应该是计算属性,但在示例中作为实验,我们将其用作存储属性。 班级学生:适用于{ var hashValue:Int = 0静态函数==(lhs:学生,rhs:学生)-> Bool {如果lhs.rollNumber == rhs.rollNumber {返回true}返回false} let rollNumber:Int init(rollnumber:Int = 0 ){self.rollNumber = rollnumber}} 现在,如果我们创建此Student类的实例并将其用作哈希值,则可以查看结果。 让lovekesh:Student = Student(rollnumber:1)var studentInfo:Dictionary =字典() 在这里,我们创建了一个名为hashpValue值为0,rollnumber为1的Student实例“ Lovekesh”,并以Student为键声明了StudentInfo字典。 studentInfo [lovekesh] =“第十标准” 打印(studentInfo […]
DevOps和持续交付实践可将持续构建部署到我们的内部或Beta测试平台。 必须管理iOS应用的版本和内部版本号。 作为最佳DevOps做法,iOS团队应经常向AppStore发布新版本(即市场营销版本),并且应在向AppStore提交应用程序之前为每个版本进行多次构建。 该发行版可能具有具有不同功能的不同内部版本。 管理iOS应用的内部版本号和版本号非常重要,以确保我们将正确的内部版本发送到AppStore。 在本文中,我们将看到如何使用agvtool命令行实用程序来管理我们的iOS应用的版本和内部版本号。 版本和内部版本号 在开始使用agvtool之前,让我们了解什么是iOS应用程序的版本和内部版本号。 版本号 基本上,版本号是该应用程序的市场编号,它是显示给应用程序用户的编号,用于标识应用程序的发行版本。 它作为CFBundleShortVersionString(捆绑版本字符串,简称)存储在应用程序的Info.plist中。 内部编号 内部版本号标识应用程序的未发布或已发布版本。 它作为CFBundleVersion(捆绑版)存储在应用程序的Info.plist中。 我们可以为特定版本进行多个构建。 agvtool agvtool是一个命令行工具,可让您自动将这些数字递增到下一个最高数字或特定数字。 该工具与Xcode命令行工具一起提供,可以从xcrun实用程序直接访问。 $ xcrun agvtool $ xcrun-查找agvtool 您可以从其文档页面阅读该工具提供的选项 $ man agvtool 这将显示agvtool随附的所有命令。 现在,我们将看到如何在真实的iOS应用程序上使用agvtool。 为了做到这一点,让我们在Xcode中创建一个名为agvtool-Demo的单视图iOS应用。 从命令行开始使用agvtool之前,需要确保以下几点。 启用agvtool和版本控制系统 禁用/启用源代码管理设置 我们将看到如何在Xcode中进行设置 启用agvtool 为了启用agvtool,我们需要确保在目标构建设置中正确设置了“ 当前项目版本”和“ 版本控制系统”属性。 选择目标构建设置,然后搜索“版本”。 现在将“ 当前项目版本 ”设置为1,并将“ 版本控制系统”值选择为“ Apple Generic” 接下来要验证的是确保“ 信息”选项卡具有捆绑软件版本和捆绑软件版本字符串,对于新项目,简短值可能设置为1。 禁用/启用源代码控制(CVS,SVN) 当agvtool更改版本或内部版本号时,它将在Xcode项目内的某些文件中进行更改。 如果使用CVS或SVN,则可以将这些更改提交给源代码管理。 如果您不使用SVN或CVS,则无需担心这些设置。 默认情况下,提交对CVS或SVN的更改为ON,但是,我们可以通过运行以下命令来禁用该设置。 $默认写入agvtool SVNEnabled否 $默认写入agvtool […]
本周,我遇到了我的朋友MateuszMaćkowiak提出的挑战,以解决他创建的diff函数中的问题。 给定两个数组,他的目标是检索: 通用元素:两个数组中的元素。 插入的元素:不在第一个数组中但在第二个数组中的元素。 删除的元素:不在第二个数组中但在第一个数组中的元素。 不过有一个陷阱。 元素不可比较,也不可等于 ,并且第一个数组的元素可能与第二个数组的类型不同。 但是,该函数将接收compare闭包,该闭包从第一个数组中获取一个元素,从第二个数组中获取一个元素,并告诉它们是否相等。 他向我展示了他的解决方案: 输入数据为: 让a = [Int](0 … 1000) 令b = [Int](750 … 1500)
Liskov替换原理非常简单。 它指出: “程序中的对象应该可以用其子类型的实例替换,而不会改变程序的正确性。” 本质上,在iOS中,这意味着您应该以一种方式对类/协议进行建模,以便可以将符合该协议的任何子类/类型替换为子类型,而不会改变程序的正确性。 例如,您有一个MyClass类。 MyClass使用另一个模块执行任务,我们称它为OperationExecuter 。 OperationExecuter可以是协议或类。 您有一个新的子类型,该子类型可以子类化/符合OperationExecuter ,我们称其为FasterOperationExecuter 。 您可以在MyClass中替换FasterOperationExecuter (如果我们通过依赖注入使用OCP的话),而无需更改其正确性。 以第2部分(OCP)中的最后一个示例为例: 并给出替换示例,也来自上一部分: let imageStorage = NoirImageStorage(访问器:RemoteServerFilesAccessor()) 我们已经完成了LSP。 如果现在将imageStorage属性更改为使用NoirImageStorage ,则所有操作仍将相同。 LSP就是这样。 我们还将ImageStorage使用的FileAccessor更改为RemoteServerFilesAccessor ,而不是DocumentDirectoryFileAccessor 。 我们的imageStorage仍然按照其需要执行操作,只是有所不同。 它仍然会拍摄图像并将其存储在我们的存储层中 (除了现在也使用服务层)。 在第一个示例中,它拍摄一张图像并将其保存到文档目录中。 在第二个示例中,它将拍摄图像,对其应用Noir效果,然后将其存储在远程服务器中。 我们没有更改ProfilePicManager的正确性。 它仍然执行需要完成的任务(只是有所不同),我们没有改变它的正确性。 转到第4部分- 接口隔离原理。
创造运动! 我们将更新雨伞以响应触摸。 在GameScene.swift中 ,查看空函数touchesBegan(_ touches :,带有event 🙂和touchesMoved(_ touches :,带有event 🙂 。 在这里,我们将告诉雨伞与游戏进行交互的位置。 如果我们基于当前触摸之一在这两个功能中都设置了伞形节点的位置,它将锁定到位并从屏幕的一侧转移到另一侧。 另一种方法可能是在UmbrellaSprite对象中设置目标,然后在调用update(dt :)时 ,我们可以朝该位置移动。 第三种方法可能是将SKActions设置为在touchesBegan(_ touches :,带有event 🙂或touchesMoved(_ touches :,带有event 🙂上移动UmbrellaSprite ,但是我不建议这样做。 这将导致我们频繁创建和销毁这些SKAction ,并且可能性能不高。 我们将选择选项#2。 更新UmbrellaSprite中的代码,使其看起来像下面的代码: 检测我们的碰撞! 现在,我们不需要担心很多冲突。 我们可能在雨滴,雨滴和雨伞以及雨滴和地板之间发生碰撞。 但是,我们确实需要检测雨滴何时击中了某些东西,因此我们可以告诉它被删除。 我们将需要创建一些变量来对每个SKPhysicsBody进行分类,以便我们找出它们碰撞时该怎么办。 为此,我们应该创建另一个名为Constants.swift的文件。 右键单击“支持”组下的,单击“ 新建文件” >“ Swift文件” ,然后单击“下一步”按钮。 将文件重命名为Constants ,然后单击Create 。 该文件应包含以下代码: 让RainDropCategory:UInt32 = 0x1 << 1 让FloorCategory:UInt32 = 0x1 << 2 让UmbrellaCategory:UInt32 = […]
这是我博客的一个交叉报道。 您可以在 此处 找到原始帖子 。 我最近一直在探索的一个领域是传感器电路与iOS应用之间的蓝牙通信。 我想根据Adafruit优秀人士提供的一些示例分享这些研究之一。 它由一个传感器组成,该传感器可以检测到火焰的存在,并通过蓝牙将该信息发送到iPhone应用程序,该应用程序显示传感器的读数。 这是实际的样子: 在本研究中,我使用Adafruit的FLORA系列基于Arduino的板进行原型制作。 FLORA板与Arduino IDE完全兼容,可轻松用于可穿戴项目。 我使用的蓝牙板是FLORA蓝牙模块,传感器是Inland 24传感器套件中随附的火焰传感器。 这是完整的电路: Arduino素描 为了运行Arduino草图,您需要确保您具有: 最新版本的Arduino IDE 已安装Adafruit AVR板套件 已安装Adafruit BluefruitLE nRF51库 该草图是基于Adafruit BluefruitLE nRF51库中包含的blueart_cmdmode草图构建的。 大部分草图是用于配置FLORA和FLORA蓝牙模块的样板代码。 循环功能内部的代码将从火焰传感器获取值,对其进行缩放,并确定是否是近距离火焰(小于1.5英尺),远距离火焰(1-3英尺)或未检测到火焰: //读取模拟量A9上的传感器: int sensorReading = AnalogRead(A9); //映射传感器范围(四个选项): // ex:’long int map(long int,long int,long int,long int,long int)’ int range = map(sensorReading,sensorMin,sensorMax,0,3); //范围值: 开关(范围){ 案例0://距离不到1.5英尺的火。 Serial.println(0); Serial.flush(); 打破; 情况1://距离1-3英尺之间的火。 […]
在上一篇文章中,我们讨论了泛型。 开始Swift编程第13部分-泛型 以前,我们介绍了类型别名,属性观察器以及“自我vs自我”。 medium.com 这是很难获得的信息,但这就是我们练习的原因。 仅仅因为我写了这个系列来进行教学,并不意味着这足以让您掌握所教的一切。 您可能从我的一篇文章转到另一篇相关文章,但我不会反对您。 事实上,我鼓励您继续从不同的来源学习。 我感谢通过阅读和/或鼓掌阅读每篇文章的人们所表现出的忠诚度,但我的首要目标不是要获得人气。 这是为了确保当您完成我的一篇文章时,您学到了一些新知识。 无需赘言,我们开始。 您是否曾经去过厨房准备食物并意识到没有干净的盘子? 您有几种选择: A.放弃晚餐 B.到餐厅去,或者 C.洗碗,然后在家修理晚餐 这些决定不仅影响您,而且影响您所喂养的人们。 选项A是最简单的解决方案,但每个人都饿着肚子,看着你成为晚餐的救星。 选项B也很容易,但价格昂贵,需要做一些不必要的额外工作,而且味道并不总是像家庭自制菜那样好。 选项C是一条艰难的道路,但如果您希望自己的食物品尝到自己想要的口味而又少有抱怨,并且希望没有破损的菜肴,那它就是最好的解决方案。 那么,所有这些与错误处理有什么关系? 一切! 当您决定尝试晚餐时,您调用了一种方法。 那么我们如何抛出错误呢? 可以通过在函数声明中的参数之后附加throws来引发错误。 但是,如果我们想从抛出函数返回错误字符串怎么办? 我们有一个选择,我之前已经暗示过。 为我们提供了针对Apple的所有错误的localizedDescription ,但它不仅神奇地读取了文本fileOpenError并提出了“无法打开文件”文本。 我们必须告诉它要提供什么。
在Xcode中使用iOS版本在Alamofire中使用debugPrint() API中的使用。 在Xcode中下载。다는느꼈다。 。스위프트 스위프트 프로그래밍 다음과이출력된다。 \Uc2a4\Uc704\Ud504\Ud2b8 \Ud504\Ub85c\Uadf8\Ub798\Ubc0d 。스트기편집로에확인했다확인했다。 。이많이갔다。 난해지난해7월XCKoLog라는CLI를다。 。손으하던해주는능을능을도구도구도구다도구 。제문있었으므로배포했다。 XCKoLog X지있다는다알았다。 이유는가가지로보였다。 CLI(XCKoLog)下载(CLI),CLI(CLILog)下载。 왕지아니이만면이면다면는이스를보바꿔로했다。 Swift가iOS(그mac고macOS)쓰이는이관심다。 Swift가오픈소스가되면서Linux에이되고사이드(服务器端)프레임워크들이화제가되었다。 快速浏览器(Serverless),OpenWhisk的IBM이공개한리스오픈소스프로젝트로인큐베이터에가있다。 XCKoLog XCKoLog Log앱서버서버서버서버서버서버서버서버다다다다다다다스다 。이스등제약은있다。 XCKoLog는도구므므므므스스스스스스스스스스。。 IBM的OpenWhisk产品和服务。 지난해8 XCKoLog를IBM Bluemix OpenWhisk등록했다。 당시Swift버전은3.1을지원했다。 IBM Cloud Functions发行版,Swift 4.0版지원한다。 照片。 IBM Cloud Functions的供应商(以下简称:供应商)。 动作(动作)的下载。 오른쪽의오른쪽의 Action Action Action Action Action Action Action Action Action Action Action Action […]
简介:我们应该避免在进行每个修复后重新运行代码,并继续进行调试。 今天我们将讨论以下几点: 更改/注入代码 打印汇编代码值 通过lldb命令添加符号断点 跳过代码行 自定义调试说明 观察点 在目标C模式下运行命令 创建命令别名 在LLDB中使用python脚本 从调试器更新动画 约束调试 更改/注入代码 要在断点处编辑值,请使用以下lldb命令 表达式variable_name =值 您还可以配置断点以自动完成此操作。 单击断点>编辑断点 注入代码:假设您忘记设置委托,现在不用重新运行,而使用相同的表达式来注入并继续调试。 打印汇编代码值 假设您已经为UIlabel setText方法设置了符号断点 现在,当遇到断点时,如何在汇编代码中看到调试点时如何打印值 在这一点上尝试这些命令并观察值 po $ arg1 po(SEL)$ arg2 po $ arg3 通过lldb命令添加符号断点 假设我们要在另一个断点被击中后激活一个符号断点。 然后,我们可以使用以下调试器命令创建一个断点。 断点集-一键式true –name“-[UILabel setText:]” 跳过代码行 为要跳过的行设置一个断点,然后只需将包含两行的按钮拖动到下一行即可。 我们想在每次点击时跳过此行,让我们为其配置断点 跳线-1 自定义调试说明 对于自定义类,我们可以实现此协议以在LLDB中获取描述 观察点 监视点就像一个断点,每次更改属性时都会暂停。 可以使用调试器的变量部分中的上下文菜单进行设置。 在目标C模式下运行命令 有一些客观的C库,您想以ObjC方式发送命令或发送命令,而无需进行swift的严格类型检查。 为此,您可以使用下面的expression命令 表达式-l objc -o-[`self.view` recursiveDescription] […]
自WWDC 2017以来,MapKit中的本机注释聚类是一项广受关注的功能。 在iOS 11之前,要在您的应用程序中集群化并运行有点费力:您必须从几个提供该功能的第三方库中进行选择,为应用程序添加另一个依赖项,并进行大量工作以使现有的与他们的系统兼容的体系结构。 所有这些只是为了使您的地图更易于阅读! 幸运的是,Apple的本机解决方案既非常容易添加到您的应用中,又与大多数MapKit实现中常见的典型模式自然契合。 让我们来看看。 对于以前在iOS上使用地图功能不多的用户,在屏幕上获取注释非常简单。 在下面的图形中,您将看到一个简单的类层次结构: MKAnnotation , MKMapView和MKAnnotationView位于它们之间。 MKAnnotation是一种具有一个必需属性的协议:坐标( CLLCoordinate2D )。 可以将符合此协议的对象添加到由MapKit中的MKMapView表示的地图中。 添加到地图的实际视图是MKAnnotationView (或其子类),它将被放置在地图上注释对象的坐标处。 很简单! 因此,一旦将一堆这些注释添加到地图上,我们如何将它们聚类? 同样非常简单:您可以利用MKAnnotationView上新的clusteringIdentifier属性。 每当地图的视口发生变化时,系统可以将共享同一clusteringIdentifier任意数量的地图上批注组合到一个群集中。 让我们深入研究一些代码,以了解实际情况。 繁荣! lines几行额外的代码,我们为我们的应用程序添加了一个很棒的新功能。 当然,我们可以进行一些改进: 如何列出每个集群中包含的项目数? 也许有关每个集群中数据的一些高级信息? 而且,woof,当前的代码有点混乱。 我们如何清理它,并使所有内容变得更加快速? 我们将在下周的第二部分中介绍这些改进! 同时,在GitHub上查看工作项目project