programing

Xcode 8은 iOS 10에 대해 깨진 NSManagedObject 하위 클래스를 생성합니다.

nasanasas 2020. 11. 22. 19:49
반응형

Xcode 8은 iOS 10에 대해 깨진 NSManagedObject 하위 클래스를 생성합니다.


최근에 iOS 앱 프로젝트를 iOS 10으로 업데이트했습니다. 이제 앱의 핵심 데이터 모델을 변경하려고하는데 Xcode가 생성하는 새로운 NSManagedObject 하위 클래스가 손상되었습니다. 또한 하위 클래스 매뉴얼을 수정하려고 시도했지만 작동하지 않습니다.

Core Data Model의 최소 도구 버전은 Xcode 7.0으로 설정되고 코드 생성 언어는 Swift로 설정됩니다.

다음은 Xcode가 생성하는 코드입니다.

import Foundation
import CoreData
import 

extension Group {

    @nonobjc public class func fetchRequest() -> NSFetchRequest {
        return NSFetchRequest(entityName: "Group");
    }

    @NSManaged public var name: String?
    @NSManaged public var platform: NSNumber?
    @NSManaged public var profiles: NSOrderedSet?

}

// MARK: Generated accessors for profiles
extension Group {

    @objc(insertObject:inProfilesAtIndex:)
    @NSManaged public func insertIntoProfiles(_ value: SavedProfile, at idx: Int)

    @objc(removeObjectFromProfilesAtIndex:)
    @NSManaged public func removeFromProfiles(at idx: Int)

    @objc(insertProfiles:atIndexes:)
    @NSManaged public func insertIntoProfiles(_ values: [SavedProfile], at indexes: NSIndexSet)

    @objc(removeProfilesAtIndexes:)
    @NSManaged public func removeFromProfiles(at indexes: NSIndexSet)

    @objc(replaceObjectInProfilesAtIndex:withObject:)
    @NSManaged public func replaceProfiles(at idx: Int, with value: SavedProfile)

    @objc(replaceProfilesAtIndexes:withProfiles:)
    @NSManaged public func replaceProfiles(at indexes: NSIndexSet, with values: [SavedProfile])

    @objc(addProfilesObject:)
    @NSManaged public func addToProfiles(_ value: SavedProfile)

    @objc(removeProfilesObject:)
    @NSManaged public func removeFromProfiles(_ value: SavedProfile)

    @objc(addProfiles:)
    @NSManaged public func addToProfiles(_ values: NSOrderedSet)

    @objc(removeProfiles:)
    @NSManaged public func removeFromProfiles(_ values: NSOrderedSet)

}

편집 : 다음은 Xcode가 제공하는 특정 오류입니다.

1. Group+CoreDataProperties.swift:13:1: Expected identifier in import declaration (the empty import)
2. Group+CoreDataProperties.swift:13:11: 'Group' is ambiguous for type lookup in this context
3. Group+CoreDataProperties.swift:15:16: Cannot specialize non-generic type 'NSFetchRequest'
4. Group+CoreDataProperties.swift:26:11: 'Group' is ambiguous for type lookup in this context
4. Group+CoreDataProperties.swift:43:82: 'SavedProfile' is ambiguous for type lookup in this context

마침내 제 일을하게되었습니다. 내가 한 일은 다음과 같습니다. (항공편은 내 엔티티 중 하나입니다.)

다음과 같이 xcdatamodeld를 설정했습니다.

여기에 이미지 설명 입력

그리고 엔터티는

여기에 이미지 설명 입력

그런 다음 Editor-> Create NSManagedObject Subclass를 사용했습니다.

내 항공편 엔터티에 대한 두 개의 파일을 생성

Flights + CoreDataProperties.swift

Flights + CoreDataClass.swift

나는 Flights + CoreDataClass.swift의 이름을 Flights.swift로 변경했습니다.

Flights.swift는

import Foundation
import CoreData

@objc(Flights)
public class Flights: NSManagedObject {

}

Flights + CoreDataProperties.swift는

import Foundation
import CoreData


extension Flights {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
        return NSFetchRequest<Flights>(entityName: "Flights");
    }

    @NSManaged public var ...
}

