iOS16下调用Language.name触发NSInvalidArgumentException崩溃求助
iOS 16下Core Data实体调用
name方法崩溃问题 问题描述
调试控制台报错:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Language name]: unrecognized selector sent to instance 0x11c6f8920'
该崩溃仅在iOS 16版本出现,iOS 15.7及之前版本可正常运行,崩溃触发代码行:Button(language.name ?? "", action: {
相关代码:
import SwiftUI import Foundation import CoreData struct CategoriesRevisionView: View { @State private var selectedLanguage: String = "" @State private var selectedLanguageSection: String = "" @State var languagesWithSectionThingHomework: [Language] = [] @FetchRequest(entity: Language.entity(), sortDescriptors: []) var languages: FetchedResults<Language> @FetchRequest(entity: LanguageSection.entity(), sortDescriptors: []) var languageSections: FetchedResults<LanguageSection> @FetchRequest(entity: SectionThing.entity(), sortDescriptors: [NSSortDescriptor(key: "native", ascending: true)]) var sectionThings: FetchedResults<SectionThing> @FetchRequest(entity: CommonWordThing.entity(), sortDescriptors: []) var commonWords: FetchedResults<CommonWordThing> let tintColour = TintColour() var revisionThings: [SectionThing] { if self.selectedLanguageSection == "" { return sectionThings.filter{ $0.setAsRevision == true && $0.languageSection?.language?.name == selectedLanguage } } else { return sectionThings.filter{ $0.setAsRevision == true && $0.languageSection?.name == selectedLanguageSection && $0.languageSection?.language?.name == selectedLanguage} } } var languagesToAddHomework: [Language] { var languagesWithoutHomework: [Language] = [] for languageSection in languageSections { if languageSection.setAsRevision == false { if !languagesWithoutHomework.contains(languageSection.language ?? Language()) { languagesWithoutHomework.append(languageSection.language ?? Language()) } } } return languagesWithoutHomework } var languagesToRemoveHomework: [Language] { var languagesWithHomework: [Language] = [] for languageSection in languageSections { if languageSection.setAsRevision == true { if !languagesWithHomework.contains(languageSection.language ?? Language()) { languagesWithHomework.append(languageSection.language ?? Language()) } } } return languagesWithHomework } var languageSectionsToAddHomework: [LanguageSection] { var languageSectionsWithoutHomework: [LanguageSection] = [] for languageSection in languageSections { if languageSection.setAsRevision == false { if !languageSectionsWithoutHomework.contains(languageSection) { languageSectionsWithoutHomework.append(languageSection) } } } return languageSectionsWithoutHomework } var languageSectionsToRemoveHomework: [LanguageSection] { var languageSectionsWithHomework: [LanguageSection] = [] for languageSection in languageSections { if languageSection.setAsRevision == true { if !languageSectionsWithHomework.contains(languageSection) { languageSectionsWithHomework.append(languageSection) } } } return languageSectionsWithHomework } var languageCategories: [LanguageSection] { return languageSections.filter { $0.setAsRevision == true } } var body: some View { List { ForEach(revisionThings ?? [], id: \.self) { revisionThing in ThingRowView(thing: revisionThing, commonWords: Array(commonWords), resizedImage: UIImage()) .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button { setRevision.unsetFilteredHomeworkThingRevision(sectionThings: [revisionThing], languageSections: Array(languageSections), commonWordThings: Array(commonWords)) computeLanguagesWithSectionHomework() selectLanguageAndSection() PersistenceController.shared.saveDB() dataSetIsEmpty() } label: { Image("removeHomework") } .tint(tintColour.SetRevisionSectionThing(sectionThing: revisionThing)) } } } .listStyle(InsetGroupedListStyle()) .background(Color.init(.systemGroupedBackground)) .navigationBarTitle("Revision", displayMode: .inline).opacity(0.8) .toolbar { ToolbarItemGroup(placement: .navigationBarLeading) { Menu { ForEach(languagesWithSectionThingHomework, id: \.self) { language in Button("\(language.name ?? "")", action: { self.selectedLanguage = language.name ?? "" self.selectedLanguageSection = "" }) Menu("Categories") { ForEach(languageCategories, id: \.self) { languageSection in if languageSection.language == language { Button("\(languageSection.name ?? "")", action: { self.selectedLanguage = language.name ?? "" self.selectedLanguageSection = languageSection.name ?? "" }) } } } Divider() } } label: { if languageSections.filter{ $0.setAsRevision == true }.count <= 1 { Label("Choose Homework Language", image: "menu") } else { Label("Choose Homework Language", image: "menu").foregroundColor(Color.systemBlue) } } .disabled(languageSections.filter{ $0.setAsRevision == true }.count <= 1) Menu { ForEach(languagesToAddHomework, id: \.self) { language in Button(language.name ?? "", action: { setRevision.setSectionThingRevision(sectionThings: sectionThings.filter { $0.languageSection?.language == language }, commonWordThings: Array(commonWords), languageSections: Array(languageSections)) computeLanguagesWithSectionHomework() self.selectedLanguage = language.name ?? "" self.selectedLanguageSection = "" }) Menu("Categories") { ForEach(languageSectionsToAddHomework.filter { $0.language == language }, id: \.self) { languageSection in Button(languageSection.name ?? "", action: { setRevision.setSectionThingRevision(sectionThings: sectionThings.filter { $0.languageSection?.language == language && $0.languageSection == languageSection }, commonWordThings: Array(commonWords), languageSections: Array(languageSections)) computeLanguagesWithSectionHomework() self.selectedLanguage = language.name ?? "" self.selectedLanguageSection = languageSection.name ?? "" }) } } Divider() } } label: { if sectionThings.filter{ $0.setAsRevision == true }.count == sectionThings.count { Image("revisionAdd") } else { Image("revisionAdd").foregroundColor(.green) } } .disabled(sectionThings.filter{ $0.setAsRevision == true }.count == sectionThings.count) Menu { ForEach(languagesToRemoveHomework, id: \.self) { language in Button(language.name ?? "", action: { setRevision.unsetFilteredHomeworkThingRevision(sectionThings: sectionThings.filter { $0.languageSection?.language == language }, languageSections: Array(languageSections), commonWordThings: Array(commonWords)) computeLanguagesWithSectionHomework() selectLanguageAndSection() dataSetIsEmpty() }) Menu("Categories") { ForEach(languageSectionsToRemoveHomework.filter { $0.language == language }, id: \.self) { languageSection in Button(languageSection.name ?? "", action: { setRevision.unsetFilteredHomeworkThingRevision(sectionThings: languageSection.sectionThing?.allObjects as? [SectionThing] ?? [], languageSections: Array(languageSections), commonWordThings: Array(commonWords)) computeLanguagesWithSectionHomework() selectLanguageAndSection() dataSetIsEmpty() }) } } Divider() } } label: { if sectionThings.filter{ $0.setAsRevision == true }.count == 0 { Image("revisionRemove") } else { Image("revisionRemove").foregroundColor(.yellow) } } .disabled(sectionThings.filter{ $0.setAsRevision == true }.count == 0) } } .onAppear(perform: initialize) } func initialize() { outerloop: for language in languages { if let languageSections = language.languageSection?.allObjects as? [LanguageSection] { for languageSection in languageSections { if let languageSectionThings = languageSection.sectionThing?.allObjects as? [SectionThing] { if languageSectionThings.filter({ $0.setAsRevision == true }).count > 0 { self.selectedLanguage = language.name ?? "" self.selectedLanguageSection = languageSection.name ?? "" break outerloop } } } } } dataSetIsEmpty() computeLanguagesWithSectionHomework() } func computeLanguagesWithSectionHomework() { var sectionThingLanguages: [Language] = [] for language in languages { if languageSections.filter({ $0.language == language && $0.setAsRevision == true }).count > 0 { if !sectionThingLanguages.contains(language) { sectionThingLanguages.append(language) } } } self.languagesWithSectionThingHomework = sectionThingLanguages } func selectLanguageAndSection() { if revisionThings?.count == 0 { if languageSections.filter({ $0.sectionThing?.allObjects.count ?? 0 > 0 && $0.setAsRevision == true }).count > 0 { selectedLanguageSection = languageSections.filter{ $0.sectionThing?.allObjects.count ?? 0 > 0 && $0.setAsRevision == true }[0].name ?? "" selectedLanguage = languageSections.filter{ $0.sectionThing?.allObjects.count ?? 0 > 0 && $0.setAsRevision == true }[0].language?.name ?? "" } } }
问题分析与解决方案
核心原因
崩溃本质是代码中创建了未关联Core Data上下文的空Language实例,这类实例没有动态生成的name属性访问方法。iOS 16对Core Data实例的合法性校验更严格,直接暴露了这个问题,而iOS 15.7的校验逻辑更宽松,所以未触发崩溃。
具体修复步骤
1. 移除非法的默认初始化器调用
找到所有languageSection.language ?? Language()的代码,替换为跳过nil值的逻辑,避免创建无效实例:
// 修改languagesToAddHomework var languagesToAddHomework: [Language] { var languagesWithoutHomework: [Language] = [] for languageSection in languageSections { guard let language = languageSection.language else { continue } // 跳过nil的language if languageSection.setAsRevision == false { if !languagesWithoutHomework.contains(where: { $0.objectID == language.objectID }) { languagesWithoutHomework.append(language) } } } return languagesWithoutHomework } // 同理修改languagesToRemoveHomework var languagesToRemoveHomework: [Language] { var languagesWithHomework: [Language] = [] for languageSection in languageSections { guard let language = languageSection.language else { continue } if languageSection.setAsRevision == true { if !languagesWithHomework.contains(where: { $0.objectID == language.objectID }) { languagesWithHomework.append(language) } } } return languagesWithHomework }
2. 校验Core Data实体配置
- 打开Core Data模型文件,确认
Language实体存在name属性,且属性类型、配置正确。 - 确保
Language类是Xcode自动生成的,若手动编写类,需确保正确实现name的get/set方法。
3. 过滤无效实例
在生成languagesWithSectionThingHomework时,添加实例有效性校验:
func computeLanguagesWithSectionHomework() { var sectionThingLanguages: [Language] = [] for language in languages { guard language.managedObjectContext != nil else { continue } // 仅保留关联上下文的有效实例 if languageSections.filter({ $0.language == language && $0.setAsRevision == true }).count > 0 { if !sectionThingLanguages.contains(where: { $0.objectID == language.objectID }) { sectionThingLanguages.append(language) } } } self.languagesWithSectionThingHomework = sectionThingLanguages }
内容的提问来源于stack exchange,提问作者Tycho Systems
相关产品推荐
相关产品推荐

