I added a set of classes to an array, all which I know have the same superclass:
[array addObject:[Africa class]];
[array addObject:[Brazil class]];
[array addObject:[France class]];
Later, I want to get the class object and call a superclass class method on it. Something like this:
Class class = [array objectAtIndex:1];
(Country class) specificClass = class;
I've tried a variation of different ideas, but can't figure out how to put that last line in code.
If I get you right you want a variable pointing to a class object, statically typed to a concrete class.
This not possible in Objective-C; there are no strongly typed class pointers. Class class is the best you can do.
You can send any known class method to a Class typed variable...
[class alloc];
[class defaultManager];
[class myCommonClassMethod];
... without making the compiler complain. Of course some of the examples might fail at runtime.
With a proper design pattern, you shouldn't need to know which country you are working with.
Start by creating an AbstractCountry class that declares (and provides stub implementations) of all the methods your countries need to generically respond to (i.e. countries can be more specific).
Then subclass that AbstractCountry for each individual country.
Then:
AbstractCountry *countryClass = [array objectAtIndex:n];
If you need behavior that only exists on a single country, then either push a stub implementation up (which wouldn't be terribly elegant) or test for response to selector (also not elegant) or cast appropriately (fragile).
Of course, all of this begs the question of why you have classes for this and not instances (though the instance design would be the same; consider something like UIControl and all the subclasses -- the control provides the abstract behavior of controls whereas the subclasses implement specific kinds of controls by oft overriding the abstract methods).
Usually in Objective-C you would call a method like so:
[class someMethod];
So in your case, let's pretend that your superclass (I'm assuming "Country") has a method to set the population or something, it would look like:
[Africa setPopulation:someInteger];
Related
Which from the following is the correct way of obtaining the meta class?
Class myMetaClass = objc_getMetaClass("NSString");
Or:
Class myMetaClass = object_getClass([NSString class]);
Are they both any different?
As mentioned in another post that is linked by the first answerer here:
Please tell me why objc_getMetaClass(); would break in certain cases in detail.
The proper way to use those in different scenarios.
Both functions are correct, but objc_getMetaClass("NSString") only works if NSString is registered with the objective C runtime. Which it almost always is if you want to get its metaclass.
But if you're creating a class using Class myClass = objc_allocateClassPair(superClass,"my_own_class",0) the situation is slightly different.
my_own_class isn't registered yet, so if you need to access the metaclass (in order to add class methods), you must use object_getClass(myClass).
objc_getMetaClass("my_own_class") would return nil.
The difference is, that the second function returns the object for the named class and the second first the object for the metaclass of the named class... :)
Both of them call the class handler callback if the class is not registered to check a second time. When you call the metaclass function you WILL get a return result.
...(However, every class definition must have a valid metaclass
definition, and so the metaclass definition is always returned,
whether it’s valid or not.)
from: Objective-C Runtime Reference
I think your real question is: What is the difference between a class and a metaclass ?
Please have a look at this excellent explanation:
What is meta-class in objective-c
This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}
I frequently need to refer to an array of strings (let's say team names) in multiple places. The contents of that array to not change.
To achieve this, I defined my own class, MyConstants. In the header I am defining some unrelated constant strings and numbers. In the implementation file, I made the class a singleton, and then added a class method arrayOfTeamNames.
To access the array, I use [Constants arrayOfTeamNames].
I this acceptable?
I was thinking about how NSString and NSArray themselves handle creation via class methods. If, for example, I want an empty array, I can use [NSArray array] - so presumably 'array' is a class method on NSArray.
Therefore, instead of my above implementation, should I be using a category to add '+arrayOfTeamStrings' to NSArray, instead of using my own class?
Or, alternatively, should I create my own subclass of NSArray and add the class method there?
In either case, do I need to make the class a singleton myself? Or is this not necessary?
In general, there can be very good uses for adding class methods to foundation classes via categories. But in this case, I would actually stick with arrayOfTeamNames being part of MyConstants. The fact that Team Names is an NSArray isn't as important as the fact that it's a constant for your application.
If the values defined in MyConstants are very diverse and unrelated, or if there are only a couple of them, then I would consider just getting rid of MyConstants as a class and using categories or even just externs, e.g. extern NSArray * const BPAllTeamNames.
Is it correct to use objc_setAssociatedObject for class object?
We often simulate class variables using static variables like that:
Objective C Static Class Level variables
but, can we use Associated objects as alternative?
objc_setAssociatedObject([self class], &STRING_KEY, myString, OBJC_ASSOCIATION_RETAIN);
Yes, a class object is a full-fledged object, so you can do anything to it that you can do with a regular object.
However, it is clearer and simpler to use a global variable.
p.s. Associating it with [self class] is not the same as using a global variable, because [self class] gives you the actual class of the current object, which may vary as this method is inherited by subclasses. Whereas with a global variable it would always be the same variable.
I'd like to test some code with OCMock.
The innards of the code are calling [NSObject isKindOfClass] on the mock object I'm providing to the code, like so:
if ([object isKindOfClass:[FancyClass class]]) { ...}
However, when I provide an OCMockObject-based mock created like this:
mock = [OCMockObject mockForClass:[FancyClass class]];
it appears that it does not pass the isKindOfClass test.
Any suggestions?
The general rule is that if you're calling isKindOfClass: and you're not passing one of the plist classes (e.g., NSString or NSNumber), You're Doing It Wrong.
If the method does two or more different things depending on which class its argument is, rend it into multiple methods, and test each method separately.
If the method does only one thing, but has to interact with the object differently depending on which class it is, then:
Make a protocol. (Protocols in Obj-C are called “interfaces” in some other OO languages, such as Java.)
Make the many classes all conform to the protocol. If necessary, use categories to add the necessary methods from outside.
Make the method under test check for conformance to the protocol, in place of the current isKindOfClass: check.
Make the method under test use the methods in the protocol.
What about:
[[[mock stub] andReturnValue:OCMOCK_VALUE((BOOL) {YES})] isKindOfClass:[FancyClass class]];