제가 거기에있는 많은 제안을 시도 했음에도 불구하고 Codegen을 다른 방식으로 작동시킬 수 없었습니다.

또한 이것은 잠시 동안 내 머리를 긁적이며 도움으로 추가했습니다. FetchRequest의 새로운 Generics 버전을 잊지 마세요.

let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")

NSManagedObject 하위 클래스 파일을 생성 한 후 이러한 오류가 발생한 이유는 데이터 모델이 변경 될 때 선택한 Codegen 옵션과 관련이있을 수 있습니다.

나는 이것이 버그라고 생각하지 않습니다. 적어도 Xcode 8.1 (8B62)에는 없습니다.

비슷한 문제가 발생하여 Codegen 옵션을 "Manual / None"으로 변경하고 Module 옵션을 "Global Namespace"로 두어 문제를 해결했습니다. 그런 다음 NSManagedObject 하위 클래스 파일을 생성했습니다. 그러나 상황에 따라 NSManagedObject 하위 클래스를 생성하지 않아도 될 수도 있습니다.

아래는 Apple 문서, Apple 개발자 포럼 및 자체 프로젝트 테스트를 기반으로 한 엔티티 Codegen 옵션에 대한 자세한 내용입니다.

옵션 1 : "클래스 정의"

  • 이것을 "플러그 앤 플레이"옵션으로 생각하십시오.

  • 모델 편집기를 사용하여 Core Data에서 관리 할 엔터티 및 관련 속성을 만듭니다.

  • NSMangagedObject 하위 클래스 생성기를 사용하지 마십시오. 필요한 파일은 Xcode에 의해 자동으로 생성됩니다 (그러나 프로젝트 탐색기에 표시되지 않음).

  • NSManagedObject 파일을 생성하는 경우 Apple은 해당 파일의 헤더 주석에서 이러한 파일을 편집해서는 안된다고 알려줍니다. 이러한 파일을 편집해야하는 경우 다른 Codegen 옵션을 사용해야한다는 좋은 징조입니다.

  • 엔터티에 대한 기본 클래스 옵션을 그대로 둡니다 (모듈 = 글로벌 네임 스페이스 및 코드 생성 = 클래스 정의).

  • NSManagedObject의 메서드를 재정의해야하는 경우 클래스 옵션 아래의 이름을 사용하여 확장을 만들 수 있습니다.

    // Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }

옵션 2 : "수동 / 없음"

  • NSManagedObject 하위 클래스 파일을보고 편집 할 수 있다는 점을 제외하면 옵션 1과 유사합니다.

  • 모델 편집기를 사용하여 Core Data에서 관리 할 엔터티 및 관련 속성을 만듭니다.

  • NSManagedObject 하위 클래스 생성기를 사용하기 전에 엔터티에 대해 Codgen 옵션을 "Manual / None"으로 설정하십시오. 모듈 옵션은 글로벌 네임 스페이스 여야합니다.

  • 속성을 추가 / 제거 / 업데이트 한 후에는 두 가지 선택 사항이 있습니다. (1) 생성 된 NSManagedObject 파일을 수동으로 업데이트하거나 (2) NSManagedObject 하위 클래스 생성기를 다시 사용합니다 (Entity + CoreDataProperties.swift 파일 만 업데이트합니다). ).

  • 다시 말하지만 NSManagedObject에서 및 메서드를 재정의해야하는 경우 확장을 만들 수 있습니다. 확장은 Entity + CoreDataProperties.swift 파일이 아닌 Entity + CoreDataClass.swift 파일에 생성되어야합니다 (이 파일은 모델 편집기 변경으로 인해 업데이트 될 수 있음).

    // Optional extension in Entity+CoreDataClass.swift extension Entity { // Override NSManagedObject methods }

