Core Data classes not generated for test target - ios

I use Core Data's automatically generated classes. My project has 3 targets in addition to the test target. For each target, the Core Data classes are properly generated which I verified by inspecting the Derived Data folder. However, classes are not generated for the Test Target despite it being ticked in the Core Data model file. This causes an "undeclared identifier" and "Use of undeclared type" errors when I try to reference one of the Core Data classes in the test target. How can I fix this please?

You do not need extra classes generated for each test target - your import process should import everything, and no files should need to be added to other targets.
Declaring #testable import MyProject should take care of everything.
In Objective C
#import MyProject;

In Xcode 9.1 try adding your .xcdatamodel to a test target too. All auto-generated class will be imported too.

This was due to a bug currently in Xcode (8.3.1) where auto-generated NSManagedObject classes (codegen set to "Class Definition") cannot be found on the global path despite the project compiling successfully. The only way around it is to which to manual generation of the NSManagedObject classes by setting codegen for each entity to "Manual/None".

Select the test target, navigate to Build Settings and search for the setting "Header Search Paths"
Then add the following entry:
$CONFIGURATION_TEMP_DIR/{Project Target Name}.build/DerivedSources/CoreDataGenerated/{Project Name}
Replace the curly brackets with your main target name (not the test target), and your project name, respectively.
Xcode should now be able to find the generated source files when building the test target.

I noticed in Xcode 9.1 that the Data Model Inspector has a drop down for the Module to use. Selecting 'Current Product Module' with the Class Definition Codegen, and including the model in your Test target, compiles without errors. From what I can tell, the problem pieSquared noticed doesn't appear to be an issue, but my tests aren't exhaustive yet. It may be something to try, nonetheless.

I have wrestled with this issue ever since Xcode 9.4 or thereabouts. The error was always the same:
Testing cancelled because build failed.
'MyEntity+CoreDataProperties.h' file not found
I've filed a bug report (45802900), but I got Apple Support involved as well and together we finally found the solution. . Actually, there are two solutions.
Solution 1: Set the Header Search Paths build setting of the Test Target
The most elegant solution, to my mind, is to set the Header Search Paths build setting of the test target. Ziqiao Chen of Technical Support figured out the correct path, while I provided the build variables. For projects with only one data model, the name of which is the same as the project (which is the default), the Header Search Path may be:
$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources/CoreDataGenerated/$(PROJECT_NAME)
Make sure the path is set to 'non-recursive'.
For projects with multiple data models, a non-recursive path should be added to Header Search Paths for each data model:
$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources/CoreDataGenerated/dataModel1
$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources/CoreDataGenerated/data_model_B
Solution 2: Add the data model to the Test Target
Another solution, which Ziqiao Chen came up with and which I've also read on here on SO, is to add the data model to the test target. In my experience, however, this only works with a single data model. As Ziqiao Chen pointed out, Xcode should generated the exact same files for the test target as for the main target.
My experience is that in more complicated projects (multiple targets, multiple data models) all kind of linker errors may occur, from complaints about duplicates to the "testing cancelled" error described above. For simple projects, however, it's a quick and simple solution.

For Xcode 11.5:
if Codegen property is class Definition, and if you are not getting a suggestion for the entity you created in xcdatamodel. Try to quit Xcode and reopen your project again. It works for me. This answer is only if you are not getting suggestion but if your file doesn't get generated try any above answer.

Related

Legacy ObjC/Swift codebase crashes tests in `swift_checkMetadataState`: how to disentangle app/test targets?

