Tag: 编程

Swift 3.0的新增功能以及您为什么要关心

自Apple的Swift于2015年12月开源以来,来自世界各地的开发人员一直在要求该公司引入其核心功能的变化。 在考虑了提议之后,Swift 3.0的beta版本终于在本月发布,它带来了许多值得一试的功能。 该版本的主要目标是丰富Swift语言并增强开发经验。 从大量改进工具质量到对API进行大规模修改以及为改善Objective-C API的自动命名指南,Swift 3.0为程序员提供了很多存储空间。 在列出这些功能之前,让我们简要介绍一下什么是Swift及其如何演变。 什么是Swift? Swift是一种针对iOS,OS X,watchOS和tvOS应用程序的编程语言,它基于C和Objective-C的最佳组合而构建,不受C兼容性的限制。 Swift采用安全的编程模式,并添加了现代功能,使编程更加轻松,灵活和有趣。 Swift对Objective-C开发人员感到熟悉。 它采用了Objective-C命名参数的可读性以及Objective-C动态对象模型的强大功能。 它提供对现有Cocoa框架的无缝访问,以及与Objective-C代码的混合匹配互操作性。 它是第一种与脚本语言一样表现力和令人愉悦的工业级系统编程语言。 它支持游乐场,这是一项创新功能,使程序员可以试验Swift代码并立即查看结果,而无需构建和运行应用程序。 修订记录: 每个版本的Swift的一些主要亮点: 2016年3月21日:Swift 2.2 –删除了有关C样式for循环,++前缀和后缀运算符以及—前缀和后缀运算符的讨论。 –在“选择器表达式”部分中添加了有关Objective-C选择器的#selector语法的信息。 –在“构建配置语句”部分中添加了有关如何根据所使用的Swift版本有条件地编译代码的信息。 2015年10月20日:Swift 2.1 –更新了“通过可选链接访问属性”部分,以阐明通过可选链接进行分配的行为。 –更新了“字符串插值”和“字符串文字”部分,因为字符串插值可以包含字符串文字。 2015年9月16日:Swift 2.0 –添加了有关新尝试的信息? 将错误转换为可选值部分的关键字。 –将有关API可用性检查的信息添加到“控制流”一章的“检查API可用性”部分和“语句”一章的“可用性条件”部分。 –更新了“同时重复”部分,其中包含有关“同时重复”循环的信息。 –使用有关标记的中断语句的信息更新了“中断语句”部分。 2015年4月8日:Swift 1.2 – Swift现在具有本机Set集合类型。 –在运行时可能失败的类型转换现在使用as? 还是一样! 运算符,并使用as运算符来保证不会失败的类型转换。 –更新了协议声明以阐明协议声明的范围和成员。 2014年10月16日:mSwift 1.1 – Any类型的常量和变量现在可以包含函数实例。 更新了Any的示例,以显示如何在switch语句中检查并强制转换为函数类型。 –现在,具有原始值的枚举具有rawValue属性而不是toRaw()方法,并且具有rawValue参数而不是fromRaw()方法的失败的初始化器。 2014年8月18日:Swift 1.0 –添加了有关仅类协议的新部分。 –在“声明属性”部分中添加了有关可用性属性的信息。 –可选参数不再具有值时隐式评估为true,而没有赋值时则隐式评估为false,以避免在使用可选Bool值时产生混淆。 而是使用==或!=运算符对nil进行显式检查,以找出可选值是否包含值。 […]

多项数学创作者博客#3:动量