옵션 3 : "카테고리 / 확장"

  • Core Data에서 관리 할 필요가없는 사용자 지정 속성이있는 경우이 옵션을 사용합니다.

  • 모델 편집기를 사용하여 Core Data에서 관리 할 엔터티 및 관련 속성을 만듭니다.

  • 모듈 옵션이 현재 제품 모듈로 설정되어 있고 Codegen 옵션이 "범주 / 확장자"로 설정되어 있는지 확인하십시오.

  • 자체 관리 할 속성을 사용하여 고유 한 NSManagedObject 하위 클래스를 만듭니다.

  • NSMangagedObject 하위 클래스 생성기를 사용하지 마십시오. 필요한 파일은 Xcode에 의해 자동으로 생성됩니다 (그러나 프로젝트 탐색기에 표시되지 않음).

    // Subclass NSManagedObject in Entity.swift class Entity: NSManagedObject { // Self managed properties }

    // Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }


  1. 이 문제를 해결하려면 앱의 파생 데이터를 삭제하십시오.

  2. 그런 다음 모듈현재 제품 모듈로 변경하고 CodegenManual / None으로 변경하십시오 .

  3. 목록 항목

CodeGen : 수동 / 없음 모듈 : 현재 제품 모듈 설정 시도

같은 문제에 직면했을 때 잘 작동했습니다.

여기에 이미지 설명 입력


다음 단계를 시도 할 수 있습니다.

  1. Xocde 프로젝트 네비게이터에서 .xcdatamodeld 파일을 선택하십시오.
  2. 에서 데이터 MODUL 경위 , 확인 CODEGEN : 수동 / 없음
  3. 그런 다음 편집 -> NSManagedObject 하위 클래스 만들기
  4. 제품 청소 및 재건

작동합니까? 그렇지 않다면

모든 클래스의 이름이 Entities 와 같지 않은지 확인하십시오 . 이러한 클래스는 빌드 단계 -> 소스 컴파일 에서 찾을 수 있습니다 . 중복 된 경우 클래스 또는 엔티티 이름 변경

또는

이 명령을 프로젝트 폴더에서 실행하여 더 많은 오류 정보를 얻을 수 있습니다.

xcodebuild -verbose

이 문제가있을 때이 메시지를 받았습니다.

중복 기호 _OBJC_CLASS _ $ _ RandomList in :

xxxx / RandomList.o

xxxx / RandomList + CoreDataClass.o

RandomList.hRandomList + CoreDataClass.h 는 컴파일 할 때 동일한 기호 를가집니다.

왜 Xcode가 경고하지 않았지만 컴파일러는 오류를 던질 것이라고 생각합니다.

이것이 당신을 도울 수 있기를 바랍니다


레거시 앱이 있고 관리 객체 클래스를 수동으로 계속 추가하려는 경우

  1. 핵심 데이터 모델 코드 생성이 수동 / 없음으로 설정되어 있는지 확인하십시오.
  2. 핵심 데이터 모델 파일 선택
  3. 관리 개체 하위 클래스 만들기

편집자 스크린 샷


세 번째 import문이 비어 있으므로 삭제하십시오 .

참고 : 왜 이런 일이 발생하는지 모르겠지만 Xcode 8의 버그 인 것 같습니다. 삭제 만하면 정상적으로 작동합니다.


엑스 코드 8.2.1 (감사 : 나는 그것을 길을 만들어 다니엘 Chepenko를 )

여기에 이미지 설명 입력

그러나 Xcode 8.2.1 은 어리석은 . 생성 된 파일에 :

여기에 이미지 설명 입력

그냥 삭제 . 제대로 실행됩니다.


모델의 Person 엔터티를 Core Data 템플릿에 추가하는 데 문제가있었습니다. 그런 다음 NSManagedObject 하위 클래스를 생성했으며 컴파일되지 않아 링커 오류가 발생합니다. Codegen 옵션을 수동 / 없음으로 변경하여 작동하도록해야합니다 (그림의 오른쪽 아래 부분 참조).여기에 이미지 설명 입력


xcode가 핵심 데이터 범주 클래스에 대해 잘못된 구문을 생성하는 xcode 문제라고 생각합니다. nsmanageobjectsubclass하나의 엔터티를 만들고 있습니다.AgentDetails 다음 클래스를 만들고 있습니다

여기서 xcode는 AgentDetails+CoreDataClass.h에서 잘못된 코드 구조를 만듭니다 AgentDetails+CoreDataClass.m. 그것들은 다음과 같은 코드 구조를 가지고 있습니다.

여기에 이미지 설명 입력

여기에 이미지 설명 입력

