CLS_LOG macro does not work in one class - objective-c

I'm using the Crashlytics CLS_LOG macro throughout my project. It's working everywhere except in one class, where I get Implicit declaration of function 'CLS_LOG' is invalid in C99. If I comment out the calls in that one class then the entire project compiles fine.
I'm including Crashlytics in my prefix.pch like this:
#ifdef __OBJC__
// Other imports
#import "Crashlytics/Crashlytics.h"
// Other imports
#endif
I've trying clearing pre-compiled headers, reinstalling the Crashlytics framework, and more - nothing has helped.
Any idea what could be breaking the macro in a single class?

I figured it out.
The problem was that I had added this class to the compiled sources for a new target (a widget), but I hadn't added the Crashlytics framework to that target.
I also followed the instructions from this answer to create a prefix.pch for the widget target, added Crashlytics to that, and now everything is compiling as expected.

Related

Problem with using Swift in Objective-C target

I have an old Objective-C project, which has multiple targets, and some of the targets share a framework (let's call it CJDataKit) that's also written in Objective-C. I'm trying to add some Swift code to my project, at least to the main app target, and have some limited implementation of it working, but I'm running into some issues whenever the Swift code needs to use or import the CJDataKit framework, or any header file that itself imports the CJDataKit framework.
What's Working
I wrote a basic UIView subclass in Swift (which didn't need any other code from my app), and I can use this in my Objective-C target, using #objc keyword and by importing "MyApp-Swift.h" in my Objective-C code.
I then wrote a new UIViewController subclass in Swift, and used a couple of simple Objective-C objects from both CJDataKit framework and non-framework classes. I did this by creating a bridging header file, and added the Objective-C headers there.
So far so good, and everything compiles fine.
What's Not Working
The problem happens if I try to import into Swift other Objective-C
files that might be importing the CJDataKit framework inside it. For
e.g. I wanted to write a Swift extension of an existing
UIViewController subclass (call is PageAViewController). This
subclass has imported multiple other header files. If I add it to the
bridging header file, I start getting build errors:
Include of non-modular header inside framework module 'CJDataKit':
'.../CJDataKit/Person.h'
Commenting out the #import CJDataKit makes it work for this particular file, but it still gets compile errors from a different header file (that was imported by PageAViewController). It'll only work if all the files imported don't have a #import CJDataKit, which is difficult and cumbersome. BTW, these files all belong to the app target, not the framework. So something about Swift doesn't like interacting with the CJDataKit framework directly, even though it works fine if it's built independently in the same app target along with the CJDataKit framework.
I've also tried importing the CJDataKit.h header file into the Swift
bridging header file, figuring this way I don't have to individually
import each file from the framework, but that doesn't work either.
That results in a different error:
Could not build module 'CJDataKit.h'
I've tried using #import <CJDataKit/CJDataKit.h> as well but same result.
From my settings:
- "Allow Non-modular Includes In Framework Modules" is Yes on the target, and framework. It is No at the project-level.
- "Defines Module" is also set to Yes, on both the app target and framework, and No at project-level.
Would love some help in getting this setup correctly. I've been searching for a solution, but haven't really found anything.

Obj-C - Import (Swift Compiler Recognise?)

I'm migrating from Obj-C to Swift and have just migrated from PSGameScene.h and PSGameScene.m to GameScene.swift.
When I build the app, I get an error stating that PSGameScene isn't a recognised symbol.
GameScene.swift is added to the "compile list", I've tried adding GameSCene-swift.h to the source, but it doesn't see it..
Where am I going wrong?
I can confirm that both the bridging header and the .swift file area added to the compile scheme.
In the .h and .m files, it does recognise the class, and when I imoprt trying to use (GameScene-swift.s it complains that the file isn't there...
I'm. little lost...
Any posters would be helpful...
Cheers,
A
Sounds like you want to use your new Swift class in Objective-C, check out this answer about how to mix and match the two in the same project.
The gist is: import the generated -Swift.h header in your .m file that you want to use the Swift class on (you can't import it in a .h, check the above answer for more):
// SomeImplementationFile.m
#import "ProjectName-Swift.h"
You can double check the name of your -Swift.h header in Build Settings / Objective-C Generated Interface Header Name.
The issue turned out to be related to the build settings. As defines module was set to NO, it didn't like the import. When the DEFINES_MODULE (defines module) setting was set to YES it all clicked into place.
This probably happened as it related to an old project which spans back to Xcode 4 days. It appears that the newer releases of Xcode don't take into account some settings.
Thanks for the answers..

How to avoid "Redefinition" and "Duplicate Protocol" definition errors in Bridging Header

I want to use a objc library and a objc class in a swift class. So I place the following in the Bridging-Header.h:
#import <FooLibrary/FooLibrary.h>
#import "FooClass.h"
The problem is that the FooClass.h has
#import "FooLibrary.h".
So when I compile I get hundreds of errors like:"Redefinition of enumerator" and "Property has previous definition" and "Duplicate protocol definition" and "Typedef redefinition"
How do I avoid this? It seems like this is just a stupid mental block I am having but I can't get past it so here I am asking.
PartiallyFinite suggested I watch for #include
I did a project wide search and I and not using it at all. There are a few in the library. I chose one of the errors. The file the decoration is in is never included in any file with #include
Sounds like something is causing the preprocessor to believe that the FooLibrary.h header imported indirectly by the second #import is somehow not the same file as the one you include just above it. My best guess as to what is that your first, framework-style import is referencing header files that are copied to a build location during build, while your second, direct file import is referencing the header file as it is in your project directory, meaning that the preprocessor sees them as two completely separate files, resulting in it being imported twice.
Proposed ways to fix:
If you can include FooClass.h using the framework-style import syntax (like #import <FooLibrary/FooClass.h>), that will probably fix the problem.
If you're absolutely sure that FooClass.h will always include FooLibrary.h, you can probably just omit the first import entirely, as everything will get imported indirectly via the second one.
Otherwise, you can try some nice, old-fashioned include guards (assuming you have write access to the library headers):
// FooLibrary.h
#pragma once // Maybe even throw in one of these for good measure;
// since we're dealing with an obscure-sounding bug,
// may as well try to fix it in all of the possible ways
#ifndef FOOLIBRARY_IMPORTED
#define FOOLIBRARY_IMPORTED
... // actual file contents
#endif
This will define a preprocessor macro the first time the file is imported, so the second time the preprocessor tries to import the file, the already defined macro will prevent the contents from being imported a second time. I fail to understand why the #import isn't doing this in your case, as that's literally its only purpose and advantage over #include, but if this fixes it, ¯\_(ツ)_/¯
This can also be caused by cocoapods - try upgrading or downgrading to a different version and re-running pod install
For me it was happening when I upgraded Xcode. All I did was to Clean Build folder and run again and it worked!

Failed to import bridging header

I've read a lot of questions and answers that deal with a similar issue, but I have yet to find a solution. If anyone could shed some light, that would be wonderful.
I created a Swift project and now I want to combine it with some Objective-C. My "failed to import bridging header" only occurs when I attempt to #import my Chartboost.h file. So, as long as I don't have anything in my bridging header file, Xcode finds it and gives me no issue. But once I add this:
#import <Chartboost/Chartboost.h>
I get the error along with 38 other errors saying "Swift Compiler Error - Function definition not allowed here".
I've correctly imported my framework. And my framework search path is correct. And it's only when I import the Chartboost framework. UIKit and Foundation work fine.
Here is what I did leading up to the issue....First, I created a new Obj-C file and then clicked "Yes when Xcode gave me a pop-up asking if it could configure a bridging header. This created "FunFacts-Bridging-Header.h"
Then I made sure Objective-C Bridging Header path was correct under Swift Compiler - Code Generation.
I even put in a very specific path /Users/me/Desktop/FunFacts/FunFacts-Bridging-Header.h
and it still says "Failed to import".
I've also set Defines Module to "Yes" (because I heard that may help). And my product module name is FunFacts.
Why is FunFacts-Bridging-Header.h failing to import when I try to add #import ?
I answered this in another post: Chartboost integration issues with XCode 6.1
EXPLANATION:
It seems like some pods and libraries don't bother importing the basic frameworks as they expect your code to already have them. This doesn't work with Swift as the way to import frameworks changed.
All you need to do is to add the frameworks needed in your bridging header file.
ANSWER:
It depends on what errors the compiler throws.
If it complains about NSObject, NSString, etc... you need to add
#import <Foundation/Foundation.h> in the top of your bridging header file.
If it complains about UIView, UIButton, etc... you need to add #import <UIKit/UIKit.h> in the top of your bridging header file.
I figured out 2 solutions!
1) This isn't the prettiest way to do it, but I copy and pasted all my code from my Chartboost.h file into my Bridging-Header.h file instead of importing . This worked. But I knew there was a better way, so I kept hunting...
2) The correct solution, I believe, is what I did next. My project's (not target) Framework Search Paths was empty. So, I went ahead and added the path to the Chartboost SDK like so: /Users/me/Desktop/Apps/SDKs/Chartboost
Now it builds and runs with no problem and I didn't have to copy and paste everything into the bridging header. All that was needed was
#import <Chartboost/Chartboost.h>
If anyone is having a similar issue, just read what I did in my question, and then follow it up with this answer.
Had a nearly identical issue and found a solution that worked for me.
My problem was that the Bridging Header was not in ALL my targets.
It was in my project but not my UnitTest target. So I added it to by my UITest and UnitTest and it started working without issue.
The problem like your's puzzled me.
But I found a solution.
#import <Foundation/Foundation.h>
You should put this code (↑) before your code.
This is just my solution (↓).
#import <Foundation/Foundation.h>
#import <Chartboost/Chartboost.h>
Good luck!
This is how I solved it (and works!):
Create yourProjectName-Bridging-Header.h file at the root of your project
Include in that file the .h of the classes you want to expose and use into your swift project
Go to yourProject->Build Settings->Search Paths, and set to Yes the "Always Search User Paths" key.
Set "User Header Search Paths" to your project root path.
That's it.
Apparently, Xcode miss out on third party folders when they are copied into your project
I am on Xcode 6.3 , swift 1.2.
The answer is really very simple.
Make sure you are adding your bridging header path in SWIFT_OBJC_BRIDGING_HEADER under the target section instead of the project section.
If you use CocoaPods this could save your time.
1) The first what you need to do is to check your Podfile it will be like:
target 'YourProjTests' do
inherit! :search_paths
end
target 'YourProjUITests' do
inherit! :search_paths
end
2) Open baseproj configuration and set for test targets correct Pods-Proj.debug , see attached image:
If you have these lines in you bridging header:
#ifndef Bridging_Header_h
#define Bridging_Header_h
#endif /* Bridging_Header_h */
Just delete them, it will solve the problems of Foundation and UIKit.
One case is that if import <Chartboost+Extention/Chartboost+Extention.h> ,
The right way is to import <Chartboost**_**Extention/Chartboost+Extention.h> ,
Just because Pod build will change the framework name of Chartboost+Extention into Chartboost_Extention

Swift to Objective-C header not created in Xcode 6

I have recently been working to add Swift to an existing project, to get to try it out in a real-world fashion.
Upon adding a Swift source file to the project, I have no problems about getting the "Bridging Header", that is, Objective-C to Swift.
But the *-Swift.h header file that is supposed to expose Swift classes either marked #objc or subclasses of ObjC classes, is nowhere to be found :-(
I don't see any specific instructions on how to accomplish the usage of my new subclass, written in Swift, in my main app code (which is still Objective-C).
The app that I am lead developer of has a fairly large codebase (70.000 lines), so transitioning it in one go is out of the question.
Now it works.
Project must have a Product Module Name that does not include spaces.
Defines Module must be set to Yes in Build Settings, under Packaging.
Finally works. Thanks to everyone for the help :-)
I had a similar problem and found that you can only add
#import "ProductModuleName-Swift.h"
to obj-c .m files, not .h files for the umbrella header to be found
I found that I had to fix all build errors before it would generate the file.
The problem for me was that it was a chicken/egg problem, in that I didn't see any build errors until I'd actually commented out the #import statement:
//#import "ProductModuleName-Swift.h"
which revealed a bunch of other errors in my Swift code.
Once I fixed these new errors and got the source building successfully, I uncommented out the #import and bingo! The header was created and importing correctly :)
If you're like me you've probably got the header name wrong. After bashing my head for a while I looked for the file in DerivedData and sure enough it's there. On my setup (using the standard derived data folder, I believe):
cd ~/Library/Developer/Xcode/DerivedData
find * -iname '*Swift.h'
Will find it. If nothing in that folder matches then Xcode is not generating it.
I'm using Xcode Version 6.2 (6C86e)
If your project module name has spaces in it, you must replace the spaces with an underscore.
For instance, if your project name is "My Project", you would use:
#import "My_Project-Swift.h"
* The only important thing is: *
to use the defined "Product Module Name" in the target, followed by -Swift.h
#import <Product Module Name>-Swift.h
// in each ObjectiveC .m file having to use swift classes
// no matter in which swift files these classes sit.
No matter if "Defines Module" param is set to Yes or No or if "Product Module Name" Project is not set.
Reminder: Swift classes must deriving from NSObject or been tagged with #objc attribute in order to be exposed to ObjectiveC / Foundation || Cocoa ...
I wanted to add one more reason you might find an issue with this - I was creating a framework that mixed Swift and Objective-C code. I was not able to import the Swift classes outside the framework - I checked for the -Swift.h file and it was being generated but was empty.
The problem turned out to be very, very simple - I had not declared any of my Swift classes public! As soon as I added the public keyword to the classes, I was able to use them from classes inside and outside the framework.
Also of note, inside the framework (inside .m files only as another answer mentions) I had to import the -Swift.h file as:
#import <FrameworkName/FrameworkName-Swift.h>
I had the same problem. Seems like you have to adjust the settings (Defines Module and Product Module Name) before you add your first Swift file.
If you do it afterwards the "*-Swift.h" file will not be generated for this project even if you add further Swift files or delete the Swift file and create a new one.
Allow me to share my experiences trying to use Swift in an old objc project. I did not have to set Defines module to YES.
In my case I needed to manually make sure there was an objc Bridging Header. Only the generated interface header name was present in my build settings.
This lead to a MyApp-Swift.h file to being generated, but without any traces of my Swift classes.
The Apple documentation says that you will be prompted to create a bridging header when adding your first swift file. Well, I wasn't. I manually added a MyApp-Bridging-header.h file and pointed to it in the "Objective-C Bridging Header" field. That made my MyApp-Swift.h file become populated with my Swift classes.
Docs: Importing Swift into Objective-C
Here is another variation of the moduleName-Swift.h not being generated.
I decided to include IOS Charts in my project but did not want to mingle the sources in the same directory, so I placed the Charts Project folder next to my code's project folder. I dragged the Charts project into my Project's Navigator Bar and included the framework in the my project target's Embedded Binaries list in the General project settings and set the Embedded Content Contains Swift Code switch to yes in my project's Build Settings tab in the Build Options section.
My project's moduleName-Swift.h file would never generate no matter what other switches or settings suggested here. Finally, using Lou Z's method of seeking out the -Swift.h files, I saw that a Charts-Swift.h file was being generated deep in my project's xcode Build directory in Charts.framework/Headers/
The solution to using Daniel Gindi's ios-charts Swift package without including the code in my project's source directory was to add:
#import "Charts/Charts-Swift.h"
To the modules charting my project's data.
The file name is always preceded by your Target name. It is referred as Product name but practically it is the target name.
So if you want it to build for a new target be ready to expect that_target-Swift.h file.
One way to handle this is
Add a preprocessor for each of your target that is the name of your target itself (without spaces). Ex. MY_TARGET=1. Add this in Project settings->Build Settings->Preprocessor Macros for each of your targets.
If you are using a PCH file,
Add these lines in the PCH file
#if MY_TARGET==1
#include "My_Target-Swift.h"
#elif THAT_TARGET==1
#include "That_Target-Swift.h"
#endif
Advantage of using PCH file is that you don't have to include the headers everywhere.
If you are not using a PCH file, just add these same lines in a single header and include that header wherever you need to use the swift classes.
This should work just fine.
If Xcode is actually generating your -Swift.h header (deep inside DerivedData) but it doesn't refer to your Swift classes, make sure you also have a bridging header defined. The way I read the docs implied I only needed that for calling Objective-C from Swift, but it seems to be necessary for calling Swift from Objective-C too.
See my answer: https://stackoverflow.com/a/27972946/337392
EDIT: It is because of public vs. internal access modifiers, as I eventually found explained in the Apple docs:-
By default, the generated header contains interfaces for Swift
declarations marked with the public modifier. It also contains those
marked with the internal modifier if your app target has an
Objective-C bridging header.
Seconding what a lot of people have here, but adding a pertinent screen shot. Swift and Obj-C code can certainly live together. It's not an all or none game.
To access Swift files in your Objective-C, all you need to do is add this call to your Obj-C file (in the .m / implementation file):
#import "{product_module_name}-Swift.h"
(Where {product_module_name} represents the product module name of your project). Rather than try to guess your product module name or figure out corner cases with spaces and special characters, just go to the build settings tab in the project and type in "product module name" - the inspector will reveal yours to you. Mine was something I did not expect it to be. Check out this screen shot if you're confused.
And to get Obj-c code working in Swift, you just need to add a bridging header file and import the relevant Obj-C headers there.
This answer addresses the use-case where you may already have some Objective-C code that calls Swift classes and then you start receiving this error.
How To Fix Issue
The following steps ultimately resolved all of the issues for me. I read above someone mentioning the "chicken and the egg" and it is exactly that concept which led me to this procedure. This explicit process shows that one has to remove any Objective-C code referencing Swift classes until after the header is generated.
Comment out the #import "ProductModuleName-Swift.h" statement in
your Objective-C implementation file
Comment out any references in the Objective-C implementation file to
Swift Classes
Clean & Build
Resolve all errors/warnings
Remove the comment on the #import "ProductModuleName-Swift.h" statement
Clean & build (successfully or fix any remaining errors, verify that you are not referencing any Swift classes in Objective-C at this point. If so temporarily comment these out)
Verify that "ProductModuleName-Swift.h" is generated by Cmd-Clicking
on the class name of the #import "ProductModuleName-Swift.h" statement
Remove the comment on the code referencing Swift classes in the Objective-C implementation file.
Clean & Build as normal (the "ProductModuleName-Swift.h" should be
generated and your Objective-C code referencing Swift Classes can be
used as normal)
Nota Bene: The answers about changing spaces to underscores and the Defines Module to YES as given above still applies when performing this process, as do the rules specified in the Apple Documentation.
Bridging Header Path
In one error, the file ProductModuleName-Bridging-Header.h was not being found during the build process. This fact generated an error
< unknown>:0: error: bridging header
'/Users/Shared/Working/abc/abc-Bridging-Header.h' does not exist
Closer inspection of the error indicated that the file would never exist at the location described because it was actually located at (a wrong path)
'/Users/Shared/Working/abc/abc/abc-Bridging-Header.h'. a quick search of the target/projects build settings to make the correction manually and the abc-Swift.h file was again auto generated.
Ok, here are all the things you really need!
1.Remove all the swift files you have added, and compile the code, without any errors.
----------
----------
2.Go to the "Projects" build settings, and set the product module name.
Project must have a Product Module Name that does not include spaces.
----------
----------
3.Defines Module must be set to Yes in Build Settings, under Packaging, in your project, and not target!
----------
----------
4.Now create a swift file or a view controller, in file-> newFile->
----------
----------
It will ask to create a bridging-header, allow it to make one.
If you have declined it once, you will have to manually add a -Bridging-Header.h
5.Add #objc in the controller, to tell the compiler that there is some swift file, which needs to be exposed to ObjectiveC
----------
----------
6.Build the project and import #import "-Swift.h" in any of the objectiveC controller, and it will work! You can Command-click on it to see the actual file!
----------
----------
Hope this helps!
The most important thing is that This file is invisible!!! At least it is in Xcode6 beta5. There will be no such file named "YourModule-Swift.h" in your workspace. Just make sure you have module name and defines module set to yes, and use it in your Objective-C class.
You have to import a header in Objective-C classes, which is:
#import “ProductModuleName-Swift.h”
It is automatically generated, on the reference it says "Any Swift files in your target will be visible in Objective-C .m files containing this import statement."
An actual file in the project is not created ([ProductModuleName]-Swift.h). Cmd + Click on the import either generates it on-the-fly (and in-memory) so you can see how the linkage is done, or opens a file somewhere in some Xcode cache dir, but it's not in the project dir.
You need to set Defines Module project prop (in target's Build Settings) to Yes and if your module name has spaces or dashes - use _ in all imports of the [ProductModuleName]-Swift.h file.
You can import it in all .h and .m files where you use swift types or you can import it in the .pch.
So if my Module (project) is named "Test Project", I would import it like this, in the .pch file of my project (just there):
#import "Test_Project-Swift.h"
Just a heads up for anyone who used "." in there project name. Xcode will replace the "." with an underscore "_" for the Swift version of the bridging header file. Oddly enough the Bridging-Header.h that is generated does not replace the periods with underscores.
For example a project with the name My.Project would have the following Bridging Header file names.
Bridging-Header.h (Autogenerated)
My.Project-Bridging-Header.h
Swift.h
My_Project.h
I hope this helps anyone who used a period and was stuck like I was. This file can be found at the following location.
Macintosh HD/Users/user/Library/Developer/Xcode/DerivedData/My.Project-fntdulwpbhbbzdbyrkhanemcrfil/Build/Intermediates/My.Project.build/Debug-iphonesimulator/My.Project.build/DerivedSources
Take care,
Jon
Project must have a Module Name not including spaces.
Defines Module must be set to Yes in Build Settings, under Packaging.
commented out the #import statement:
If still you are having error in importing "ProductModuleName-Swift.h" then
//#import "ProductModuleName-Swift.h"
which revealed a bunch of other errors in my Swift code.
Once I fixed these new errors and got the source building successfully, I uncommented out the #import and bingo! The header was created and importing correctly :)
I found a trick that always works on me.
Create your #import "ProductModuleName-Swift.h" in your appDelegate.h file and in your ProductName-Prefix.pch file. If you don't have it in xcode 6 you can create it with this way Why isn't ProjectName-Prefix.pch created automatically in Xcode 6?
Command+shift+k to clean your code, if you receive an error about your "ProductModuleName-Swift.h" delete it from appDelegate.h file.
Clean your code again. Now everything will work like a charm
If you receive again error about the "ProductModuleName-Swift.h", now create again in appDelegate.h file and clean your code again.
Do this work (delete and create the "ProductModuleName-Swift.h" from appDelegate.h file and clean your code) everytime you receive this error to silent it.
I Found this solution
Create SwiftBridge.h
put #import “ProductModuleName-Swift.h”
Make this .h file public (important) Select the file -> In Show the file Inspector (right bar) -> Make it public
Now you can
#import "SwiftBridge.h"
instead of ProductModuleName-Swift.h
This's a workaround solution, for the next version of Xcode I think this problem will be solved.
Good luck
If you were able to build a project before, with no issues related to “ProductModuleName-Swift.h” not found error, and now you are getting that nasty errors again, the reason might sit in your recent changes.
For me this was by (accidental) incorrect .swift file encoding. Reverting changes and bringing the back manually, does the job.
I was having a hard time determining my module name/objective-c's import of swift's headers. I did read a lot of articles here too.
But the definitive answer for your project name with all its included special characters (be it '.' or a numeric or a space) - you can find the text that will work for you in the "Product Module Name" under the target's Build Settings.
For example my target name started with a numeric - "1mg" and the field mentioned above showed "_mg" as my module name.
so I used #import "_mg-Swift.h" and it worked.
This may be an obvious point (maybe too obvious), but you must have at least one swift file in the project for the header to generate. If you are writing boilerplate or config code with the intention of writing swift later the import won't work.
In my case I had to set the deployment target to at least “OS X 10.9” and the -Swift.h header was automatically generated. Keep in mind that you can get a lot of deprecation warnings when you change the deployment target version, especially when you have an older and very large Objective C code base. In our case we also had a lot of work to do in XIB files & view classes.
I had to delete WatchOS2 swift code from my Objective C project. And only after that XCode offered to generate -Swift.h
I had similar problem but my project was compiling before and suddenly got error after few files code change. It took me while to figure out why I am getting 'File not found' error for myproject-swift.h file. The code changes I had done had some errors. Xcode did not point put those error instead all time showing the 'File not found error'. Then got copy of previous version code and I compared with new code and merged file one by one. After each file merge complied the project to find the error. So bottom line is if you have error in your code Xcode may just display 'file not found error' for myproject-swift.h file. Most likely you have compilation error in your project. Clean those error and it will work.
If you're using something like Cocoapods (and working out of the workspace rather than the project) try opening the project and building it before opening the workspace and building. YMMV.
Sometimes you just need to unset and then set again the target membership on the obj-c .m file.