I've got a mixed ObjC/Swift codebase with a very mixed-up structure, and the tests no longer run under Xcode 10.2 (details below). I'm trying to make the minimum structural changes to get tests back, so that I have a safety net for the refactoring that will come next. After taking what seems to me to be the obvious first step, the tests fail to build (details again below).
I'm interested in any of
solutions for the original problem (to get tests running again in the messy setup)
solutions for the problem after refactoring (to get refactored tests building in the somewhat tidier setup)
suggestions for build settings to verify or include in the description here, to get clearer on what's going wrong
I'm not interested in advice about how to structure a fresh project or create new targets with more sensible configurations: extracting code from these targets is also non-trivial, so I really need test coverage back before I start any refactoring.
Original situation (very messy)
project myCompany
app target app which builds module MyCompany
contains both Swift and ObjC code, with dependencies both ways
Defines Module = Yes, Product Module Name = MyCompany
test target myCompanyTests
Defines Module = No, Product Module Name = MyCompany
also contains both Swift and ObjC code
CocoaPods for external dependencies, also a bunch of internal Swift modules with dependencies managed by hand
Test files are included only in the myCompanyTests target, but many code files are included in both app and myCompanyTests targets. I think this and the two targets defining the same module name was probably in order to avoid having to import the app target into tests, because of problems with Swift/ObjC interop (see the next section). Building tests produces warnings about classes implemented in two places:
objc[9724]: Class _TtC12MyCompany12DiaryFetcher is implemented in both
/Users/tikitu/Library/Developer/CoreSimulator/Devices/556CAC28-B90B-4B6B-A87C-1A1450795051/data/Containers/Bundle/Application/495F33C2-F7FC-4AE6-B3FE-6908D6361B55/mycompany-develop.app/mycompany-develop (0x10d724060)
and
/Users/tikitu/Library/Developer/Xcode/DerivedData/mycompany-bifciplpbqaeqqdrmhivpjgnojri/Build/Products/Debug-iphonesimulator/mycompany-develop.app/PlugIns/myCompanyTests.xctest/myCompanyTests (0x13566dc38).
One of the two will be used. Which one is undefined.
As of Xcode 10.2, myCompanyTests builds successfully but running the tests fails with an EXC_BAD_ACCESS in swift_checkMetadataState somewhere inside the UIApplicationMain call. My guess is that this is related to the module-name/files-in-both-targets shenanigans.
First attempt at "fix the obvious mistakes"
As a first attempt to tidy things up somewhat I've done the following:
Remove all non-test files from the myCompanyTests target
Rename myCompanyTests Product Module Name to MyCompanyTests
Add #testable import MyCompany in lots of swift tests
Then I start running into Swift/ObjC interop problems, because I need to call Swift code in the app target from ObjC code in the test target. Things I've tried:
#import "MyCompany-Swift.h" in an objc .m test file
'MyCompany-Swift.h' file not found
#import <MyCompany-Swift.h> in an objc .m test file
'MyCompany-Swift.h' file not found
#import <MyCompany/MyCompany-Swift.h> in an objc .m test file (yes you can see I don't actually understand this mechanism)
'MyCompany/MyCompany-Swift.h' file not found
#import "MyCompanyTests-Swift.h" in all objc .m test files that need access to the app target
the generated file MyCompanyTests-Swift.h includes a line #import MyCompany; which looks very promising!
but that line fails with the error Module 'MyCompany' not found
Especially this last one looks suspicious to me, as I would expect the Xcode generated file should "just work". I guess I've overridden some user setting somewhere that's getting in the way: I'd be delighted with any suggestions for places to check.
I won't accept this (yet) as it's incomplete information, but I believe at least that I know why the fixed-up version is failing: the location of MyCompany-Swift.h isn't in the unit-test target's header search paths, because it's the app target. Reference e.g. https://github.com/jeremy-w/MixedLanguageTesting (which suggests adding an ad-hoc entry to the header search paths).
I believe the issue to be that only a framework target auto-creates the swift-to-objc header file Module-Swift.h: neither the app target nor a test target appear to do so.
I successfully resolved these issues by creating two new framework targets
* MyCompanyStuffThatUsedToBeInApp (containing everything that used to be in the app target except main.h), which does bidirectional swift/objc interop and
* MyCompanyTesting (a framework target imported by the tests, which likewise does bidirectional swift/objc interop for test-only code).
There may still be simpler ways to tidy this up, but this one at least is proven to work.