따라서 AgentDetails.h동일한 인터페이스 갖는 것과 같은 중복 인터페이스 문제 가 있습니다.

이제이 문제를 해결하려면 코드를 변경해야합니다. AgentDetails+CoreDataClass.h

여기에 이미지 설명 입력

그리고 AgentDetails+CoreDataClass.m이렇게 :

여기에 이미지 설명 입력


Data Model Inspector에서 'Module'에서 Current Product Module을 선택하고 'Codegen'에서 Manual / None을 선택합니다. (이렇게하면 동일한 엔터티에서 속성을 수정할 때 하위 클래스 파일을 편집하고 CoreDataProperties.swift를 다시 생성 할 수 있습니다.)

여기에 이미지 설명 입력

그런 다음 Editor 메뉴에서 Create NSManagedObjectSubclass를 선택할 수 있습니다. Xcode는 YourEntity + CoreDataClass.swift 및 YourEntity + CoreDataProperties.swift에 대해 2 개의 파일을 생성합니다. 최신 Xcode (8.2.1)가없는 경우 Model Inspector에서 설정 한 선택적 / 비 옵션 속성이 올바르게 표시되지 않습니다. YourEntity + CoreDataProperties.swift 파일에서 편집 할 수 있습니다.


Xcode 8.1은 내부적으로 모델 클래스를 생성하는 것 같습니다. 생성 된 2 개의 클래스를 삭제하기 만하면 코드에서 엔티티를 계속 사용할 수 있습니다.

내가받은 오류 메시지는 다음과 같습니다.

<unknown>:0: error: filename "Recipe+CoreDataProperties.swift" used twice: '/Users/Rick/Desktop/Devslop/Rick Recipe/Recipe+CoreDataProperties.swift' and '/Users/Rick/Library/Developer/Xcode/DerivedData/Rick_Recipe-cctgjudvqobxlwetbcwmzrgxigwg/Build/Intermediates/Rick Recipe.build/Debug-iphonesimulator/Rick Recipe.build/DerivedSources/CoreDataGenerated/Rick_Recipe/Recipe+CoreDataProperties.swift'
<unknown>:0: note: filenames are used to distinguish private declarations with the same name
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

또한 NSManagedObject 하위 클래스를 직접 추가하는 경우 다음 단계를 따르는 것을 잊지 마십시오. '.xcdatamodeld'로 이동-> 엔터티 선택-> 데이터 모델 검사기 표시-> Codegen-> '수동 / 없음'선택

이것은 나를 위해 일했습니다.


어떤면에서 도움이되는 David Atkinson 의이 게시물을 찾았 습니다. David가 설명한대로 코드를 생성하면 일부 구문 오류가있는 코드를 얻고 오류를 수정하면 모든 것이 이전처럼 작동합니다. '.'로 시작하는 누락 된 파일이 없습니다. 더 이상.

수정해야 할 구문 오류는-불필요한 가져 오기-및 내 코드에서 공개되지 않는 일부 공용 속성입니다.


최신 Xcode 8.1 베타 (8T47) 빌드를 실행하고 있습니다.

오류 로그 (아래 참조)에 따라 자동 생성 된 파일의 두 복사본이 생성됩니다. 하나의 복사본은 Xcode 프로젝트 폴더 (Xcode의 왼쪽 도구 모음에있는 디렉터리에 표시됨)에 저장되고 두 번째 복사본은 프로젝트의 DerivedData 폴더에 생성됩니다.

/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataProperties.swift
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataClass.swift

Xcode 프로젝트 디렉토리에서 사본을 삭제하면 모든 문제가 해결되지만 더 이상 이러한 파일을 편집 할 수 없으므로 무의미합니다.

나는 이것이 해결책이라고 말하는 것이 아니라 프로젝트를 빌드하는 데 반 정도의 방법 일뿐입니다. 이 버그가 곧 해결되기를 바랍니다.

오류 기록


나를 위해 NSManagedObject수동으로 서브 클래 싱하여 CocoaTouch 클래스를 만들었습니다 . 모듈을 Current Product Module로 설정하고 Codegen을 Category / Extension으로 설정했는데 잘 작동합니다.


