在正常的快速项目中,我们将创建一个桥接标题,然后将我们的Objective-C框架导入该桥接标题中。 对于框架,您将需要创建一个自定义的swift模块。 假设您有一个名为MyFramework的Objective-C框架。 首先,将您的框架添加到项目中: 然后,您需要将聚合添加到项目和目标列表。 输入Objective-C框架的名称作为产品名称。 然后转到构建阶段> +>新建运行脚本阶段。 输入以下脚本: 确保将头文件的路径设置为Objective-C框架的头文件的路径。 您可以在这里找到:https://github.com/AnumQ/public_scripts/blob/master/module.sh 从方案列表中选择聚合的MobileFramework,以建立聚合的MobileFramework。 现在,我们必须将框架包含在我们的项目中。 为此,我们将MobileFramework模块添加到主项目(框架)的Target Dependencies中。 现在构建您的MyCustomFramework项目。 通过添加import语句,只需在swift文件中使用框架: 哇!
iOS中的实用MVVM 在最近的几篇文章中(这里,这里和这里),我解释了MVVM架构模式如何帮助编写更清洁的iOS…… medium.com 通过RxSwift和ObjectMapper缓解Firebase的痛苦 本文是我在软件工程中的一些实用方法。 medium.com Swift + MVVM +双向绑定=胜利! TLDR; 一种在UIControl和Observable上实现两种方式绑定的方法,以便您编写代码,要编写… codeburst.io 在Swift中了解模型视图控制器(MVC)– LearnAppMaking Reinder de Vries于2017年7月12日在App Development中撰文Model-View-Controller(MVC)具有异常强大的功能…… Learnappmaking.com 使用Firebase为iOS应用创建后端– SitePoint Firebase是一个后端即服务平台,可以帮助您快速开发和部署应用程序。 它提供… www.sitepoint.com 保持Swift模型干净 扩展程序是您最好的新朋友 medium.com 在Swift中轻松进行结构初始化 您是否知道swift可为您的所有属性自动生成初始化? 假设您有amyStruct: medium.com 第一章–类,结构和枚举的必然选择·邂逅Swift你需要知道的n事件 编辑描述 gradyzhuo.gitbooks.io Swift中的结构和类–什么,何时以及如何 结构和类是面向对象的编程概念,使用它们的主要原因是可以使您更多…… 开发到 在视图控制器之间传递数据(方法)– LearnAppMaking 由Reinder de Vries撰写于2017年7月19日在App Development中为Swift 4和Xcode 9更新。 Learnappmaking.com Swift:NotificationCenter协议 观察者模式变得更好 medium.com 具有模型观察器的Swift MVC架构 使用MVC方法进行iOS应用开发时,我想通过发布到…来观察模型的更改。 stackoverflow.com 提示:使用KVO和关键路径进行绑定 […]
注意:已在2017年3月10日更新为使用Xcode 8.2.1和CocoaPods 1.2.0。 情况 :您正在项目中使用RxSwift。 您意识到拥有一个操场来测试想法真的很好。 问题 :您无法将RxSwift(或RxCocoa)导入您的游乐场。 苹果公司的指示是不透明的。 解决方案 :使用CocoaPods安装RxSwift。 CocoaPods将创建一个包含RxSwift和您现有项目的工作区。 在项目内创建的工作区将能够导入RxSwift。 详细说明 :如果您尚未使用CocoaPods,请初始化一个新的Podfile : $ pod init 现在,您的项目目录中应该有一个Podfile 。 在您的Podfile添加以下段: #项目豆荚 pod’RxSwift’,’〜> 3.2′ 然后安装此pod: $ pod安装 现在您应该有一个工作区(扩展名为.xcworkspace )。 使用Xcode打开此文件。 现在,您可以创建您的游乐场了。 转到项目导航器,然后取消选择所有内容(⌘单击任何选定的项目)。 这很重要,因为在下一步中添加项目时,您希望它位于工作空间而不是现有项目下。 使用项目导航器中的“ +”按钮将新的Playground添加到工作区。 给您的游乐场起个名字。 我建议将其与Project.xcodeproj和Project.xcworkspace文件放在同一目录中。 保持在一起。 此时,您应该有一个工作区,其中项目,操场和吊舱都在工作区的顶层: 现在构建您的项目。 这还将建立您在上一步中选择的Rx目标。 您的构建应该成功! 现在转到您的游乐场并导入RxSwift。 使用RxSwift游乐场 您可能会注意到RxSwift在操场上的行为有所不同。 具体来说,如果您创建一个Observable.interval,它似乎没有任何作用。 那是因为您需要告诉Xcode继续连续运行您的Playground,否则它仅运行每个语句并立即停止执行,然后观察到的时间间隔可以发送事件。 可以通过在Playground / Sources下添加此SupportCode.swift文件来解决。 在操场的尽头,将调用添加到playgroundTimeLimit以指定您想让操场运行多长时间。 例如: PlaygroundTimeLimit(10) 这将使运动场保持运行10秒钟,此后运动场将自动停止,从而节省了笔记本电脑的电池并限制了输出缓冲区的大小。
已针对Swift 4.2更新2018年9月12日 zy懒的เป็นอีกหนึ่งตัวช่วยสำคัญในภาษาSwiftที่ทำให้การเขียนAppง่ายขึ้นลดการใช้หน่วยความจำและทำงานได้เร็วขึ้นอีกด้วย ู้จัก懒的ในภาzyาSwiftกัน Lazyพูดกันง่ายๆzyอการชะลอการทำงานzyรือการคำนวณบางอย่างออกไปช่วยลดการหน่วงของแอพ(กระตุก)รวมทั้งการจัดการCodeก็ง่ายขึ้นด้วย 由LazyในSwiftแบ่งออกเป็น2ส่วนใหญ่ๆดังนี้ 1.懒惰的变量 zyรแบบLazyจะพบได้บ่อยสุดทั้งในตัวแปรระดับออปเจคตัวแปรระดับคลาสตัวแปรระบบรวมทั้งยังใช้ในสตรัคได้อีกด้วย lazy varในคลาสหรือสตรัค 6月12日至12日:ที่ใช้อนกับด้านบนต่างกันที่ใช้for ..在แทนforEach {..} ทัดรรทัด16:ผสมการใช้mapและ过滤器เพื่อหาเส้นรอบวง> 40 *บรรทัด17:ลองเอาArray(…)ออกแล้วสังเกตผลลัพธ์ดูครับ ทัดรร:20:maxElementเพื่อหาค่าสูงสุดแบบlazy zyหกตัวกตัวzy zy la la la DictionaryืืDictionary Dictionary Dictionary Dictionary Dictionary Dictionary Dictionary字典ใหญ่มราDictionaryาDictionary Dictionaryริ่งลดกอ Appองหน่วยความจำจนAppปิดตัวไปได้ ใช้างสถาณการณ์ที่ลดการใช้CPUลงได้อย่างมากเช่น Ramารใช้งานRamโดยใช้分配(分配密度) zyนื่องจากดาต้าเซตใหญ่าเซตใหญ่zyาเขียนแบบปกติจะเห็นช่วง สรุป zyารใช้lazy zyยให้โค้ดเรารันได้เร็วขึ้นและลดการพีคของหน่วยความจำลงได้หากคนที่ใช้map,flatMap,forEeah,filter,…เป็นประจำอยู่แล้วไม่ต้องปรับโครงสรงสร้ร้ร้างโค้ดใดๆก็สามารถใช้lazy 。ยinา。รยังไม่แม่น语法หรือยังใช้for .. in ..ในการแปลงค่าหรือหาผลลัพธ์ลองศึกษาแนวทางนี้ดูครับจะทำให้โค้ดสั้นลงและเร็วขึ้นอีกด้วย
使您的Swift应用更具React Nativey 自白 我要告诉你一个肮脏的小秘密。 有时候,我很想念React Native。 我知道我知道。 感觉很不对劲。 但是其中有些感觉是正确的。 反应性的,声明性的UI代码? 热装? 可以绕过应用商店的更新? 而且即使Javascript在很多方面不如Swift出色,它也变得相当不错(新的异步/等待和Flow的渐进类型检查)。 我一直不时地尝试它, 希望它变得惊人,并让我摆脱所有在iOS开发中发疯的事情。 当然,它并非没有缺点,但某些功能却非常有趣且富有成效-谁不想玩得开心又富有成效? 对于我们这些人来说,React Native并非可行之举,如果我们仍然可以在编写Swift的同时获得一些功能呢? 今天,我们将探讨如何拥有反应性的,声明性的UI代码和热重载应用程序数据,从而节省大量测试时间。 另外,也许我们可以做一些绕过应用商店进行更新的事情吗? 反应式,声明式用户界面 React Native使我们可以编写UI代码,感觉更像是对UI的描述,与配置和转换所有数据的逻辑分离。 我们没有花哨的虚拟DOM React,但是我们可以解决这个问题。 Reactor是我编写的一个小型Swift库,灵感来自Elm,Redux,以及Benjamin Encz等人撰写的出色ReSwift著作。 请参阅文档以更深入地了解Reactor,但是我们正在使用的基本模型是: 查看示例项目,看看它是如何完成的。 但这几乎就像您可能想象的那样:我们的状态旨在使用Marshal进行序列化/反序列化,然后将其全部与我们的体系结构和文件监视程序一起使用。 我认为这里有很多潜力:重新创建用户报告的错误状态,无需重新编译即可测试UI,轻松检查应用程序的当前状态……各种有趣的东西。 绕过App Store 我们正在迅速接近已知的iOS世界的终结。 由于其解释性,Javascript不仅可以热重载代码,而且可以热重载已通过网络接收的代码。 这带来了A / B测试的整个可能性,绕过了应用商店进行某些更新和安全漏洞。 😛 正如我们之前讨论的那样,我们无法热重载Swift代码。 但是,我们知道可以热装应用程序数据。 那么,如果我们将更多的UI表示为应用程序数据怎么办? 也许我们可以编写一些可重用的组件,并且数据本身会告诉我们它要使用哪个UI组件。 正如约翰·桑德尔(John Sundell)所展示的,这是Spotify正在做的事情。 观看该视频。 很酷,很酷的东西。 结论 React Native从iOS社区获得了一些帮助。 尚未尝试过的开发人员可能不应该得到很多,但像所有工具一样,它也都有其优点和缺点。 也许这些缺点在您的项目中对您不利。 这并不意味着我们不应该垂涎专家,也不应该试图弄清楚如何将其他领域的出色软件开发人员的想法应用到我们自己的领域中。
每个想成为高级开发人员的初级开发人员,都必须从“设计模式”中学习,该模式是Erich Gamma,Richard Helm,Ralph Johnson i John Vlissides的经典著作。 我不得不承认,我从“设计模式”开始并不容易-毕竟,这是一本充实的抽象指南,也是您必须发展的如此抽象的思维方式。 幸运的是,在这个痛苦的过程中,我有一个同伴,我忠诚的黑人拉布拉多·肯迪(Labrador Kendi),每当我开始入睡时都会叫醒我。 我相信“实践能成为大师”,并且您应该始终以自己的语言来表达抽象以真正理解它。 而且,因为值得与他人分享-我们将与Kendi一起分享有关模式的知识。 那么谁愿意,让我们读… 首先-模式到底是什么? 它总是从问题开始,必须解决它。 有人找到优化的解决方案,可以在这种情况下使用。 因此,如果您知道该模式,则无需自己发明。 因此,正确识别问题的类型至关重要。 因此,我们将从案例分析开始讨论每种模式。 案号 1-我们要构建不同类型的复杂对象。 这些目的是一个制造过程的结果。 如何在不复制代码的情况下构建这些对象? 解决方案是使用“构建器”模式,其中复杂的对象创建算法独立于该对象的组件和组件的连接方式,并且构造过程允许创建不同类型的对象。 用例:如果我是狗屋生产的总监(干什么!),我会雇用一名首席建造者来创建狗屋项目。 反过来,这名建筑商会继承其他将完成此项目的建筑商,结果建造了不同类型的狗屋(一间小房子用于贝塞特犬,一间大房子用于拉布拉多犬)。 案号 2-我们希望能够在运行时添加和删除产品。 我们要避免创建与产品类层次结构相对应的工厂类层次结构。 解决方案是使用原型模式。 用例:我们发现狗屋的生产没有回报。 相反,我们购买现成的狗屋。 在订购时,客户会给我们提供首选项,例如“为该颜色绘画”或“在前面添加此标题”。 我们通过将原型克隆与客户的偏好相结合来动态创建新产品。 总结一下: 创建模式有助于保持系统独立于对象创建,组成和表示的方式。 它们封装了系统使用哪些特定类的信息,并隐藏了创建和组成对象的过程。 对复杂对象创建过程的最佳控制是生成器模式。 它会逐步生成产品,并且只有在过程完成后,导演才能从Builder中获取产品。 其他模式只需一步即可创建对象。 工厂方法是一种流行的对象构造函数,当一个类想要将一个任务委托给其他一些辅助类时,该方法特别有用。 工厂方法的缺点是创建了并行的类层次结构(产品类=构造函数类)。 因此,有时最好使用与工厂方法相反的原型模式,该模式通过克隆对象而不是创建新对象来减少类的数量。 此外,原型模式是唯一一种在运行时提供添加和删除产品功能的模式。 本文还没有提到其他设计模式:抽象工厂和单例。
思想和基准。 这个主意。 Baya的想法可以追溯到2016年6月。具有讽刺意味的是,Android开发人员Backstage Podcast的第50集-最重要的是ContraintLayout ,这个概念与Baya完全不同。 进入事件大约15分钟后,讨论转移到一些基本原则,例如将视图层次结构与布局层次结构分离以及它们称为“虚拟视图组”的概念。 切特总结了这部分内容: “因此,它为您提供了从ViewGroups或单独的布局获得的封装,而在这些嵌套的东西的视图层次结构中没有额外的开销” 但是,这就是事情。 我真的很喜欢查看布局代码,并且能够快速推断出布局的外观。 使用ContraintLayout至少可以使您摆脱ContraintLayout 。 当使用这样的系统时,我最终会使用可视化编辑器。 梦想是保持可读性,但将布局和视图层次结构分开。 Android和Java的问题是,要么在实现适合现有系统的布局类时扩展View ,从而根本不展平视图层次结构,要么子类化我们要使用的每个View类我们的布局系统,以使它们实现新的界面。 两种选择都没有太大意义,就是这样。 当我和JoachimFröstl开始为iOS开发时,Swift改变了所有这些情况。 轻量级结构以及使用扩展添加协议一致性的能力正是我们所需要的。 我们从编写一个简单的协议和一些扩展程序开始,使我们的生活更轻松-没多长时间,Baya诞生了。 这个概念。 Baya围绕一些原则构建。 它们都起源于核心思想,除了最后一个更像是表现。 通过分离布局逻辑的平面视图层次结构。 通过将布局代码封装在具有描述性名称的结构中,以提高可读性。 通过面向协议的可扩展性。 一个人应该能够编写自定义封装的布局逻辑并将其插入。 布局定义,测量阶段和布局阶段的分离。 一个例子。 每个UIView都是一个BayaLayoutable 。 您可以在BayaLayoutable或BayaLayoutable的数组上调用Extension函数来创建布局。 这些布局还实现了BayaLayoutable 。 最后,通过调用layout?.startLayout(with: bounds)在layoutSubviews()或viewWillLayoutSubViews()启动布局例程。 如果需要度量通过的结果,例如在sizeThatFits() ,请调用layout?.startMeasure(with: size) 。 在100个子视图中具有19毫秒的时间,看来Baya是使用上述实现方式禁食的对象。 介意的不是很多,但是我们就在PinLayout的正下方。 这是另一款配备iPhone 6Plus的手机(我周围有一个)。 我认为这几毫秒不会带来很大的变化,因此请以该基准为准。 如果您有兴趣,请查看回购-如果您认为我在某处作弊,请在下面发表评论! 谢谢阅读! 我希望您喜欢阅读本文。 将这些想法写下来然后忘掉是很有趣的。 截至撰写本文时,Baya仍为0.2.0版本。 我们在两个项目中使用了它,并且很享受与它一起工作。 一些布局挑战使我们几次改进了API。 由于我们大部分时间都是自己使用Baya,因此我们没有得到太多反馈,也不想暂时锁定API。 在代码库中发现令人尴尬的错误? 对概念还是徽标中的酷鸟有什么想法? […]
任何和任何? 在Swift中很奇怪。 我们使用Swift Reflection API作为研究的基础,探索未知的深处,并在与Any一起工作时发现Swift Cast API的某些不一致行为。 最近,在使用Swift Reflection API时,我偶然发现了一个痛苦的问题。 基本上,当类型转换为Any和Any时? 遵守协议Swift束手无策,并开始把我迷住了。 事不宜迟,这是吃掉我,强奸我并杀死剩下的代码的代码(请注意,按照该特定顺序): 您可以在我以前的博客文章中了解有关强制转换功能的更多信息: Swift中的类型推断 我要坦白。 我真的对在我的代码中各处编写iflet和guard感到厌倦。 有… blog.idapgroup.com 如果我们为嵌套属性运行代码,结果将与预期的一样: 类型=可选(嵌套) 巢状 嵌套可查询 嵌套为AnyObject的Greetable 当我们尝试使用optionalNested属性运行printCasts时,有趣的部分开始了: 电话的结果就像T-Rex试图藏在衣柜里戴上帽子一样奇怪: 类型=可选(可选(嵌套)) 巢状 嵌套为AnyObject的Greetable Swift尝试将Optional <Optional >解包到嵌套中 ,但是当解压缩为Nested符合的Greetable协议时却失败了,但是当我们完成中间转换时,设法对协议进行了双重可选的解包到AnyObject 。 在最基本的层次上,这确实很糟糕,因为我们不能使用相同的函数来处理Any所隐藏的不同值,并且我们没有任何非显式的方式来了解其中的内容。 请注意,这里的不规则行为是double可选项的展开。 optionalNested键的值本身是可选的,因为该属性是可选的,并且在第一次打包时将其包装在另一个可选中。 叫做。 对于optionalNested ,这三个条件都不应该起作用。 这一点对于从Type显式展开是有效的? 键入 ,其中类型!=任何 : 这导致编译器错误: 从“ Int ??”开始向下转换 设为’Int’仅解开可选内容。 我尝试玩耍,发现另一个有趣的行为: 打印1 。 因此,似乎在强制转换为Any时,就像编译器会自动解包一样? 然后,如果将其强制转换为Type,则会导致另一个展开。 那么,我们应该如何解决呢? […]
在此处找到原始帖子。 前言 计算机是由多个硬件组件组成的复杂机器。 然后是一个软件层,可以有效地利用这些组件来执行所需的任务。 这些复杂的机器很多时候互相交谈以共享信息或委派一些任务。 所有这些任务在某个时间点都会处理数据。 对整个生态系统的研究被广泛称为计算机科学。 科学领域,其整个重点是使一组任务自动化。 我们将不断发展和改善现有的生态系统,并期望它能为我们做更多的事情。 在硬件组件上不时有值得称赞的改进。 随后,我们改进了软件方法,以充分利用这些笨拙的组件。 我们发明了操作系统,内核,编译器,并逐步对其进行改进以与硬件相匹配。 为了构建这些功能强大的软件,需要开发出具有更多功能和更多功能的新编程语言。 每种编程语言均出于一组目的而存在,并且支持一个或多个编程范例。 这样的范例之一就是面向对象的编程(OOP),它于1960年代初期引入,并从那时起被广泛使用。 这种范式要求我们根据对象来思考一切。 OOP通过其核心原理(抽象,封装,继承和多态性)具有解决现实问题的强大能力。 因此,许多编程语言已成为OOP的主要范例。 诸如C ++,JAVA,Objective-C等OOP语言通过分类,子分类,方法重载,抽象(协议)等支持了核心原理。 不过有一些注意事项– 所有这些功能仅可用于对象(引用类型)。 诸如结构和枚举之类的值类型无法利用这些功能,因此它们仅保留了数据存储空间而已。 我们失去了值类型是线程安全的巨大优势。 结果,我们不懈地致力于解决对象(引用)的线程安全问题。 同样,大多数OOP语言由于其性质的复杂性而不支持多重继承,因此不支持多重继承。 例如:假设歌手和演员都从其父艺术家Artist继承,他们都免费获得了Artist实现的通用功能 但是,如果要求说某些歌手也可能是演员,那么继承树将看起来像– 在这里,我们也将每个歌手都设置为演员 ,当歌手不是演员时,这会强制不相关的功能。 期望 这些惊人的OOP功能也应该有一种可用于值类型的方法,这样我们就不必担心解决线程安全的成本。 而且,如果我们可以在不给我们的类型带来太多复杂性的情况下带来多重继承,那么我们就可以完全避免上述问题。 解决方案—面向协议的方法 时间需要不同的思维方式。 超越OO方式的思考。 面向协议的方法。 但是首先,什么是协议? 协议是一组规则和要求(方法和属性),类型(值或引用)需要满足。 将协议视为其要求的抽象蓝图。 一个类型可以相应地实现这些要求,并称其符合协议。 此外,一种类型可以符合多种协议。 让我们尝试通过面向协议的方法来解决上述问题– 我们声明了三个协议, 艺术家 , 演员和歌手 。 演员和歌手都继承自Artist协议。 每个协议都已声明其要求。 例如,符合Artist协议的类型需要在其实现中定义名称和年龄。 同样,符合Singer协议的类型需要提供name , age , […]
照片,视频,文档对布告栏用户至关重要-这是他们交流和分享工作场所中日常活动的方式。 在为该应用的iOS版本开发此功能时,我意识到没有单个代码块可以从设备访问媒体文件。 这就是这件作品的来源。 如果您只需要一段代码即可完成此操作,请随时将其插入您的应用程序。 以下是创建自定义类的分步教程, 该类将帮助开发人员使用swift 4访问基本附件,例如“相机图像”,“照片库”,“视频”和“文件导入”。 TL:DR —您可以在此处查看其完整的GIST文件。 我已将其命名为AttachmentHandler.swift 步骤1:使用UIAlertController创建操作表 通过使用UIAlertController创建操作表。 我将在操作表中列出所有四个选项,并在底部列出“取消”按钮。 如果您想进一步了解UIAlertController。 请您在这里检查。 您也可以查找UIActionSheet,但这已被描述。 func showAttachmentActionSheet(vc:UIViewController){ currentVC = vc 让actionSheet = UIAlertController(标题:Constants.actionFileTypeHeading,消息:Constants.actionFileTypeDescription,preferredStyle:.actionSheet) actionSheet.addAction(UIAlertAction(title:Constants.camera,style:.default,handler:{(action)-> Void in self.authorisationStatus(attachmentTypeEnum:.camera,vc:self.currentVC!) })) actionSheet.addAction(UIAlertAction(title:Constants.phoneLibrary,style:.default,handler:{(action)-> Void in self.authorisationStatus(attachmentTypeEnum:.photoLibrary,vc:self.currentVC!) })) actionSheet.addAction(UIAlertAction(title:Constants.video,style:.default,handler:{(action)-> Void in self.authorisationStatus(attachmentTypeEnum:.video,vc:self.currentVC!) })) actionSheet.addAction(UIAlertAction(title:Constants.file,style:.default,handler:{(action)-> Void in self.documentPicker() })) actionSheet.addAction(UIAlertAction(title:Constants.cancelBtnTitle,style:.cancel,handler:nil)) vc.present(actionSheet,动画:true,完成:无) } 步骤2:检查授权状态 .. 来自PHPhotoLibrary 。 这意味着我们必须验证用户是否已获得访问其照片的权限。 在Info.plist中添加两行 隐私权-相机使用说明 隐私权—照片库使用说明 […]