Build error Xcode 10 - Multiple commands produce

I just upgraded to Xcode 10, and I suddenly face this error when I try to build, any ideas how to fix it? I tried cleaning derived data, but without any luck.
If you use CocoaPods, click Xcode menu file -> Workspace Settings , And click Build system choice Legacy Build System
If you not use CocoaPods, same of top , select Project Settings
If your app is generating the error related to the multiple .app files just like mentioned above in question then removing the .plist files from "Copy bundle Resources" WILL NOT WORK.
If the error is related to .app file then follow the following steps.
Select the Target.
Go to Build Phases tab.
Remove the items listed in Output Files
Compile the code if it compiles successfully then not follow the next steps.
If code does not compile successfully and Xcode may give you an error related to "Library not found". Then add the missing library in General Tab in Linked Frameworks and Libraries that Xcode mentioned in the error.
Keep adding these libraries (that Xcode ask through compile errors) in Linked Frameworks and Libraries until the code compiles successfully.
Hope this helps.
You can try to change the build system to Legacy,
File > Workspace Settings > Build System > Legacy Build System.
I also faced this issue in xcode 10 but it was because of adding the same framework in main project + other extensions (watchkit or siri extension etc).
I added ObjectMapper in podfile for my main project + for my extensions. When I compiled it gave me an error that multiple command produce and also shows me which framework is causing this issue. Now its working fine for me as I've removed it from my extensions I wasn't using it in my extensions.
Don't know about your issue may be you can check your podfile.
If this is CoreData related. The issue is that you are trying to generate the NSManagedObject subclass but you need to set the 'CodeGen' option to Manual/None. This option is defaulted to Class definition and this would regenerate the code thus creating this issue.
i encountered this issue as well while working with CoreData.
in my .xcdatamodeld file, it came down to the fact that, during the creation of my various Entities, i had copy and pasted one multiple times (thinking i was saving time because various properties were similar enough that i thought this was a good idea).
the resulting Build error Xcode 10 - 'Multiple commands produce' occurred because i forgot to check and make sure the new Entities were set to their own unique corresponding class to match the new Entity in the Data Model Inspector pane.
unfortunately, it took me two days to figure out the original Entity's Class Name was still in place.
so lesson: careful when you copy/paste/duplicate Entities in CoreData.
(... i guess :0} )
some time saver. oops! hope this helps someone.
I had this same issue with Core Data entity class. I had forgotten to select Codegen Manual / None because I do not allow mine to be autogenerated. So I had a class in place and also it was trying to generate one.

Adding Swift files to test target not fixing unit tests

I have looked at a lot of blogs and tried many things to get my Swift unit tests to work in Xcode 6.0.1 (or 6.1 for that matter). I'm trying to access classes in my app's target so I wrote this line:
var vc: LoginViewController!
Of course, I get the "Use of undeclared type 'LoginViewController'" error.
I then try to add LoginViewController to my test target, but then I get "use of unresolved identifier" errors on other classes in my project. So I try to add those classes to my test target, but I end up with a seemingly endless source of errors like the screenshot below:
Declaring all my classes as public, causes other errors and seems like bad practice. Is there anyway to include unit tests in a Swift project that relies on many frameworks and classes? I simply want to start with something almost exactly like the code in this article.
After much headache and putting this on the back burner, I found that the main problem was when adding files to the test target membership, the Objective-C classes would still complain. I figured it was an old compatibility issue with the new way Swift does unit tests, but the solution was my test target didn't know there was a bridging header. Thus, I added a reference to it in my test target's build settings, like so:
It seems simple and obvious now, but the errors were unhelpful. No other solutions I saw for Swift unit tests suggested this could be an issue, but now I know.
Tl;dr
For unit tests to work in Swift, the test target must know everything the app target knows, so add a reference to your bridging header in your test target too (if applicable).
If you're using Xcode 7, there's now a much better way of dealing with this using #testable import {ModuleName}.
Just make sure that the module you want to test has the build setting Enable Testability set to YES.
I am using Xcode 6.1
You need to add your swift file to the target membership of the test target

