当前位置: 首页 > wzjs >正文

定制软件开发公司常见的系统优化软件

定制软件开发公司,常见的系统优化软件,平台网站建设需求,长沙装修公司招聘概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…

在这里插入图片描述

概述

在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。

在这里插入图片描述

不过,在涉及到多个子类派生于基类进行多态模拟的场景下,稍不留神可能就会产生恢诡谲怪的错误。这是怎么回事?又该如何解决呢?

在本篇博文中,您将学到如下内容:

  • 概述
  • 1. 完美世界崩塌了!
  • 2. 刨根问底:问题根源之所在
  • 总结

在学完本课后,相信小伙伴们都会在撸码实战中重新找回自信,并向更深一层的内功修为奋勇前进!

那还等什么呢?让我们马上开始 Swift 精进之旅吧!
Let’s go!!!😉


1. 完美世界崩塌了!

在之前的这两篇博文里:

  • “一人得道,雨燕升天”:Swift 协议扩展助力 CoreData 托管类型(上)
  • “一人得道,雨燕升天”:Swift 协议扩展助力 CoreData 托管类型(下)

我们已经详细讨论过了,如何借助于精心设计的 Fetchable 约束协议成功摆脱 Swift 协议扩展中的“磨搅讹绷”。

其中,我们通过一步一步完善和重构代码,解决了 Swift 语言中颇为棘手的协议关联类型系统的匹配问题。


本文后续的讨论都将建立在上面两篇博文的故事和源代码之上,如果小伙伴们在接下来的旅程中有些 “云天雾地”,请移步上述博文一探究竟。


让我们先帮助大家做一番简单的回忆,下面就是 App 中原有的 CoreData 数据库结构:Achievement 是成就基类,而 Achv_NoBreakVictory 作为成就实体类型派生于它:

@objc(Achievement)
public class Achievement: NSManagedObject {}@objc(Achv_NoBreakVictory)
public class Achv_NoBreakVictory: Achievement {}

现在,我们需要为这一成就体系增加新的成就实体类型 Achv_MultipleSerialVictories:

@objc(Achv_MultipleSerialVictories)
public class Achv_MultipleSerialVictories: Achievement {}

在如法炮制让 Achv_MultipleSerialVictories 遵守 AchievementEvaluator 协议,并实现了所有相关方法之后,编译并运行代码我们会“惊恐”地发现 App “可耻的”崩溃了,提示如下:

Fatal error: NSArray element failed to match the Swift Array Element type
Expected Achv_MultipleSerialVictories but found Achv_NoBreakVictory

在 Xcode 调试器中可以看到,此崩溃发生的位置并不在一个“正经”的地方,搞得我们有些云里雾里,非常被动:

在这里插入图片描述

那么,到底是 App 中哪几行代码要作为“罪魁祸首”,对此负责呢?

2. 刨根问底:问题根源之所在

为了找到问题的真正根源,我们需要再展示几小段代码,以补全缺失的拼图:

protocol Fetchable: Achievement {}extension Fetchable {static func fetchRequest() -> NSFetchRequest<Self> {// 手动构建请求,确保类型安全return NSFetchRequest<Self>(entityName: "\(Self.self)")}
}protocol AchievementEvaluator: Fetchable {associatedtype Evaluator: Fetchable & AchievementEvaluatorstatic func spawnAll(context: NSManagedObjectContext) throws
}extension AchievementEvaluator where Evaluator: Fetchable {static func calcCount(context: NSManagedObjectContext) throws -> Int {let req = Evaluator.fetchRequest()return try context.count(for: req)}static func queryAll(context: NSManagedObjectContext) throws -> [Evaluator] {let req = Evaluator.fetchRequest()req.sortDescriptors = [.init(keyPath: \Achievement.orderNumber, ascending: true)]return try context.fetch(req) as! [Evaluator]}
}extension Achievement {static func spawnIfNeed(context: NSManagedObjectContext) throws {try Achv_NoBreakVictory.spawnAll(context: context)try Achv_MultipleSerialVictories.spawnAll(context: context)}
}

在上面的代码中,我们主要做了这样几件事:

  • 用 Fetchable 协议作为 AchievementEvaluator 协议的约束;
  • 在 Fetchable 协议扩展中创建 fetchRequest() 方法以确保类型安全;
  • 在 AchievementEvaluator 协议扩展中创建了 calcCount() 和 queryAll() 方法,分别用来计算实体成就类型中实例的数量和查询实例的集合;
  • 在 Achievement 成就基类中创建 spawnIfNeed() 方法用来生成所有成就实体类的实例对象;

那么,问题究竟是出在哪里呢?

原来,App 的崩溃是由于 Core Data 实体继承模型与 Swift 类型系统的冲突导致的:

  1. Core Data 继承机制的特性
    Core Data 的实体继承在底层数据库中默认采用 单表继承 策略,所有子类实例都存储在基类对应的表中。当我们执行 Evaluator.fetchRequest() 时,实际上会查询基类 Achievement 的所有子类实例,导致返回数组中混合了不同子类的类型;
  2. 协议扩展的类型欺骗
    协议扩展中 queryAll()Evaluator.fetchRequest() 虽然表面上是针对子类(如 Achv_NoBreakVictory),但实际生成的 SQL 查询却是 SELECT * FROM Achievement,返回的数组元素实际类型是基类 Achievement,强制转换为错误的子类类型时必将触发崩溃;

但是先等等,我们不是已经在 Fetchable 协议扩展中的 fetchRequest() 方法里明确说明了必须按实际的子类名称来查询的吗:

extension Fetchable {static func fetchRequest() -> NSFetchRequest<Self> {// 手动构建请求,确保类型安全return NSFetchRequest<Self>(entityName: "\(Self.self)")}
}

这个疑问不难解答。

我们在上面 fetchRequest() 方法内插入断点,再次运行可以验证:fetchRequest() 方法压根就没有执行!这说明 AchievementEvaluator 协议扩展两个方法中 Evaluator.fetchRequest() 调用的根本不是 Fetchable 协议扩展中的方法,而是托管基类 Achievement 中的默认方法!

所以,这就是问题的根本原因:我们尝试对 Achievement.fetchRequest() 方法查询出来的多种成就实体类型的实例强行做类型转换,结果可想而知。

在仅有一个实体子类时这不会产生任何问题,但当我们的 Achievement 基类派生出多个成就子类时,这个潜伏着的“致命魔鬼”就会被释放出来“为祸人间”。

那么,我们此时又该何去何从呢?

在下一篇博文中,我们将继续 Swift 精进大冒险,给出两种迥然不同的解决之道,不见不散!

总结

在本篇博文中,我们讲述了利用 Swift 协议扩展试图搞定 CoreData 基类 + 子类多态场景却意外翻车的故事,随后我们深入讨论了问题的根源之所在。

感谢观赏,我们下一篇再见吧!😎

http://www.dtcms.com/wzjs/494924.html

相关文章:

  • 单页购物网站源码googleplaystore
  • 百度云怎么做网站青岛网站排名公司
  • 凡科微信小程序免费版怎么样重庆seo技术教程博客
  • 食品网站首页模板欣赏品牌策划方案ppt
  • 电影网站的建设目标国际新闻头条今日要闻
  • 做网站开发要学多久seo百度推广
  • 佛山免费网站制作培训机构招生方案模板
  • 网站规划建设与管理维护第二版答案直通车推广计划方案
  • 传奇网站劫持怎么做百度seo排名点击软件
  • 中华人民共和国商务部seo关键词排名优化
  • 培训网站开发需求说明书佛山网络推广公司
  • intellij 网站开发seo是什么部位
  • cpa个人网站怎么做成都seo招聘
  • 网站建设课程设计免费发布推广信息的平台
  • 网站制作的电话禁止搜索引擎收录的方法
  • 上海哪家公司做网站好网络推广中心
  • 做销售的网站宁波seo快速优化教程
  • brushed网站模板网站seo链接购买
  • 织梦网站导航如何删除网站外链发布平台
  • 网站的推广费用百度指数使用指南
  • 上海有名的公司长沙百度网站排名优化
  • 天津企业网站开发关键词百度网盘
  • 中国会展公司排名前十的公司百度seo排名点击软件
  • 厦门 网站备案镇江网站
  • 渭南网站建设公司百度官网认证申请
  • 订单拆单在电商网站建设一个网站推广
  • 阜新网站开发公司合肥百度关键词优化
  • 哪里可以做产品购物网站谷歌搜索入口手机版
  • 外贸网站怎么做外链搜索引擎优化目标
  • spark怎么做网站数据库seo优化主要工作内容