大部分时间都可以坐下来编码。 该死的,我没有抓住机会。 发现到目前为止,我想要在此应用程序中实现的所有功能绝对引人入胜,我能够毫无问题地实现。 猜猜通过树屋之类的网站了解核心概念的所有时间已经开始得到回报。 学会UIAlertController到几乎流利的程度,集成了UIImagePickerController,学会了如何将DatePicker集成到UITextfield中。 然后最重要的是,我成功地将所有这些不同数据类型的状态存储到我的自定义EventData结构中,然后成功地打印回了我想要的值! 还集成了受密码保护的UITableViewCell,我真的很惊讶通过谷歌搜索/调整代码来实现这一点。 现在,我遇到的主要问题是:将自定义DataType保存到某种持久性存储中。 我以为可以将其存储在UserDefaults中,但是出现的错误使我想到可能必须使用其他工具才能获得此结果。 将我的问题提交给iOSProgramming子reddit,我们希望对此有解决方案!

教程设计模式-OOP的力量(第1部分)

先决条件—本博客系列需要具有面向对象编程的中级专业知识。 您应该具有有关类,对象,构造函数,继承,值和引用类型的基本知识。 通过从头到尾阅读本系列文章,中级者将获得知识,专家将增强其知识。 设计模式用于表示经验丰富的面向对象的软件开发人员社区所采用的最佳实践。 生成器设计模式可帮助我们以更简单易读的方式构建对象。 生成器设计模式遵循以下两个简单规则。 分开原始的类表示形式及其构造方法。 在最后一步返回类的实例 问题: 考虑一下类,说Person具有十个或更多属性,当您需要创建Person类的实例时,对它的构造函数进行设计。 它的构造函数将使用十个或更多的参数,很难将多个参数作为单个函数或构造函数进行管理,最终,您将失去代码的可读性。 查看以下示例。 尝试在操场上运行上面的示例,它将成功运行,并为您提供预期的输出。 从逻辑上讲这是正确的。 我们可以通过克服以下几点来改进上面的示例。 我们必须以提到的顺序传递值,不能重新排列参数序列以提高可读性。 即使在对象创建时不知道某些值,我们也必须传递所有值。 例如,假设您需要创建一个Person类的对象,但是此人仍在寻找工作。 当该人加入任何公司时,只有我们会提供作品详细信息。 解: 创建相关属性的逻辑组。 为不同的属性组创建单独的构建器类。 在最后一步中检索实例。 让我们用一个例子简化一下, 在示例WithoutDesignPatternExample1.swift中,我们已经有一个名为Person的类,其中有14个属性。 如果我们仔细检查所有14个属性,则这些属性具有4个逻辑组。 个人详细信息属性 联系人详细信息属性 地址详细信息属性 公司详细信息属性 多面设计和流畅设计模式共同帮助我们克服了上述两个问题。 在上面的示例中,我们将Person类的职责划分为不同的类。 现在, Person类仅包含数据属性,而我们创建了多个构建器类,它们负责构建/更新相对的属性组。 我们有一个基本的构建器类PersonBuilder ,还有四个派生的构建器类,分别为PersonPersonalDetailsBuilder , PersonContactDetailsBuilder , PersonAddressDetailsBuilder和PersonCompanyDetailsBuilder 。 基类PersonBuilder帮助我们随时在多个构建器之间切换,而派生自PersonBuilder的其他四个构建器负责更新相对属性。 在上面的示例中,我们可以清楚地看到,与第一个示例WithoutDesignPatternExample1.swift相比, Person对象的构造更具可读性,而且我们可以随时以更易读的方式更新属性组或任何单个属性。 在上面的示例中,请注意,在调用每个属性更新方法后,我们将返回生成器实例的自身。 这有助于我们编写同一构建器的多个方法的链接,而不是分别编写多行。 这个概念被称为流畅模式。 好处: 以更易读的方式轻松初始化具有太多属性的类的对象。 遵循单一责任原则。 根据您的方便,以任何顺序初始化对象或更新属性。

使用可编码对带有关联值的枚举进行编码和解码(Swift 4)