Core data: Unable to load class named "CDAccount"

I've recently downloaded iOS 8 to make sure that my existing app works properly with it, but I'm getting a warning in the debugger on launch:
"CoreData: warning: Unable to load class named 'CDAccount' for entity 'CDAccount'.
Class not found, using default NSManagedObject instead."
After some research, it seems like people have had similar issues when using Core Data in Swift, but all my code is in Objective-C (and the data model hasn't changed for at least 6 months).
Any advice is much appreciated, I'm really nervous that my app isn't going to function properly once people start upgrading to iOS 8!
I had the exact same problem in Objective-C and Xcode 6. For some reason, Xcode had removed my 'CustomNSManagedObject'.m classes from my Compile Sources.
Go to your project target -> Build Phases -> Compile Sources and use the + button to add CDAccount.m
If you are using Mogenerator to create a _CDAccount.m file, add that to your Compile Sources as well.
Remove the "dot" in Configurations "Default" on .xcdatamodeld:
to:
Rebuild the application.
My issue was also similar, but the reason was that module of entity was not set.
It seems to be an Xcode bug/issue. I'm using Xcode 6.3.1
click on your core data entity (xxx.xcdatamodeld), then select the entity, and in the attributes inspector you'll see that the entity's class name is set to:
PRODUCT_MODULE_NAME.xxx, where 'xxx' is your entity's name.
solution : You have to replace PRODUCT_MODULE_NAME with your app's name.
If in doubt about your app's name, check under 'build settings', filter on 'product_module_name', and you'll find your app name under 'packaging'
in some cases (my case) the data model file (swift or objective-c) is also removed by Xcode from the project - it's still on in disk though, but you need to add it again. So in this case take the 'CDAccount.m' file & drop it in your project again (or use another of the several ways to do this)
My issue was similar, but the listed solutions didn't work because my CD Classes were stored in a framework. The solution was to change the Class Name Representation to "frameworkName.className". However, the xcdatamodeld didn't allow me to change it to that, so I had to "Show Contents" on the file, open the "contents" file in XCode, and make the changes myself.

Link framework against App and Test Target

I have a custom Framework I use within my normal App target as well as the corresponding UnitTest target. Turns out that confuses the runtime in such way that it is unable to choose the correct implementation since it has multiple choices:
objc[35580]: Class AClass is implemented in both ../MyApp.app/MyApp and ../MyApp.app/MyAppTests. One of the two will be used. Which one is undefined.
That of course leads to weird behavior if you try to check an object's class hierarchy or do any other class related checks.
So it boils down to the following two questions:
I don't see similar logs for e.g. UIKit components, but this framework is also linked to both targets. Have I incorrectly compiled the framework?
Is it just a trivial configuration issue I missed?
PS: I already checked similar posts like 1 or 2, but although everything is configured as described, the problem remains.
You have added the dependency framework to the Tests target. This is flawed thinking. Since your primary application ALSO exports the SAME framework you will receive warnings about duplicated symbols for any classes found in the framework.
By removing your framework from the test target you can resolve the warnings. Remember, you're not losing any functionality by not linking against the same framework in the test target. Trust me, your code is still there.
I ran into a similar problem here: Xcode5: creating new testing target
The key is to create a new unit testing bundle, point it to your original target, and then don't do anything else! If you start including frameworks and source files into the test target, it'll generate these linking errors. The test target is supposed to "inject" the test classes into the actual target, not create a new separate target on it's own. So you just need to import the header files in your test class, and write your test cases.
I think the bundle should only "read" the framework's header files but not build the sources and leave that task to the App (remove the Framework .m files from the UnitTest target).
Right now the App and the UnitTest are both building the Framework, thus the duplicated classes.

Resources