5

I am a bit confused with new codegen functionality.

While developing, you could lookup all files that exist in projects. But not with codegen.

However, it worked well. But it doesn't fit new framework-oriented programming paradigm.

Scenario: I have completely separate framework Database. It could be embedded in application or could not. It depends. But it is completely separated.

Now I would like to use codegen feature. It describes automagic. It spawns in DerivedData all Core Data headers and it switch core data models development to categories-oriented paradigm ( hello, swift! )

Ok, everything works fine and compile until I want to expose all files with public access. It is obvious that all model files ( nearly all except, for example, hidden entities or abstract entities if necessary ) have public access level.

However, Xcode doesn't find template for codegen files.

It doesn't work, for example, in case of missing Map.modulemap file. Ok.

In this scenario it looks like:

framework module DBDatabaseBeaver {  
  umbrella header "DBDatabaseBeaver.h"  
  export *  
  module * { export * }  
}

But if I am right, this modulemap file doesn't lookup in correct Xcode CodeGen CoreData directory ( DerivedData ).

Also, it is hard to know which access level do these codegen headers have.

I have only one setting that could change something: Module setting in codegen.

But if I change it to something different from Global Namespace, it makes tricks with me and codegen file like:

// $(DatabaseModelName).h  
#import ".DBDatabaseEntity+CoreDataClass.h"  
#import ".DBDatabaseEntity2+CoreDataClass.h"  
...

Take a look at this file.

  1. It somehow put dots at the beginning of filename.

  2. It relies on $(DatabaseModelName), not on $(DatabaseModuleName).

  3. See 2. ModelName is xcodemodel filename. ModuleName is a framework target module name. It uses first, not second.

Could anybody explain a solution for scenario and add comments/(documentation links?) about all codegen features?

I thought that this scenario could be solved by fixing modulemap file and by adding correct Module name for entities in Model ( codegen setting ).

However, I don't know which paths should I add to modulemap to point to codegen files.

gaussblurinc
  • 3,476
  • 8
  • 31
  • 61

1 Answers1

2

You should be able to make the automatically generated header files be publicly accessible by copying them from the derived sources folder to the public headers folder of your framework.

You can do this by adding an extra Run Script step to the target of your framework. Copy the following script into the script editor and replace Your_Framework with the name of your frameworks executable.

#set -o xtrace
find "${DERIVED_SOURCES_DIR}/CoreDataGenerated/Your_Framework" -type f -name "*.h" -exec cp {} "${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}" \;

All this script does is list every header file in the derived sources directory (find $SOURCEPATH -type f -name "*.h") and then calls copy on each one in turn -exec cp {} $DESTPATH \;

If you have any problems uncommenting the first line (i.e. removing the #) and then looking at the build log should make it easier to diagnose.

tdbit
  • 733
  • 9
  • 14
  • Did you try your answer? I tried copying headers a month ago and stuck at unknown objc_classes. ( Object files .o :/ ). Another solution is copying autogenerated headers at the end of your development to your project folder. ( Before deploying data model / database framework into application ). – gaussblurinc Apr 12 '17 at 17:19
  • Yes, this is the approach I use in my framework & it works for me. If you have unknown objc_classes or object files then that's not a *header* (.h) problem that's an *implementation* (.m) problem. Core Data will generate Category files to add CoreData Properties on your object (e.g. MyObject+CoreDataProperties.h and .m) but you still need to write the object header and implementation (e.g. MyObject.h and .m). These files must be part of your build process: the .m file must be in the **Compile Sources** step must be in the **Headers** step of your build target. Maybe check that? – tdbit Apr 12 '17 at 21:54
  • You mean that without clean files ( 'MyObject.h, MyObject.m' ) Xcode can't compile correct object files despite of implementations of core data entities interfaces in +CoreDataClass categories? ( Generated headers and sources contains interfaces and implementations of entities if you choose Class Definition code generation option ). – gaussblurinc Apr 13 '17 at 08:16
  • **Correct!!** Because Core Data is only generating categories it still needs the original object interface & implementation to add the category to. For more information watch the 2016 [What's New in Core Data](https://developer.apple.com/videos/play/wwdc2016/242/) talk - particularly 28:30 onwards. – tdbit Apr 13 '17 at 17:10
  • well, it seems weird. Class Definition generates `@interface Entity @end` default (class) definition in +CoreDataClass category :( So, I still need empty `Entity.h` and `Entity.m` :( – gaussblurinc Apr 13 '17 at 18:41
  • Hmm, that sounds strange. What kind of CodeGen have you selected for each Core Data entity? It sounds like you've selected **Class Definition** when you probably want to select **Category/Extension**. With **Category/Extension** Core Data will only create 2 categories for each Entity specifically: `@interface Entity (CoreDataProperties)` and `@interface Entity (CoreDataGeneratedAccessors)`. It might also be worth just cleaning your build environment and restarting Xcode. – tdbit Apr 14 '17 at 00:18
  • 1
    The import statements in the headers need converted to framework format too, e.g. #import this requires a more complicated script. – malhal Sep 17 '17 at 20:42