在下载管理器框架的Swift 4迁移过程中,我重写了模型对象(符合NSCoding NSObject子类)。 我的DownloadItem的状态由带有关联值的枚举表示: 使用Swift 3,我必须编写一个符合NSCoding的包装对象,以保留该枚举。 使用Codable不再需要此解决方法,因为我可以直接向枚举添加Codable一致性。 现在,有不同的方法可以实现此目的。 我仍然不确定最好的解决方案是什么,但是也许有人可以使用我目前的方法。 在查看DownloadState ,让我们看一下一个简单的Value枚举示例: 在类型和大小写之间存在一对一的映射,因此我们可以设置一个如下所示的容器: //伪字典 [“ string”:字符串,“ int”:Int,“ data”:数据,“ double”:Double] 毕竟, KeyedDecodingContainer和KeyedEncodingContainer只是非常严格的字典,其中下标键是强类型的String枚举(符合CodingKey ),而getter和setter利用Swift的错误处理系统来提供有意义的错误,说明为什么获取或设置特定键的值可能失败。 因此,至少对我而言,将容器视为具有固定键的字典是有意义的🙂 为Value实现Codable可能看起来像这样: 我们使用decodeIfPresent函数,因为将只设置一个密钥。 缺点是我们不使用switch语句进行解码,因此当我们添加新的大小写而忘记对其进行解码时,编译器不会对我们大喊大叫。 而且,它不适用于DownloadState示例,因为我们有带有和不带有关联值的案例。 我的方法是使用“基本”案例和关联值作为CodingKey ,然后让一个私有枚举将所有基本案例作为简单String托管。 让我们看看它的外观: 我真正喜欢的是编译器可以完全自动生成Base的Codable实现,因为它只是一个String枚举。 不幸的是,我们仍然必须为DownloadState provide提供Codable实现。 以下伪字典都是DownloadState所有有效表示形式。 //伪字典 [“基地”:“取消”] ->下载状态。取消 [“ base”:“ paused”,“ pausedReason”:“ waitingForWifi”] -> DownloadState.paused(原因:.waitingForWifi) [“基础”:“下载”,“下载进度”:0.5] -> DownloadState.downloading(进度:0.5] 可以缩放吗? 不……如果涉及多个关联值,则实际上这是一个非常复杂的类型,应像嵌套结构或类一样进行处理。 请考虑以下示例,其中Route表示带有主页和详细信息页面(用于播放音乐)的音乐应用程序的不同屏幕: 超级简单吧? 但是将每个关联的值添加到CodingKeys 有一些缺点: 在与基本情况相同的层次结构上具有关联值在语义上是错误的(就像在DownloadState示例中一样,但是更加突出) 如果枚举得到更多的情况(和更多的关联值),这将变得更加难以阅读和维护 如果这是一个类或结构,则您永远不会考虑对父代中嵌套类型的信息进行编码。 […]

在Swift中更轻松地使用JSON和POP编码

让我们从符合Codable的简单类型开始。 在这种情况下,我们将使用微博帖子,因为这是我现在花费太多精力的原因。 struct Post:可编码{ 让标题:字符串? 让内容:字符串 } 目前,我们大多数人都在像这样对JSON进行编码和解码。 let aPost = Post(title:nil, 内容:“一些非常有趣的评论”)//编码为JSON数据 让coder = JSONEncoder() 让数据=尝试? coder.encode(aPost)//从JSON Datalet解码器解码= JSONDecoder() 让restorePost =尝试吗? coder.decode(Post.self,来自:数据!) 这很好并且相对容易,但是每次仍然是相当数量的样板。 首先,您需要一个编码器/解码器,并且必须处理Codable API方法正在抛出方法的事实。 在此示例中,我try? 可选的返回方法。 如果您需要的不仅仅是返回值的可选值,那就更麻烦了。 然后,您将推出do-catch块以捕获和解析错误,如果您从不受控制的Web API消费JSON数据,则应该完全这样做。 借助一点点的POP,面向AKA协议的编程,魔术可以做得更好。 在可选返回值仍然足够的情况下。 将值类型存储到NSUserDefaults或以其他方式存储到磁盘以进行检索就是这种情况。 我们可以肯定地知道我们要存储和检索的内容,因此我们实际上并不需要错误捕获模式。 我们从我们的类型可以遵循的协议开始。 该协议没有任何要求,因为它将使用扩展程序来为这些便利功能提供默认功能。 协议JSONCodable {} 我们只希望此默认功能可用于已经符合Codable类型。 我们可以通过将协议作为Codable的扩展来实现这Codable ,但是我希望这些事情更加明确。 我们不想意外地忘记在其他Codable类型上使用这些方法,我们不确定可选返回是否足以满足要求。 为了实现这两个目标,我们将使用我们自己的显式协议JSONCodable并将其扩展JSONCodable也限制为Codable 。 这是我们的协议扩展。 它包含一些静态变量和2种方法,使其成为简单的代码行即可获取我们类型的JSON Data版本或从JSON Data中还原其实例。 扩展名JSONCodable其中Self:Codable { //我们方便使用的编码器和解码器。 //这些是类型要使用的静态变量 //本身而不是实例。 静态var编码器:JSONEncoder […]

