How to dynamically auto-register C function so it could be available through the whole project without any imports/headers/externs/.pch-files? - objective-c

In my project I have an doSomething.m and soSomething.h files with the only C function:
void doSomething() {
}
The first question: what should I do to make this function accessible from any place in my code without needing to import any headers?
Note: I guess that to solve this problem the doSomething.h file is not needed at all, but its presence/absence is not a restriction.
I have the following pieces of knowledge but I can't have the whole picture of what is needed:
I can use some another function with attribute((constructor)) that will be run at compilation runtime and it could do some manipulations to register doSomething;
_class_addMethod_ adds methods on "runtime". But I don't know how to resolve "the class of global namespace";
NSObject's + load method but it is not relevant here.
The second tricky question on top of the first: when I will have an answer to the first question, how can I then prevent "Implicit declaration of function 'doSomething' is invalid in C99" exactly for the function doSomething and not for the all others?
UPDATE: I forgot to exclude from the consideration the following options:
.pch file, global headers
The files where I want to use doSomething method should not contain any additional declarations like extern void doSomething()

Well you cant really make it so you dont have to import a header, what you can do however is add the include into your pre compile header
Look in the "Supporting Files" folder in your project.
you will see a file like thise
<ProjectName>-prefix.pch
add your import at the bottom of this file. and every file will then have all the imports added here.
Note
I use Xcode
I guess if your using another IDE such as for GnuStep you would likely have another place similar. I dont know how the other IDE's work.

In the file where you want to use it, import it:
extern void doSomething (void);

Related

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!

Where would I place a global utility function in Objective C?

