Accessing static variables that are simulating class variables from unit tests - objective-c

Is there an Objective-C runtime library function (unlikely) or set of functions capable of inspecting static (quasi-class level) variables in Objective-C? I know I can utilize a class accessor method but I'd like to be able to test without writing my code "for the test framework".
Or, is there a obscure plain C technique for external access to static vars? Note this information is for unit testing purposes—it needn't be suitable for production use. I'm conscious that this'd go against the intent of static vars... a colleague broached this topic and I'm always interested in digging into ObjC/C internals.
#interface Foo : NSObject
+ (void)doSomething;
#end
#implementation Foo
static BOOL bar;
+ (void)doSomething
{
//do something with bar
}
#end
Given the above can I use the runtime library or other C interface to inspect bar? Static variables are a C construct, perhaps there's specific zone of memory for static vars? I'm interested in other constructs that may simulate class variables in ObjC and can be tested as well.

No, not really, unless you are exposing that static variable via some class method or other. You could provide a + (BOOL)validateBar method which does whatever checking you require and then call that from your test framework.
Also that isn't an Objective-C variable, but rather a C variable, so I doubt there is anything in the Objective-C Runtime that can help.

The short answer is that accessing a static variable from another file isn't possible. This is exactly the same problem as trying to refer to a function-local variable from somewhere else; the name just isn't available. In C, there are three stages of "visibility" for objects*, which is referred to as "linkage": external (global), internal (restricted to a single "translation unit" -- loosely, a single file), and "no" (function-local). When you declare the variable as static, it's given internal linkage; no other file can access it by name. You have to make an accessor function of some kind to expose it.
The extended answer is that, since there is some ObjC runtime library trickery that we can do anyways to simulate class-level variables, we can make make somewhat generalized test-only code that you can conditionally compile. It's not particularly straightforward, though.
Before we even start, I will note that this still requires an individualized implementation of one method; there's no way around that because of the restrictions of linkage.
Step one, declare methods, one for set up and then a set for valueForKey:-like access:
// ClassVariablesExposer.h
#if UNIT_TESTING
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#define ASSOC_OBJ_BY_NAME(v) objc_setAssociatedObject(self, #v, v, OBJC_ASSOCIATION_ASSIGN)
// Store POD types by wrapping their address; then the getter can access the
// up-to-date value.
#define ASSOC_BOOL_BY_NAME(b) NSValue * val = [NSValue valueWithPointer:&b];\
objc_setAssociatedObject(self, #b, val, OBJC_ASSOCIATION_RETAIN)
#interface NSObject (ClassVariablesExposer)
+ (void)associateClassVariablesByName;
+ (id)classValueForName:(char *)name;
+ (BOOL)classBOOLForName:(char *)name;
#end
#endif /* UNIT_TESTING */
These methods semantically are more like a protocol than a category. The first method has to be overridden in every subclass because the variables you want to associate will of course be different, and because of the linkage problem. The actual call to objc_setAssociatedObject() where you refer to the variable must be in the file where the variable is declared.
Putting this method into a protocol, however, would require an extra header for your class, because although the implementation of the protocol method has to go in the main implementation file, ARC and your unit tests need to see the declaration that your class conforms to the protocol. Cumbersome. You can of course make this NSObject category conform to the protocol, but then you need a stub anyways to avoid an "incomplete implementation" warning. I did each of these things while developing this solution, and decided they were unnecessary.
The second set, the accessors, work very well as category methods because they just look like this:
// ClassVariablesExposer.m
#import "ClassVariablesExposer.h"
#if UNIT_TESTING
#implementation NSObject (ClassVariablesExposer)
+ (void)associateClassVariablesByName
{
// Stub to prevent warning about incomplete implementation.
}
+ (id)classValueForName:(char *)name
{
return objc_getAssociatedObject(self, name);
}
+ (BOOL)classBOOLForName:(char *)name
{
NSValue * v = [self classValueForName:name];
BOOL * vp = [v pointerValue];
return *vp;
}
#end
#endif /* UNIT_TESTING */
Completely general, though their successful use does depend on your employment of the macros from above.
Next, define your class, overriding that set up method to capture your class variables:
// Milliner.h
#import <Foundation/Foundation.h>
#interface Milliner : NSObject
// Just for demonstration that the BOOL storage works.
+ (void)flipWaterproof;
#end
// Milliner.m
#import "Milliner.h"
#if UNIT_TESTING
#import "ClassVariablesExposer.h"
#endif /* UNIT_TESTING */
#implementation Milliner
static NSString * featherType;
static BOOL waterproof;
+(void)initialize
{
featherType = #"chicken hawk";
waterproof = YES;
}
// Just for demonstration that the BOOL storage works.
+ (void)flipWaterproof
{
waterproof = !waterproof;
}
#if UNIT_TESTING
+ (void)associateClassVariablesByName
{
ASSOC_OBJ_BY_NAME(featherType);
ASSOC_BOOL_BY_NAME(waterproof);
}
#endif /* UNIT_TESTING */
#end
Make sure that your unit test file imports the header for the category. A simple demonstration of this functionality:
#import <Foundation/Foundation.h>
#import "Milliner.h"
#import "ClassVariablesExposer.h"
#define BOOLToNSString(b) (b) ? #"YES" : #"NO"
int main(int argc, const char * argv[])
{
#autoreleasepool {
[Milliner associateClassVariablesByName];
NSString * actualFeatherType = [Milliner classValueForName:"featherType"];
NSLog(#"Assert [[Milliner featherType] isEqualToString:#\"chicken hawk\"]: %#", BOOLToNSString([actualFeatherType isEqualToString:#"chicken hawk"]));
// Since we got a pointer to the BOOL, this does track its value.
NSLog(#"%#", BOOLToNSString([Milliner classBOOLForName:"waterproof"]));
[Milliner flipWaterproof];
NSLog(#"%#", BOOLToNSString([Milliner classBOOLForName:"waterproof"]));
}
return 0;
}
I've put the project up on GitHub: https://github.com/woolsweater/ExposingClassVariablesForTesting
One further caveat is that each POD type you want to be able to access will require its own method: classIntForName:, classCharForName:, etc.
Although this works and I always enjoy monkeying around with ObjC, I think it may simply be too clever by half; if you've only got one or two of these class variables, the simplest proposition is just to conditionally compile accessors for them (make an Xcode code snippet). My code here will probably only save you time and effort if you've got lots of variables in one class.
Still, maybe you can get some use out of it. I hope it was a fun read, at least.
*Meaning just "thing that is known to the linker" -- function, variable, structure, etc. -- not in the ObjC or C++ senses.

Related

How to write methods that should only be used within the class itself and are able to access ivars [duplicate]

This question already has answers here:
Best way to define private methods for a class in Objective-C
(12 answers)
Closed 9 years ago.
I have a class which has some methods that are only to be used within the class itself. These methods exist because I have a three-step process for the graphics work I'm doing, but I only want instances of the class to access the final result of those calculations, in a simplified example:
#import <Foundation/Foundation.h>
#interface GraphicsWorld : NSObject
#property(nonatomic, strong) NSMutableArray *objects;
#property(nonatomic, strong) NSMutableArray *adjustedObjects
/* three methods I'll never use outside of this class
I want to find a way to get replace these methods.
*/
-(void) calcTranslation;
-(void) calcRotation;
-(void) calcPerspective;
/* the one method I'll use outside of this class */
-(NSMutableArray *) getAdjustedObjects;
#end
I could define c-functions just outside of my implementation for this, but then they wouldn't have access to the properties:
#import <Foundation/Foundation.h>
#import "GraphicsWorld.h"
void calcTranslation()
{
// I'm useless because I can't access _objects.
}
void calcRotation()
{
// Hey, me too.
}
void calcPerspective()
{
// Wow, we have a lot in common.
}
#implementation GraphicsWorld
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation();
calcRotation();
calcPerspective();
return adjustedObjects;
}
#end
Unless I'm misunderstanding your question, it sounds like you just want to hide your methods from being public? If so, just delete them from the header. You no longer need to declare methods in advance in objc (Xcode). The compiler will just find them internally now.
Make C-style functions (as you've shown) that take arguments and return values.
Make private Objective-C-style methods.
In addition to your #implementation section in the .h file, you can also have one in your .m file, which is private. Just as you declare methods and properties in the .h file's #implementation, you can do the same in the .m.
A method can be called whether it is declared private, or not put in the header file; due to the nature of Objective-C hiding methods is hard.
Hiding functions is a lot easier, just declare them static. To access the current instance you just pass in a reference to it - i.e. exactly what Objective-C does behind the scenes.
So for example:
void calcTranslation(GraphicsWorld *self)
{
// Access properties, instance variables, call instance methods etc.
// by referencing self. You *must* include self to reference an
// instance variable, e.g. self->ivar, as this is not a method the
// self-> part is not inferred.
}
and to call it:
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation(self);
...

What is the difference between the areas where you can declare instance variables in Objective-C? [duplicate]

Ever since starting to work on iOS apps and objective C I've been really puzzled by the different locations where one could be declaring and defining variables. On one hand we have the traditional C approach, on the other we have the new ObjectiveC directives that add OO on top of that. Could you folks helps me understand the best practice and situations where I'd want to use these locations for my variables and perhaps correct my present understanding?
Here's a sample class (.h and .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
#end
and
#import "SampleClass.h"
// 4) what goes here?
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
#implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
#end
My understanding of 1 and 4 is that those are C-style file-based declarations and definitions that have no understanding whatsoever of the concept of class, and thus have to be used exactly how they would be used in C. I've seen them used for implementing static variable-based singletons before. Are there other convenient uses I'm missing?
My take from working with iOS is that ivars have been alost completely phased out outside of the #synthesize directive and thus can be mostly ignored. Is that the case?
Regarding 5: why would I ever want to declare methods in private interfaces? My private class methods seem to compile just fine without a declaration in the interface. Is it mostly for readability?
Thanks a bunch, folks!
I can understand your confusion. Especially since recent updates to Xcode and the new LLVM compiler changed the way ivars and properties can be declared.
Before "modern" Objective-C (in "old" Obj-C 2.0) you didn't have a lot of choices. Instance variables used to be declared in the header between the curly brackets { }:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#end
You were able to access these variables only in your implementation, but not from other classes. To do that, you had to declare accessor methods, that look something like this:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
#end
// MyClass.m
#implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
#end
This way you were able to get and set this instance variable from other classes too, using the usual square bracket syntax to send messages (call methods):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
Because manually declaring and implementing every accessor method was quite annoying, #property and #synthesize were introduced to automatically generate the accessor methods:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#synthesize myVar;
#end
The result is much clearer and shorter code. The accessor methods will be implemented for you and you can still use the bracket syntax as before. But in addition, you can also use the dot syntax to access properties:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
Since Xcode 4.4 you don't have to declare an instance variable yourself anymore and you can skip #synthesize too. If you don't declare an ivar, the compiler will add it for you and it will also generate the accessor methods without you having to use #synthesize.
The default name for the automatically generated ivar is the name or your property starting with an underscore. You can change the generated ivar's name by using #synthesize myVar = iVarName;
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#end
This will work exactly as the code above. For compatibility reasons you can still declare ivars in the header. But because the only reason why you would want to do that (and not declare a property) is to create a private variable, you can now do that in the implementation file as well and this is the preferred way.
An #interface block in the implementation file is actually an Extension and can be used to forward declare methods (not needed anymore) and to (re)declare properties. You could for instance declare a readonly property in your header.
#property (nonatomic, readonly) myReadOnlyVar;
and redeclare it in your implementation file as readwrite to be able to set it using the property syntax and not only via direct access to the ivar.
As for declaring variables completely outside of any #interface or #implementation block, yes those are plain C variables and work exactly the same.
First, read #DrummerB's answer. It a good overview of the whys and what you should generally do. With that in mind, to your specific questions:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
No actual variable definitions go here (it's technically legal to do so if you know exactly what you're doing, but never do this). You may define several other kinds of things:
typdefs
enums
externs
Externs look like variable declarations, but they're just a promise to actually declare it somewhere else. In ObjC, they should only be used to declare constants, and generally only string constants. For instance:
extern NSString * const MYSomethingHappenedNotification;
You would then in your .m file declare the actual constant:
NSString * const MYSomethingHappenedNotification = #"MYSomethingHappenedNotification";
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
As noted by DrummerB, this is legacy. Don't put anything here.
// 3) class-specific method / property declarations
#end
Yep.
#import "SampleClass.h"
// 4) what goes here?
External constants, as described above. Also file static variables can go here. These are the equivalent of class variables in other languages.
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
Yep
#implementation SampleClass
{
// 6) define ivars
}
But very rarely. Almost always you should allow clang (Xcode) to create the variables for you. The exceptions are usually around non-ObjC ivars (like Core Foundation objects, and especially C++ objects if this is an ObjC++ class), or ivars that have weird storage semantics (like ivars that don't match with a property for some reason).
// 7) define methods and synthesize properties from both public and private
// interfaces
Generally you shouldn't #synthesize anymore. Clang (Xcode) will do it for you, and you should let it.
Over the last few years, things have gotten dramatically simpler. The side-effect is that there are now three different eras (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). So when you see the older code, it can be a little confusing. Thus confusion arising from simplicity :D
I'm also pretty new, so hopefully I don't screw anything up.
1 & 4: C-style global variables: they have file wide scope. The difference between the two is that, since they're file wide, the first will be available to anyone importing the header while the second is not.
2: instance variables. Most instance variables are synthesized and retrieved/set through accessors using properties because it makes memory management nice and simple, as well as gives you easy-to-understand dot notation.
6: Implementation ivars are somewhat new. It's a good place to put private ivars, since you want to only expose what's needed in the public header, but subclasses don't inherit them AFAIK.
3 & 7: Public method and property declarations, then implementations.
5: Private interface. I always use private interfaces whenever I can to keep things clean and create a kind of black box effect. If they don't need to know about it, put it there. I also do it for readability, don't know if there are any other reasons.
This is an example of all kinds of variables declared in Objective-C. The variable name indicate its access.
File: Animal.h
#interface Animal : NSObject
{
NSObject *iProtected;
#package
NSObject *iPackage;
#private
NSObject *iPrivate;
#protected
NSObject *iProtected2; // default access. Only visible to subclasses.
#public
NSObject *iPublic;
}
#property (nonatomic,strong) NSObject *iPublic2;
#end
File: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
#interface Animal(){
#public
NSString *iNotVisible;
}
#property (nonatomic,strong) NSObject *iNotVisible2;
#end
#implementation Animal {
#public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
iPrivate = #"iPrivate";
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
_iPublic2 = #"iPublic2";
iNotVisible = #"iNotVisible";
_iNotVisible2 = #"iNotVisible2";
iNotVisible3 = #"iNotVisible3";
}
return self;
}
#end
Note that the iNotVisible variables are not visible from any other class. This is a visibility issue, so declaring them with #property or #public doesn't change it.
Inside a constructor it's good practice to access variables declared with #property using underscore instead self to avoid side effects.
Let's try to access the variables.
File: Cow.h
#import "Animal.h"
#interface Cow : Animal
#end
File: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
#implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
//iPrivate = #"iPrivate"; // compiler error: variable is private
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
self.iPublic2 = #"iPublic2"; // using self because the backing ivar is private
//iNotVisible = #"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = #"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = #"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
#end
We can still access the not visible variables using the runtime.
File: Cow.m (part 2)
#implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:#"iNotVisible" value:#"iMadeVisible"];
[self setIvar:#"_iNotVisible2" value:#"iMadeVisible2"];
[self setIvar:#"iNotVisible3" value:#"iMadeVisible3"];
NSLog(#"\n%# \n%# \n%#",
[self getIvar:#"iNotVisible"],
[self getIvar:#"_iNotVisible2"],
[self getIvar:#"iNotVisible3"]);
}
#end
Let's try to access the not visible variables.
File: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:#selector(blindAccess)];
}
}
This prints
iMadeVisible
iMadeVisible2
iMadeVisible3
Note that I was able to access the backing ivar _iNotVisible2 which is private to the subclass. In Objective-C all variables can be read or set, even those that are marked #private, no exceptions.
I didn't include associated objects or C variables as they are different birds. As for C variables, any variable defined outside #interface X{} or #implementation X{} is a C variable with file scope and static storage.
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.

Is there a way to wrap protocol buffers into Objective-C and still take advantage of inheritance?

I want to use Protocol Buffers in an iOS project. I'm trying to avoid making the whole project into an Objective-C++ fiasco, so I want to wrap the C++ protobuf classes into Objective-C ones. I have several dozen protobuf messages, and while I have done this successfully one class at a time, ideally I would like to use inheritance to minimize the repeated code. I'm new to Objective-C and I haven't used what little I knew of C++ in 10 years, so this has mostly been an exercise in frustration. Below is an example of how I have wrapped a single message.
Code
.proto:
message MessageA {
optional string value = 1;
}
MessageAWrapper.h:
#import <Foundation/Foundation.h>
#interface MessageAWrapper : NSObject
#property (nonatomic) NSString *value;
+ (id)fromString:(NSString *)string;
- (NSString *)serialize;
#end
MessageAWrapper.mm:
#import "MessageA.h"
#import "message.pb.h"
#interface MessageAWrapper ()
#property (nonatomic) MessageA *message;
#end
#implementation MessageAWrapper
- (id)init
{
self = [super init];
if (self) {
self.message = new MessageA();
}
return self;
}
- (void)dealloc {
delete self.message;
self.message = NULL;
}
- (NSString *)value {
return [NSString stringWithUTF8String:self.message->value().c_str()];
}
- (void)setValue:(NSString *)value {
self.message->set_value([value UTF8String]);
}
- (NSString *)serialize {
std::string output;
self.message->SerializeToString(&output);
return [NSString stringWithUTF8String:output.c_str()];
}
+ (id)fromString:(NSString *)string {
MessageA *message = new MessageA();
message->ParseFromString([string UTF8String]);
MessageAWrapper *wrapper = [[MessageAWrapper alloc] init];
wrapper.message = message;
return wrapper;
}
#end
Goal
There is a lot of code here that will be repeated dozens of times in which the only variation is the wrapped class type (init, dealloc, serialize, fromString), so ideally I would like to put it on a parent ProtobufMesssage class instead. Unfortunately I've had no success in making this work because I can't find a way for the parent class to know the class its children are using, which is required for example in init and fromString.
Things I've attempted
struct
template class
void*
Obstacles I've encountered
can't find a way to store a reference to a class/type
can't have any C++ headers or code in the .h file (as this requires the whole project to be Objective-C++)
difficulty keeping references to the protobuf message parents (Message or MessageLite) because they are abstract
As I said I have very little understanding of C++ or Objective-C; most of my experience is with much higher level languages like Python and Java (though I do mostly understand basic C things like pointers).
Is this perhaps not even possible? Am I approaching it wrong or missing something obvious? Any help would be much appreciated. Thanks.
I don't know much about C++ at all, but can't you declare the Objective-C property to be a Message *?
You've already separated the C++ code from the header by declaring the property in the .mm file, the problem you will have is with instance methods named by the compiler (value() and set_value()) and only being valid methods for the subclass. It might help to use the Reflection class to get and set fields by their name. Here is an excerpt from Google's message.h showing this:
Message* foo = new Foo;
const Descriptor* descriptor = foo->GetDescriptor();
const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
assert(text_field != NULL);
assert(text_field->type() == FieldDescriptor::TYPE_STRING);
assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
const Reflection* reflection = foo->GetReflection();
assert(reflection->GetString(foo, text_field) == "Hello World!");
You could create Objective-C -objectForKey: and -setObject:forKey: instance methods that typecheck and get or set the value (confusingly, the key in the case of MessageAWrapper would be #"value"). Your subclasses would not even need to be aware of the C++ code.
You can also separate the creator function in -init and +fromString: method into something like, +_createNewInstance;
+(Message*)_createNewInstance{ return new MessageA(); }
allowing your subclasses of MessageWrapper to reuse all code except for creating the C++ object.
While Objective C has very powerful instrospection capabilities, C++ is more limited. You do have RTTI (Run time type information), but it's not even as powerful as the Objective C counterpart.
However, it might be enough for you. Within your Objective C++ class, you might find the type of you message object with the typeid operator:
if( (typeid(self.message) == typed(foo)){
//doSomething
else if( (typeid(self.message) == typed(bar)){
// doSomething else
}
Maybe the best option is to add another indirection level. Make an Objective C class hierarchy that wraps all your protocol buffer C++ classes and then create another Objective C that uses those classes (as delegates maybe). I believe this might be a better option. Use C++ only for those unavoidable cases.
Good luck!

Can the new Clang Objective-C literals be redirected to custom classes?

Although the overloading of # begins to tread on dangerous territory, I love the addition of the new Objective-C literals in Clang 3.1. Unfortunately the new literals are of limited use to me. Except for instances where code needs to interface with AppKit, I've mostly dropped the use of Foundation classes in favor of my own custom framework (for a variety of reasons; most of which is that I need direct control over the memory allocation patterns used by objects).
I could always use some runtime trickery to pass off the newly created object as my custom class (and is what I already have to do with string object literals, since only the non-Apple GCC runtime supports the -fconstantstring=class flag), but this is a hack at best and throws out all the benefits I gained by replacing the equivalent Foundation class to begin with.
Unlike string object literals, the new literals Clang implements are not actually constant classes (where the memory layout is hardcoded); instead the appropriate messages are sent to their respective classes to create and initialize a new object at runtime. The effect is no different than if you had created the object yourself. In theory it means that the classes used and the methods called by the new literals are not hardcoded. In practice I can't find any way to change them to point to my own custom classes and methods (I would in fact be happy just to point to a custom class; pointing a dummy method to an actual method at runtime isn't difficult).
When I first looked into this, I was really hoping to find a set of flags that could be used to do what I'm asking, but as I haven't found any, I'm hoping someone has a solution.
You can substitute class for some Objective-C literals with #compatibility_alias keyword trick.
Here's an example.
#compatibility_alias NSNumber AAA;
Of course, you should provide proper implementation for new class.
#import <Foundation/NSObject.h>
#interface AAA : NSObject
+ (id)numberWithInt:(int)num;
#end
#implementation AAA
+ (id)numberWithInt:(int)num
{
return #"AAAAA!!!"; // Abused type system just to check result.
}
#end
#compatibility_alias NSNumber AAA;
Now Clang will do the job for you. I confirmed this is working for number, array, dictionary literals. Unfortunately string literals seem to be emitted statically, so it won't work.
For more information about #compatibility_alias keyword, see here.
Note
Because #compatibility_alias keyword is a compiler directive which applies to current compilation unit, you need to separate compilation unit to avoid symbol duplication with NSObject class in Apple's Foundation Kit. Here's how I did it.
main.m
#import "test.h" // Comes before Foundation Kit.
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool
{
NSLog(#"return of test = %#", test());
// insert code here...
NSLog(#"Hello, World!");
}
return 0;
}
test.h
id test();
test.m
#import "test.h"
#import <Foundation/NSObject.h>
#interface
AAA : NSObject
+ (id)numberWithInt:(int)v;
+ (id)arrayWithObjects:(id*)pobj count:(int)c;
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c;
#end
#implementation AAA
+ (id)numberWithInt:(int)v
{
return #"AAAAA as number!!!";
}
+ (id)arrayWithObjects:(id*)pobj count:(int)c
{
return #"AAAAA as array!!!";
}
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c
{
return #"AAAAA as dictionary!!!";
}
#end
#compatibility_alias NSDictionary AAA;
#compatibility_alias NSArray AAA;
#compatibility_alias NSNumber AAA;
id test()
{
// return #{};
// return #[];
return #55;
}
Result.
2013-03-23 08:54:42.793 return of test = AAAAA!!!
2013-03-23 08:54:42.796 Hello, World!
The comments have it all correct, but just to summarize:
No.
The meanings of Apple's #{}, #[], and #"" literals are hard-coded into Clang. You can see it here: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?view=markup It's all fairly modular, meaning that it wouldn't be hard for a Clang hacker to add her own literal syntax... but "modular" doesn't mean "accessible from the outside". Adding a new syntax or even redirecting the existing syntax to new classes would definitely require rebuilding Clang yourself.
Here's a blog post about adding NSURL literals to Clang by hacking on its internals: http://www.stuartcarnie.com/2012/06/llvm-clang-hacking-part-3.html (Thanks #Josh Caswell)
If you're willing to use Objective-C++ with C++11 extensions, you can has "user-defined literals", which allow you to write things like
NSURL *operator ""URL (const char *s) { return [NSURL URLWithString: #(s)]; }
int main() {
...
NSURL *myurl = "ftp://foo"URL;
...
}
This was mentioned in the comments on Mike Ash's blog. http://www.mikeash.com/pyblog/friday-qa-2012-06-22-objective-c-literals.html But this doesn't look very Objective-C-ish (or very C++ish!), and it works only with an Objective-C++11 compiler, and in general please don't do this. :)

Write Objective-C class from scratch

I'd like to write an Objective-C class without Cocoa or GNU's Object.h (for educational purposes). I dug around the net and it seems to me that quite a lot of stuff that one would expect to "come with the language", such as classes and message sending are actually defined in files written by third parties, such as objc-runtime.h.
Is there any documentation about what is really pure Objective-C and what is part of the runtime / frameworks? And what functionality do I have to implement to get a working environment without using any third-party code such as Object.h or objc-runtime.h (note again that this is for educational purposes, not for production code)?
Thanks for any insight!
Really, the only thing you must take care of yourself if you don't inherit from NSObject is object creation and destruction; methods otherwise behave the same way regardless of their parent class. Features like KVC and memory management are features of OpenStep/Cocoa, but not required as part of the language.
Here's a class from scratch:
#interface MyClass { // note the lack of a superclass here
#private Class isa;
}
+ (MyClass *)create;
- (void)destroy;
- (int)randomNumber;
#end
#implementation MyClass
+ (MyClass *)create {
return class_createInstance(self, 0);
}
- (void)destroy {
object_dispose(self);
}
- (int)randomNumber {
return rand();
}
#end
And here's how it could be used:
int main(int argc, char **argv) {
MyClass *foo = [MyClass create];
if (foo) {
printf("random! %i\n", [foo randomNumber]);
[foo destroy];
}
}
Edit: If you don't even want to use class_createInstance() and object_dispose(), you'll have to implement equivalents manually, as well as an equivalent of class_getInstanceSize() so you know how much memory an object occupies. But even if you manage that, don't think you've escaped the Objective-C runtime! Message dispatch is still entirely built on the C functions in the runtime, and Objective-C syntax is transformed into calls to those functions during compilation.
Matt Gallagher wrote a really cool post on writing a bare-bones Cocoa program. Since Objective-C is a superset of C, you can just do:
echo "int main(){return 0;}" | gcc -x objective-c -; ./a.out ; echo $?
Anyways, you probably would get a lot out of reading his post.
As far as avoiding the framework and creating your own base object goes, all you need to do is make sure that the first iVar is declared Class is_a and you could probably have a reasonable stab at replicating NSObject is by passing through to the runtime functions.
As far as avoiding the runtime library AND the framework goes, that's not really possible. Objective C (or at least, the bits that aren't just C) is a dynamic language. So pretty much everything it does that C doesn't do is handled by the runtime library.
It might be possible to build your own classes and objects using the 32bit runtime and the deprecated API, which doesn't abstract away the layout of classes, protocols, etc. to the extent that the modern runtime does (I've only really poked around with the modern runtime)
Perhaps you could create classes, add methods and allocate instances and by setting values in class_t structs and then using malloc() to allocate, although even then, you'd still be implicitly using the runtime function objc_msgSend every time you used the [obj selector] syntax -- unless you want to implement that as well, in which case you've just reimplemented the language yourself. The 'pure core' of the language you're looking for just is the runtime.
Here's an example of class, without using class_createInstance or object_dispose, or any other Objective-C Runtime (at least we don't call them directly).
#import <objc/objc.h>
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
static Class __scratchClass = NULL;
#interface Scratch {
Class isa;
char *name;
}
+ (id) initialize;
+ (Scratch*) new:(const char*)strName;
- (void) sayHello;
- (void) destroy;
#end
#implementation Scratch
+ (id) initialize {
__scratchClass = self;
return self;
}
+ (Scratch*) new:(const char*) strName {
Scratch* pObj = (Scratch*)malloc(sizeof(Scratch));
if (!pObj) return NULL;
memset(pObj, 0, sizeof(Scratch));
pObj->isa = __scratchClass;
pObj->name = (char*)malloc(strlen(strName)+1);
strcpy(pObj->name, strName);
return pObj;
}
- (void) sayHello {
printf("Hello, World!\nThis is Scratch (%s)...\n", name);
}
- (void) destroy {
if (name) {
free(name);
name = NULL;
}
free(self);
}
#end
int main(int argc, char** argv) {
Scratch* ps = [Scratch new:argv[0]];
[ps sayHello];
[ps destroy];
return 0;
}
Compile the code with (assuming you save it as 'test1.m'):
gcc -o test1 test1.m -lobjc