为什么Qt for C ++仍然是事实:F噪音

如今,当您谈论桌面开发时,人们看着您就像是某种Luddite。 尽管对移动技术进行了大肆宣传,但诚实的事实是,最高效,最复杂的工作仍在台式机上(或通过在台式机上运行的浏览器)进行。 我喜欢Java,Swift及其它们,但是在构建桌面应用程序时,串联Qt的C ++仍然是最好的。 以下是我在2017年仍然是Qt迷的一些原因: 简单 具有C ++的Qt 易于使用。 唯一可比较的其他开发环境是XCode。 在启动过程中有了无数的出色范例,很快就可以弄湿自己的脚。 我知道,成为编码员的吸引力在于解决“凡人”几乎无法理解的那种复杂性,但是我还是简化UI构建之类的基本任务的忠实拥护者,以使其成为一门艺术而不是代替它可以解决一个复杂的数学问题。 Qt来自Java Swing和PyGTK背景,对我来说,Qt是天堂。 快速。 非常快。 众所周知,C ++是一种非常快速的语言,我相信Qt已经利用了这种速度。 比较我过去开发的软件的开发和交互,Qt总是比较灵活(我没有做任何基准测试,所以我可能是错的)。 即使在今天,当我大部分时间都在XCode上度过时,我仍然不禁为Qt的速度和轻便程度惊叹。 当然,这可能是基于我作为编码员的内部偏见和限制。 以下是我很久以前进行的基于GUI的原始归类的摘要。 在给定大数据集的情况下,它的工作方式像一种魅力,并且比Java更加清晰。 您可以自己尝试。 // MergeSort.cpp //类MergeSort成员函数定义。 #include 使用std :: vector; #include“ merge_sort_budget.h” //类MergeSoft定义 / ** MergeSort类的构造函数。 @param btList bt列出预算选项卡列表。 * / MergeSortBudget :: MergeSortBudget(BudgetTabList btList) { 大小= btList.size(); //验证vectorSize //使用带有不同日期的随机BudgetTabItems填充向量 对于(int i = 0; […]

斯威夫特のコンパイルエラーの仕组み

