In Objective-C, is there a way to get a class and send messages to it when you have the name of the class as a string? For example, is there a function func where func(#"NSString") == [NSString class]?
The reason that I want to know this is I am building a dynamic linker library for a language I am working on, and I want it to have an interface to Objective-C libraries.
Yes — two, in fact. If you have a Foundation-type framework (e.g. from Cocoa, Cocoa Touch or GNUstep), you can use the NSClassFromString() function, which is precisely the same as your func. If you do not want to depend on a framework, there's a similar runtime function, objc_getClass(), that takes a const char* and returns the named class (or nil if none is found).
You can use NSClassFromString(NSString className) to get the class object from its name.
Hope this helps!
Related
My iOS application can use an optional external 3rd party library.
I thought of using this answer (Weak Linking - check if a class exists and use that class) and detect if the class exists before executing code specific to this library.
However, I found out that this external library is not written as Objective-C classes, but rather as C STRUTS and functions.
Is there a similar technique that would allow me to check if a C Strut or function exists? Or some better alternative to see if this library is present at runtime?
structs are compile-time artifacts. They tell the compiler how to lay out a region of memory. Once that is done, structs become unnecessary. Unlike Objective-C classes which have metadata, structs have no runtime presence. That is why it is not possible to detect them at runtime.
You can check if a dynamic library is present by calling dlopen, and passing its path:
void *hdl = dlopen(path_to_dl, RTLD_LAZY | RTLD_LOCAL);
if (hdl == NULL) {
// The library failed to load
char *err = dlerror(); // Get the error message
} else {
dlclose(hdl);
}
If dlopen returns NULL, the library cannot be loaded. You can get additional info by calling dlerror. You need to call dlclose after you are done.
AFAIK a classical C function has to exist. It is statically bound during the linking process and it is not, like Objective-C mehtods, dynamically bound on runtime.
So when the code compiles AND links without errors or warnings, then you should be fine.
The same for structs.
I need to find a way to tell the C compiler of my program that a certain structure is the same as the other structure (they are identical in definition). I figured casting would be decent enough, but maybe its not a good idea?
The reason that I am not just using one struct is because the structs are defined in very heavy framework classes and I have a lot of different classes of my own importing the class that requires the use of the structure in it's .h.
So, how can I tell the compiler that Struct A can be used for a function requiring Struct B, given that they are identical, if it is even possible?
To make this very specific, in my case, I have a singleton that is accessed and utilized by around 14 classes. Some of the functions in the singleton work alongside the other classes and provide resources and data for their specific imports. One of which is the MapKit framework. There are a number of structs within the MapKit framework that I have been utilizing (especially MKUserLocation.h), but will import a number of other classes and add on a lot to the definition.
A specific example for me is using CLLocationCoordinate2D, which I have had to recreate in my singleton so that not all 14 classes import from the MapKit framework. It just seems excessive.
I know how to make this all work, but there should be a good solution to this other than casting or importing to everything.
Can you simply write a global function to convert from one struct to another?
void OneStructToAnotherStruct( struct FromStruct* from, struct ToStruct* to )
{
to->x = from->x;
to->y = from ->y;
to->z = from->z;
}
I want to create an Objective C class at runtime from a file. So for example I have an objective c application, I want to then point it at a text file (or an .h .m pair, whatever works) and then have the application parse the text file and create the class at runtime (Class no object). Of course I would write the parser and all of that stuff I just want to know if its possible. I read these two articles:
http://www.mikeash.com/pyblog/friday-qa-2010-11-6-creating-classes-at-runtime-in-objective-c.html
http://www.mikeash.com/pyblog/friday-qa-2010-11-19-creating-classes-at-runtime-for-fun-and-profit.html
Which shows how to make an objective C class at runtime, but its being done using C functions which were defined at compile time. If I can find a way to do the same thing using strings to define the functions that would be perfect, because then I don't have to define them at compile time.
That's what called reflective programming. I guess there's no code evaluation support for Obj-C since it's not a scripting language, so the reflection concept for Obj-C is quietly limited. Plus, at run-time the compiler already translate the code into Obj-C clang code and it's a very time-consuming job just to reverse-translate the bytecode and recompile it again
For Obj-C reflection you can refer to these answers
Build a class :
Create objective-c class instance by name?
Implement a method :
Objective-C, how can i hook up a method in another class
Change class for an object :
Objective-C: How to change the class of an object at runtime?
Sure. Totally possible.
I would suggest starting with the Objective-C support in this as it includes a full-on Objective-C parser and code generator.
see my github project cocoa-interprreter it does part of what you want.
it takes a text file and compiles it at runtime .. and then runs the resulting executable using NSTask. It would be quite easy to change it so the binary is loaded into the own process using NSBundle
https://github.com/Daij-Djan/cocoa-interpreter
I left the original, so people can understand the context for the comments. Hopefully, this example will better help explain what I am after.
Can I create a class in Obj-C that has file-scope visibility?
For example, I have written a method-sqizzling category on NSNotificationCenter which will automatically remove any observer when it deallocs.
I use a helper class in the implementation, and to prevent name collision, I have devised a naming scheme. The category is NSNotificationCenter (WJHAutoRemoval), so the private helper class that is used in this code is named...
WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver
That's a mouthful, and currently I just do this...
#define BlockObserver WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver
and just use BlockObserver in the code.
However, I don't like that solution.
I want to tell the compiler, "Hey, this class is named Bar. My code will access it as Bar, but I'm really the only one that needs to know. Generate a funky name yourself, or better yet, don't even export the symbol since I'm the only one who should care."
For plain C, I would is "static" and for C++ "namespace { }"
What is the preferred/best/only way to do this in Obj-C?
Original Question
I want to use a helper class inside the implementation of another. However, I do not want external linkage. Right now, I'm just making the helper class name painfully unique so I will not get duplicate linker symbols.
I can use static C functions, but I want to write a helper class, with linker visibility only inside the compilation unit.
For example, I'd like to have something like the following in multiple .m files, with each "Helper" unique to that file, and no other compilation unit having linker access. If I had this in 10 different files, I'd have 10 separate classes.
#interface Helper : NSObject
...
#end
#implementation Helper : NSObject
...
#end
I have been unable to find even a hint of this anywhere, and my feeble attempts at prepending "static" to the interface/implementation were wrought with errors.
Thanks!
I don't believe you will be able to do what you want because of the Objective-C Runtime. All of your classes are loaded into the runtime and multiple classes with the same name will conflict with each other.
Objective-C is a dynamic language. Unlike other languages which bind method calls at compile time, Objective-C does method resolution at invocation (every invocation). The runtime finds the class in the runtime and then finds the method in the class. The runtime can't support distinct classes with the same name and Objective-C doesn't support namespaces to seperate your classes.
If your Helper classes are different in each case they will need distinct class names (multiple classes with the same name sounds like a bad idea to me, in any language). If they are the same then why do you want to declare them separately.
I think you need to rethink your strategy as what you are trying to do doesn't sound very Objective-C or Cocoa.
There's no way to make a class "hidden." As mttrb notes, classes are accessible by name through the runtime. This isn't like C and C++ where class are just symbols that are resolved to addresses by the linker. Every class is injected into the class hierarchy.
But I'm unclear why you need this anyway. If you have a private class WJHAutoRemovalHelper or whatever, it seems very unlikely to collide with anyone else any more than private Apple classes or private 3rdparty framework classes collide. There's no reason to go to heroic lengths to make it obscure; prefixing with WJHAutoRemoval should be plenty to make it unique. Is there some deeper problem you're trying to fix?
BTW as an aside: How are you implementing the rest of this? Are you ISA-swizzling the observer to override its dealloc? This seems a lot of tricky code to make a very small thing slightly more convenient.
Regarding the question of "private" classes, what you're suggesting is possible if you do it by hand, but there really is no reason for it. You can generate a random, unique classname, call objc_allocateClassPair() and objc_registerClassPair on it, and then assign that to a Class variable at runtime. (And then call class_addMethod and class_addIvar to build it up. You can then always refer to it by that variable when you need it. It's still accessible of course at runtime by calling objc_getClassList, but there won't be a symbol for the classname in the system.
But this is a lot of work and complexity for no benefit. ObjC does not spend much time worrying about protecting the program from itself the way C++ does. It uses naming conventions and compiler warning to tell you when you're doing things wrong, and expects that as a good programmer you're going to avoid doing things wrong.
What is the standard way of incorporating helper/utility functions in Obj-C classes?
I.e. General purpose functions which are used throughout the application and called by more than 1 class.
Can an Obj-C method exist outside of a class, or does it need to be a C function for it to have this kind of behaviour?
I would group similar functions as static methods in a helper class. These can then be called using the classname rather the instance name. Static methods are defined with a + instead of the usual -.
like so:
#interface HelperClass: superclassname {
// instance variables - none if all methods are static.
}
+ (void) helperMethod: (int) parameter_varName;
#end
This would be called like so.
[HelperClass helperMethod: 10 ];
As this is static you do not init/alloc the class. This has the advantage of clearly grouping like Helper functions. You could use standalone C functions but as your Application gets larger it can become a right mess! Hope this helps.
Tony
I don't see why people are avoiding creating functions. Objective-C is a superset of C, which means that C is part of it. Moreover, it's completely integrated—there's no wall between them.
Create functions! It's fine! Foundation does it. Application Kit does it. Core Animation does it. Core Media does it.
I see no reason not to.
There are a number of options for this in Objective-C. First, since Obj-C is a strict superset of C, you can define all your library functions in a separate module (source file) and happily call them from any Obj-C object/code you already have. If you create an obj-c source file (.m file) you can then call back into/use objects.
If your generic functions are logically manipulating other, established objects (for instances, operates on an NSString), you can use categories to graph your functions on already existing classes (where that makes sense).
Finally, as Tony points out, you can create classes with static methods (although I like this option the least, personally). I tend to use a mix of one an two... adding categories where appropriate and using standard functions for others. I generally only make a new class where it makes sense to design a class.