I included in my iOS project a widely used UIImage category to handle PDF, and got some compilation errors. This raised several questions.
Q1: Why would Xcode (or actually the LLVM compiler) not give any warning on a header file that is including itself ? I don't know if this has a special meaning in C or Objective-C that would prevent it from being seen as a typo ? In my example, I believe that a mistake was made and Foundation.h was probably the intended include:
In the category file NSString+MD5.h I found:
#import "NSString+MD5.h"
#interface NSString(MD5)
- (NSString *)MD5;
#end
The corresponding .m does not include the .h. (Link is "Here")
Q2: I got the compilation error because I started from an Apple project that doesn't NOT include the Foundation framework (AVCam 3.1 for iOS) ! So NSString was undefined. I'm a bit puzzled by this but linking with the foundation framework in xcode is like including all its headers ? I would expect again some warning at least ?
Thanks for any explanation on this probably very basic C topic.
First of all, in Objective-C, we #import, which is different from #include. While #include will attempt to include any file you list, #import will never double import any file. I imagine that this explains why there's no problem with a .h file trying to #import itself. It's not correct for the file to import itself, but because it's an #import, it won't actually cause any issues.
As for the .m file not importing it's .h, in this case, it doesn't actually have to. It's a good idea, out of habit, to always import the .h file, and any files generated by Xcode will do this automatically, however it's not always necessary. It's only necessary when the .h file has declared something that the .m has to know about. For example, a #property that you intend to use. You've declared it in the .h so it'd have public access, but if you intend to use it in the .m, the .m has to know the #property has been defined. Additionally, if you've #imported some files in the .h that the .m needs and you don't want to import them again in the .m, you'd need to import the .h (although it's generally going to be better to just import them in the .m.
Here, the .h simply defines the exists of a method that returns an NSString * and is called md5 and takes no arguments. This means that anything importing this .h file can call this method and Xcode won't complain about the md5 method not existing. The corresponding .m file implements a method that coincidentally matches the one the .h defined. If you deleted the .m file, your program would almost certainly still compile just fine... but you'd hit an unrecognized selector exception when you go to the point that md5 was being called--despite Xcode not complaining about it. With the .m in the project, this exception isn't hit. The program figures out at run time which method to execute.
And finally, as for not including Foundation.h, every iOS project created by Xcode has #import Foundation.h and #import UIKit.h in the precompiled header file. Any other file in your project with these imports is just redundantly importing the file, as it's already been imported by the .pch, but because of the magic of #import (vs #include) it's not actually double imported.
If you're working with an iOS project that doesn't have these imports in your .pch, your best bet is to just stick them in the .pch.
If you're opposed to this for some reason, the best way to fix this md5 file is with this simple line:
#import Foundation.NSString;
Related
This question probably has an answer elsewhere, but I've only found answers for outdated versions of Xcode or projects that use Swift.
I am using Xcode 10 and reading iOS Programming The Big Nerd Ranch Guide, 4th Edition. I am using such an old version because this is the resource that my work provided to me.
Currently I am trying to add a method to a CoreData generated class for Objective-C.
With CodeGen set to Category/Extension with my entity selected in CoreData the generated class files are:
BNRItem+CoreDataProperties.h/m
BNRItem+CoreDataClass.h/m
BNRItem+CoreDataClass.h includes BNRItem+CoreDataProperties.h, and BNRItem+CoreDataProperties.h includes BNRItem.h (which does not exist). I assume that I need to create BNRItem.h but I don't know what file to import into BNRItem.h since either BNRItem+CoreDataProperties.h or BNRItem+CoreDataClass.h would seem to create a circular include cycle.
In which file do I add an instance method to a CoreData generated class for Objective-C in Xcode 10?
The convention is to use #class in the .h file and #import in the .m file, except when #import is necessary in the .h file. The latter occurs when referring to a superclass or protocol.
The idea is to speed up recompiles. If ClassA.h imports ClassB.m, and you change only ClassB.m during development, then because ClassA.m imports ClassA.h which imports ClassB.m, ClassA.m will need to be recompiled during the next build, even though it is unchanged.
Of course, all of this goes away in Swift :)
This is likely not the actual answer, but I fixed this by changing the CodeGen to Manual/None and editing the files that it generated.
What about leaving the code generation option to Class Definition and create an extension (a category in Objective-C) of your entity?
The #import statement was introduced to resolve the cyclic dependencies created by #include.
So it doesn’t matter much if you are using #import, but if you’re still concerned you can also use #class forward declaration
This has always been my struggle, but just now I ran into this Apple article.
The second way, is the way you are trying to use. The unexpected step is to move the properties file to the trash. And actually it seems the <class>+CoreDataClass files have to be renamed to just <class>.h and .m. After that you can use those files to extend your class and the property files keep being generated.
So the steps to create your managed object class are:
Choose Category/Extension in the data model inspector for your entity.
Generate your class with the Editor > Create NSManagedObject Subclass... menu.
Move the created <class>+CoreDataProperties.h and .m files.
Additional step: rename the data class files as just described.
I'm working on an iOS project that contains Swift and Objective-C Classes.
To instantiate an object described in Objective-C, I've understand that I needed to have a Bridging-Header file that contains all the imports of the headers I will have to use on my Swift classes. And it works great on my project.
I made all classes I needed, I subclassed Objective-C classes in Swift, everything is OK.
My problem is when it comes to do the opposite: instantiate a swift object in an Objective-C file. So I read that I need to have those options:
Define Modules as Yes
add the line #import "<#YourProjectName#>-Swift.h" on the *.m file I'm working on.
And that is what I did:
I changed all the values on the Build Settings that needed to be changed. I added the import line, I even tried to create the header file, but I still have the "<#YourProjectName#>-Swift.h" file not found error.
Of course, I replaced the YourProjectName by the actual module name, the one I found under Product Module Name in Packaging section on Build Settings. Also, there is no spaces in the Project Name.
Did I forgot a step?
Make sure you are importing the -Swift.h file from a .m Objective-C file and not a .h header file. The docs only talk about importing from .m:
... import the Xcode-generated header file for your Swift code into any Objective-C .m file you want to use your Swift code from.
The -Swift.h file is generated during the build and I've found that importing it from a .h file always fails, even when I know the file exists. Since it's generated by the build, I'm guessing it's cleaned out when the compiler is sifting through the headers and regenerated once the .swift files are compiled.
Just wondering -
When you start to type #import "
Xcode suggests .m files and .h files. I just had a few hours of frustration after mistakenly importing .m file.
Is that a bad design? Can you import .m files?
You can import any files. #import is just a preprocessor directive that basically says "include contents of the file I tell you into the current file". There are some include guards as well, but the import does just that - it imports the file you tell it to.
Importing the header with .h file is probably more of a convenience/convention (please don't beat me for this, I'm just guessing) unless there's some C/C++ standard that says otherwise.
I am facing an issue, Currently i am using xcode 5.0, when i am importing clasess from prefix.pch then it dose not give suggestions on appdelegate.h file. But it gives suggestion on other view controller's. I have googled about it and find if we define macros in prefix.pch then this problem occurred. Still after removing the macros it did not give suggestion on appdelegate.
Suggestios means if i try to write
#property(strong,nonatomic) UINavigationController *navControler;
After writing #property(strong,nonatomic) UINav xcode did not give suggestion. But if I remove all the import statement and macros from prefix.pch file then xcode give suggestions on appdelegate.
From my point of view, rather than finding a workaround, I want to put some light on the actual problem.
So when you want to add something in .pch (pre compiled headers), it means you want to use the content of files before your program is actually being compiled & build. In simple words the headers included in pch acts as a stub code, a base code or may be a code that is meant for using as it is intact.
So if you have already included appDelegate.h file in .pch & writing some code in appDelegate.h file, then the compiler is trying to use 'appDelegate.h` from .pch as a pre-compiled information. And may be it is resulting in a indefinite sate of Xcode background processing, which is not allowing to show the drop down helps in the file which is already pre-compiled.
To me it looks like app delegate.h in .pch is not the right place. Where ever you want in your program, you can very well include appDelegate.h file. However it is also a signal of bad Class Design approaches.
Also, if you want to add #define statement & other macros in .pch then it is not the right approach. The right approach is :
Make a simple .h file, say constants.h
Add all your #defines & macros here in constants.h file.
Add the #import "constants.h" in your .pch file.
That should solve your problem.
Hope that helps.
Default file:
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#end
My understanding is pre-compiled headers are included in every file. Why doesn't this import just go into the pre-compiled headers?
There is no guarantee that every project have a .pch file that import Foundation.h so Xcode need to generate it to make sure new files always compile.
Also some people think it is good style to include header even it is already included in .pch file. Because you know exactly what headers are needed by this file. It also allow people to disable prefix header if needed.
My Xcode 5 doesn't appear to be including it in every class (it is included in the .pch file). I agree with you that this makes more sense than including it everywhere. The answer to your question is probably "an oversight on Apple's part" :)