そンパイルエラーが出たときに原因を(りたンパイラのソース分析的に)探りたいときがある。その水深1cmまでをまとめてみたい。 これを読む阳离子(水深0.1cm) 手元にSwiftのコードがあること。下の场所から入手できる。私は下载Zip bonタンロードした。 苹果/斯威夫特 swift – Swift编程语言 github.com エラーメッセージのありか(水深0.3cm) 普段,プログラミンミ中に目にするエラーメッセージの文章は / include / swift / AST の中にある 诊断***。def という,拡张子がdefのファイルにまとめて书かれている。このファイルは复数あって,***には化化された名前が入る。 以下のものがある。 DiagnosticsParse.def DiagnosticsSema.def DiagnosticsClangImporter.def 诊断SIL.def 诊断IRGen.def DiagnosticsFrontend.def DiagnosticsDriver.def DiagnosticsRefactoring.def DiagnosticsCommon.def DiagnosticsAll.def での中で,DiagnosticsParse.def变成一个を抜粋するとこんな感じである。これは闭じ波括弧が多いというエラーメッセージ。 错误(extra_rbrace,none, “顶级的外部’}’”,() 定义数が多いものは,Swift4.1の时点で DiagnosticsParse.defに500以上 S800以上 ある。 ***の记事ではこのDiagnostics ***。defを「メッセージ定义ファイル」または「.defファイル」ということにする。 メッセージ定义の形式(水深0.7cm) メッセージ定义ファイル内の个々の定义は基本的に 错误(ID,选项,文本,签名) の形で行う。 ID エラーを识别を文字列。エラー発生处理でエラーを指定するのに用いる。 选项 何か付加情报を入れるようだが何もないことが多い 文本 コンパイル时に确定する部分は%が付けられている。これはC言语のprintfやObj-CのNSLog方式に似ている。 签名 Textのメーメッセージの中でコンパイル时に确定する部分の型をタプル形式で与える。文字の中でこれらが入る部分にはあらかじめ%が付けられている。 さっきのメッセージをあらためて见ると 错误(extra_rbrace,none, “顶级的外部’}’”,() […]

UICollectionView快照滚动和分页

对于具有相同大小的单元格和一个部分的集合视图,这是一种捕捉逻辑(可以轻松添加更多部分的逻辑)。 scrollViewWillEndDragging具有inout targetContentOffset参数,这意味着我们可以读取和修改滚动的结束位置。 幸运的是,我们不需要考虑插图,行或项目的间隔( 由于包含了它们而浪费了很多时间,因此无法理解为什么正确的数学会产生错误的结果 ),但是我们需要考虑情况用户滚动到最后一页的位置-targetContentOffset将在范围之内,但当前contentOffset不在范围内,因此我们也需要检查一下: //获取单元格宽度 让cellWidth = collectionView( collectionView, 布局:collectionView.collectionViewLayout, sizeForItemAtIndexPath:NSIndexPath(forItem:0,inSection:0)).width let page:CGFloat //计算建议的“页面” 让proposedPage = targetContentOffset.memory.x / cellWidth // 3.25应该返回第3页:floor(3.95)== floor(3) // 3.3+应该返回第4页:floor(4.0+)!= floor(3) 如果floor(proposedPage + 0.7)== floor(proposedPage) && scrollView.contentOffset.x <= targetContentOffset.memory.x { 页面=楼层(建议页面) } 其他{ 页=楼板(建议页+ 1) } //替换滚动的结束位置 targetContentOffset.memory = CGPoint( x:cellWidth *页面, y:targetContentOffset.memory.y ) 如果需要“真正的”分页,如一次滚动一页,我们需要做一些改动: //我们需要保存起点 私人var startingScrollingOffset = […]

Swift中的扩展