내 특별한 경우에는 이미 엔티티와 동일한 이름의 Model 클래스가있는 기존 프로젝트에 CoreData를 추가했습니다. 이전 모델 클래스를 삭제하면 유형이 새 CoreData Entity 클래스와 충돌하므로 문제가 해결되었습니다.


나는 문제를 해결하는 많은 답을 볼 수 있지만 여기서 실제로 일어나는 일의 진정한 이유가 부족하다는 점을 감안할 때 내 소금을 넣고 있습니다.

나는이 동일한 문제를 우연히 발견했고 빠른 조사를 통해 다음과 같은 사실을 발견 할 수있었습니다.

  • Xcode 7까지 Core Data 엔터티의 기본 동작은 개발자가 해당 NSManagedObject 하위 클래스의 변경 사항을 수동으로 만들고 유지해야한다는 것이 었습니다. ( "Create NSManagedObject subclass .."옵션을 선택하는 편집기 메뉴를 사용하여 수행 할 수 있습니다.)

  • Xcode 8부터 Apple은 NSManagedObject 하위 클래스를 관리하고 유지하기 위해 Codegen 이라는 데이터 모델 검사기에 새로운 설정을 포함 시켰습니다 . 이 설정의 기본값은 컴파일 타임에 정의 된 엔터티를 기반으로 NSManagedObject 하위 클래스를 생성하고 파생 데이터 폴더에 저장하도록 Xcode에 지시하는 "클래스 정의"입니다.

프로젝트 내에 NSManagedObject 하위 클래스와 Xcode가 자동으로 생성하는 하위 클래스가 있으면 "다중 명령이 생성됩니다 ..."컴파일 시간 오류가 발생하는 실제 원인이됩니다. 이제 중복 된 관리 개체 모델이 있습니다 !!!

해결책은 둘 중 하나를 사용하는 것입니다. 개인적으로 프로젝트 내에 관리되는 개체 모델이있는 것을 선호하므로이 "Codegen"설정을 "수동 / 없음"으로 변경했습니다. 모델에 논리를 추가하지 않는 경우 프로젝트의 관리 개체 모델을 제거하고 Xcode가 언급 된 설정에 대한 "클래스 정의"값을 기반으로 작업을 수행하도록 할 수 있습니다. 이것이이 문제를 처리하는 올바른 방법입니다.

여기에서이 모든 것을 자세히 설명하는 훌륭한 기사를 찾을 수 있습니다.

https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041


나는 아래 주어진 예처럼 그것을 해결했다.

CurrentcyPair.xcdatamodeld 만들기

선택 CurrentcyPair.xcdatamodeld을 하고 기본을 선택 -> 엔티티 (CurrencyPair)가, 같은 클래스의 이름을 변경 (.ManagedCurrencyPair)

엔티티를 선택하고 Inspector를 엽니 다. 데이터 모델에서 코드 생성을 수동 / 없음으로 설정

여기에 이미지 설명 입력

여기에 이미지 설명 입력


필요한 것은 Create NSManagedObject 서브 클래스를 실행하기 전에 CodeGen을 Category / Extension으로 설정하는 것입니다.


나는 Flight Entity가 있고 Data Model Inspector의 이러한 설정이 나를 위해 일했습니다.

  1. 이름을 아무것도 설정하지 마십시오 ( "NSManagedObject"의 일부 회색 텍스트가 표시됩니다). 기본값은 "Flights"로 작성됩니다.

  2. Nothing in the module."Global Namespace" greyed out is what you will see.

  3. Codegen to Manual/None.

  4. Then Goto Editor -> Create NSManagedObject Subclass to create the swift files

  5. Rename the Flights+CoreDataClass.swift to just Flights.swift

Here's the link to the Screenshot(For some reason imgur was rejecting it :( ) https://drive.google.com/file/d/0B8a3rG93GTRedkhvbWc5Ujl4Unc/view?usp=sharing


After I renamed the following:

From: YourEntity+CoreDataClass.swift To: YourEntity.swift

and

From: YourEntity+CoreDataProperties.swift To: YourEntityCoreDataProperties.swift

then it works. It looks like "+" is causing the problem.

참고URL : https://stackoverflow.com/questions/39657231/xcode-8-generates-broken-nsmanagedobject-subclasses-for-ios-10

반응형