When writing an iOS app, where would I place a function that I intend to use from any other file?
For example, a function to convert a NSDate to a relative time string ("5 secs ago").
Would I make a class and make these functions all static?
Functions can be placed wherever convenient. If a function or group of functions is likely to be imported in many places, you can declare and implement them in their own .h/.m pair. So for example you might implement your date conversion function in a file named XYZDateUtilities.m, and declare it in XYZDateUtilities.h.
Declaring functions with the static qualifier would limit their scope to the file in which they were declared, so you wouldn't want to do that; in fact you'd want to do the opposite -- declare them as extern in the .h file so that they'll be visible in other files.
You have a couple options:
1) If you're extending the behavior of a class (such as the NSDate string conversion method you described), it may work best to simply create a category on said class.
Here's a tutorial on iOS categories:
http://mobile.tutsplus.com/tutorials/iphone/objective-c-categories/
Important Note:
Categories change a class's behavior (if you override a method) everywhere within the project whether or not you include the header (.h) file in another specific class's imports
For this reason, it's generally best to not override methods via a category, but instead, to create a subclass if you want to change certain methods.
For adding new methods, however, categories can be very convenient and useful.
2) If you want to create a new class that's imported everywhere, you can create said class and put its header import, i.e. #import "MyClass.h", into your project's prefix.pch file (found under the "supporting files" group within the project by default).
Anything that you put into the prefix.pch file will be available anywhere within your app. This is also a useful place to put constants (such as strings) or define enums that are used across many classes within the app.
I hope this helps. Let me know if further clarification is needed, and I'll do my best to help.
Cheers!
Another option would be to create a class for your helper methods and implement all the helpers as class methods.
e.g. HelperClass.h
+ (NSString *)getFrenchCapital
e.g. HelperClass.m
+ (NSString *)getFrenchCapital
{
return #"Paris";
}
Then import your helper class wherever you need it, and simply call the class methods:
e.g. Foo.m
#import "HelperClass.h"
...
- (void)logFrenchCapital
{
NSLog(#"Capital of France: %#", [HelperClass getFrenchCapital]);
}
If you make all functions static in a class, then alternative is to just define functions in .m file, and extern functions in .h file, just like what you do in C.

Removing a method call from inside a static lib(.a) without recompiling

I'm using a static lib thats giving me a warning when uploading my binary for review by apple.
The method in the static lib that causes the warning(non-public selectors) is never called by me, its corresponding .h is deleted from my proj, but warning still persists.
Given that I know the method name causing the problem, is there a way for me to open/edit this .a and comment/delete the offending piece of code and then use the modified .a in my project.
I don't have access to the .a source to recompile it, and its very old and the creator of it has no contact details for me to track down.
Many Thanks,
-Cake
Quick and dirty solution: Open the .a file in a hex editor and change all instances of the name. Leave the function name the same length so that offsets in the file don't change, just change a letter or something like that. I did a quick test, adding a dummy function to a subproject we're building as a static library then tweaking the function name in the .a file (there were five instances, for what that's worth) and everything built okay. I don't see any reason it wouldn't pass the App Store check after that.
I'm really surprised the function was still there in the final build, though—I thought Dead Code Stripping was supposed to clean out any unused code. Huh.
http://opensource.apple.com/source/cctools/cctools-809/
I don't presume to get your bounty, because I haven't provided an easy solution. But yes, it in theory is possible. You have your work cut out for you.
There are several solutions, depending on your lib and project.
In your build settings :
Enable "dead code stripping" if possible : If the method is never used (even internally), the symbol will be deleted.
Use "Unexported symbol file" : Simply add the symbol into a file and it will be removed from the binary. This will work even if the symbol is used internally.
Enable "Deployment Postprocessing" and "Strip Linked Product" with "Strip Style" set to "All symbol"
(Not sure) Use "Symbols Hidden by Default". This is related to the code generation and should not affect linking, but just in case everything above failed...
No need to hack the binary files. Just turn off the compiler's "unused selectors" warning: -fno-unused-selectors.

Objective-C's #import statement - Won't Import a file inside a folder

I'm new to Objective-C here, and still learning its syntax, so I'm experimenting some things... and I'm trying to understand how the #import statement works when it comes to importing a file inside a folder.
I have a main function inside of a file and in the same directory of my main function contains a folder for a class, inside that folder I am trying to import a header file for that class.
I'm trying to import it like this:
#import "Person/person.h"
And I believe that should work but instead Xcode fires off a error saying it can not find the file/directory.
The folder that contains person.h is in the same directory as my main function's file.
I still don't understand what's wrong with that piece of code, if someone can tell me the proper way to do this it would help a lot, thanks!
Try #import "person.h", the folder isn't really. It is a group, something like a virtual folder in the project, that let you organize visually your project files.
(one way) to use this functionality is to add the parent directory (of Person/) to your target's include paths.

How can I get a method to return a Random object of type NSObject

I as a learning exercise of Objective C I need to write a method that returns a Random NSObject.The approach that I tried to follow was to trying to get a list of all runtime objects and the itirate through and get an NSObject and return that.
Firstly I am not sure if that is the best approach. Secondly the code I am using is based on this and objc_getClassList link but in Xcode4 I am getting compile time error
warning: Semantic Issue: Implicit declaration of function 'objc_getClassList' is invalid in C99
warning: Semantic Issue: Implicit declaration of function 'classIsSubclassOfClass' is invalid in C99
I have tried adding following headers but no good
#import <objc/runtime.h>
#import <objc/objc-class.h>
#import <objc/objc-runtime.h>
but neither helped me and still have the warning.
So can I please some help with these two things 1- Is this the right approach and what is if not to achieve what I am trying to achieve 2- How can I get this code to not give warnings in Xcode 4.
Well, objc_getClassList is declared in objc/runtime.h, so including or importing that should do it.
For the other part, you simply need to declare your function before you use it. At the top level of the file, or in a file that you then include, you put the function header, without the body:
BOOL classIsSubclassOfClass( const Class aClass, const Class subclass );
This lets the compiler know about the function; you can then #include this declaration in any file that needs to use the function, while defining it (i.e., filling out the body) wherever you like.
So what you want is to get a class, any class, that inherits from NSObject?
I do not think this is the right approach at all. I can not see the need to get any random class. What would you do with it?
Maybe what you want to is add a subset of known classes that are of use to use in an array. And then pick one at random from that array.