我在以前的博客中使用过Extension for Label。 在那里,我在扩展中添加了所有代码,但是您为什么想在本章中知道为什么这样做,我将很清楚所有这些东西在您自己的项目中创建和使用非常容易。 什么是扩展? 扩展为现有的class , structure , enumeration , or protocol type添加了新功能。 这包括扩展您无法访问原始源代码的类型的能力(称为追溯建模)。 扩展类似于Objective-C中的类别。 (与Objective-C类别不同,Swift 扩展没有名称。) 资料来源–苹果文件。 创建您的第一个扩展 通过写出类或Controller类(如extension和类名)的侧面, 扩展很容易创建 扩展UserModel { //您的功能 } 您可以将其用于符合协议 如果您在项目中使用表格视图,则需要使用这些方法来确认协议,但是,如果项目中以及其他协议中有很多方法,那么这将很难管理,并且大多数情况下,我们在查找代码时会遇到问题在我们班里。 在这个类中,您可以看到,这是每个这样开始开发的开发人员在开始阶段的基本代码。 如果您开始从事实际项目,这是一个很小的类,那么将有更多的功能和对象变得更加难以快速查找或检查您的代码。 现在,您可以非常清楚地看到您的代码被分为具有适当功能标识的组,其中Extension非常清楚地在此处定义了代码。 额外提示–“ MARK ”这将在文档编制过程中出现。 您可以访问此 ( NSHipster )链接以更好地理解Swift语言中的代码文档。 带扩展的代码分离 您可以借助扩展来编写属于特定协议的单独协议方法。 当您将来再次在同一个类中进行工作或进行修改时,它非常易于理解的代码。 芒果类: UIViewController { 覆盖func viewDidLoad (){ 超。 viewDidLoad () } } // MARK :-TableView数据源方法 […]

RxSwift和可变参数DisposeBag的秘密

使用RxSwift的最新功能之一来显着清理代码 我的公司已经将RxSwift用于所有新的iOS项目已有一段时间了,我们开始欣赏它的强大功能,灵活性和简洁性。 就是说,我们可以说RxSwift在一个区域不那么简洁。 实际上,这是完全多余的。 所以今天,让我们谈谈Disposables和DisposeBags。 一次性用品和DisposeBags? 如您所知,Disposables和DisposeBags是RxSwift对Swift的ARC内存管理的让步。 当您订阅或绑定到RxSwift Observable或从RxSwift Observable驱动时,该订阅将返回Disposable。 一次性使用基本上是对该订阅以及该订阅的整个Observable链的引用。 在处置该一次性物品之前,订阅链一直存在(除非订阅收到完成事件或错误事件,但这是另外一回事了)。 所以。 最重要的是,订阅会返回我们需要维护的一次性物品,以便正确控制订阅的生命周期。 为了方便起见,这些一次性物品通常插入已创建的DisposeBag中,并附加到UIViewController(或在某些情况下附加到View Model或其他对象)。 一个DisposeBag就是它所说的,一袋(或一组)一次性用品。 那对我们有什么帮助呢? 好了,当视图控制器被释放时,其变量(包括bag)将被释放。 释放disposeBag时,其deinit函数将对其包含的所有一次性用品调用dispose。 那些可抛弃型对象继而释放它们可能要参考的任何可观测对象的引用,也可能继而释放其对观测对象的引用,依此类推,等等,直至完成。 一切都已正确释放,没有泄漏,每个人都很高兴。 除了一个小问题。 冗余 因此,假设您使用的是RxSwift,而您使用的是MVVM(模型-视图-视图模型)体系结构。 在此特定屏幕上,我们的视图模型将公开一组可观察对象,而我们的视图控制器会将这些可观察对象绑定到一组标签。 很基本的东西。 代码看起来像这样。 一切都非常简单,但是也许您在上面的示例中注意到了一些多余的样板代码? 那就对了。 每个订阅(绑定)都返回一个一次性对象,必须将其添加到disposeBag中。 每个人返回它。 并且每个人都必须维护。 没有解决的办法。 还是在那里? 解? 可变参数的处理袋 现在检查以下代码。 干净得多! 但是所有一次性用品都发生了什么? 好吧,RxSwift 4.3添加了DisposeBag的insert函数的可变版本。 可变参数可以使用一个或多个参数。 在这种情况下,一个或多个一次性用品。 因为如果您看内部dispose(by:disposeBag),您会发现它只是一行代码:disposeBag.insert(self)。 因此,我们无需获取每个订阅的结果并将其功能性地链接到Dispose(by :),而是绕过中间人并将每个人直接添加到disposeBag中。 我想您会同意代码绝对更加简洁,并且通过消除一些样板代码,我们可以更好地表达该功能的意图。 请享用。 顺便说一句,如果您发现DisposeBag上的可变参数插入很有用,欢迎您。 这是我对RxSwift项目的次要贡献之一。 😉