Is it possible to initialize a property in a category before any category method is called? - objective-c

Is it possible to initialize a property in a category?
For example, if I have a mutable array property called nameList in a class. Is it possible to have a category created for this class to add an object to the array property before any of the category method is called?

If I understand you correctly, and others are interpreting your question differently, what you have is:
A class with a property
A category on that class
And you want to call a particular method automatically before any category method is called on a given instance, that method would "initialise" the category methods by modifying the property.
In other words you want the equivalent of a subclass with its init method, but using a category.
If my understanding is correct then the answer is no, there is no such thing as a category initializer. So redesign your model not to require it, which may be to just use a subclass - as that provides the behaviour you are after.
The long answer is you could have all the category methods perform a check, say by examining the property you intend to change to see if you have. If examining the property won't determine if an object has been "category initialized" then you might use an associated object (look in Apple's runtime documentation), or some other method, to record that fact.
HTH
Addendum: An even longer/more complex solution...
GCC & Clang both support a function (not method) attribute constructor which marks a function to be called at load time, the function takes no parameters and returns nothing. So for example, assume you have a class Something and a category More, then in the category implementation file, typically called Something+More.m, you can write:
__attribute__((constructor)) static void initializeSomethingMore(void)
{
// do stuff
}
(The static stops the symbol initializeSomethingMore being globally visible, you neither want to pollute the global name space or have accidental calls to this function - so you hide it.)
This function will be called automatically, much like a the standard class + (void) initialize method. What you can then do using the Objective-C runtime functions is replace the designated initializer instance methods of the class Something with your own implementations. These should first call the original implementation and then an initialize your category before returning the object. In outline you define a method like:
- (id) categoryVersionOfInit
{
self = [self categoryVersionOfInit]; // NOT a mistake, see text!
if (self)
{
// init category
}
return self;
}
and then in initializeSomethingMore switch the implementations of init and categoryVersionOfInit - so any call of init on an instance of Something actually calls categoryVersionOfInit. Now you see the reason for the apparently self-recursive call in categoryVersionOfInit - by the time it is called the implementations have been switched so the call invokes the original implementation of init... (If you're crosseyed at this point just draw a picture!)
Using this technique you can "inject" category initialization code into a class. Note that the exact point at which your initializeSomethingMore function is called is not defined, so for example you cannot assume it will be called before or after any methods your target class uses for initialization (+ initialize, + load or its own constructor functions).

Sure, it possible through objc/runtime and objc_getAssociatedObject/objc_setAssociatedObject
check this answer

No it's not possible in objective c.Category is the way to add only method to an existing class you can not add properties in to this.
Read this
Why can't I #synthesize accessors in a category?

Related

'does not have member' when calling objective C setter method from Swift

After importing the objective C robbiehanson/XMPPFramework into a swift project (setting up build setting, bridging header, etc). I am able to call normal methods in the imported classes and set properties directly.
However, certain instance methods that set properties cause immediate errors as if they don't exist in the instances I'm calling them on. For example:
- (void)setMyJID:(XMPPJID *)newMyJID
{
[self setMyJID_setByClient:newMyJID];
}
Or even the setMyJID_setByClient:newMyJID method which actually does the setting.
In two separate objective c example projects I have looked at, the setMyJID method is being called from other classes. However, while I am able to call other instance methods on the class, I can't call this one. Since I am not very familiar with objective c, I though this might be because it wasn't declared in the header file, causing some swift specific problem, but attempts to add a declaration for it did not help.
I am able to set the relevant property directly, but this is not only undesirable, I also would like to understand why I am not able to call certain methods.
I am attempting to make the call on an instance of the XMPPStream class like this
//This shows immediate error: XMPPStream does not have a member named 'setMyJID'
stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
// This works perfectly
stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))
Any help would be appreciated.
In the XMPPStream class, myJID is declared as follows:
#property (readwrite, copy) XMPPJID *myJID;
In Objective-C, this means that there are actually two methods on the XMPPStream class that conform to the following signatures:
- (XMPPJID *)myJID;
- (void)setMyJID:(XMPPJID *)myJID;
So, from Objective-C code, you can call them like any other method. However, as you know, you also have the option of using the syntactic sugar in the language known as "dot notation":
// getter with dot notation
XMPPJID *jid = stream.myJID;
// setter with dot notation
stream.myJID = jid;
However, in Objective-C, these dot notation expressions are directly translated into calls to the getter and setter. They're just there to look nice.
Things are different in Swift. When you have a property, like this one:
var myJID: XMPPJID
this does not mean that there exist separate getter and setter methods, like you might be imagining:
func myJID() -> XMPPJID {}
func setMyJID(jid: XMPPJID) {}
In Swift, you must access properties using dot syntax.
Knowing this, your problem becomes obvious. When you tried:
stream.setMyJID(XMPPJID.jidWithString(someXMPPAddress)
Swift tried to run the instance method setMyJID of stream, and found, rightly, that it did not exist! This, of course:
stream.myJID = (XMPPJID.jidWithString(someXMPPAddress))
works perfectly, because you're setting a property as Swift requires.
As an educational aside, you may sometimes see cases where, when accessing Objective-C properties from Swift, you not only can, but must use the getter and setter methods - dot notation won't even work! This seems totally counterintuitive, but there's a good reason for why this happens. One example of this that I can think of off the top of my head is the verbosely-named UIView property translatesAutoresizingMaskIntoConstraints, used for view layout. If you try to use it in Swift, like so:
// Set translatesAutoresizingMaskIntoConstraints to false on self
translatesAutoresizingMaskIntoConstraints = false
you would get a compilation error! Specifically,
Cannot assign to 'translatesAutoresizingMaskIntoConstraints' in 'self'
Why? The answer lies in the UIView headers:
- (BOOL)translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0); // Default YES
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0);
It turns out that this "property," like many others in the Cocoa frameworks, is actually just a pair of methods that look like property accessors. Because of how Objective-C translates dot notation into method calls, you'd never notice before. Now, though, Swift is stricter – to get and set this "property," you must call the appropriate methods.

Self contains Self property [duplicate]

This question already has answers here:
What is the purpose of the -self method in NSObject-conformant classes?
(3 answers)
Closed 8 years ago.
I was messing around with Objective-C and I stumbled upon something strange. The following code compiles and works the way I want it to.
self.scrollView.delegate = self.self.self.self.self;
// equivalent to = self;
Why does this compile? Is it the case that self is a property of an object. If so, I have never seen self declared as a property. I thought self referred to the instance of the class you are creating.
Let me turn this around Why shoudn't it compile nor work as expected?
self is a property of NSObject. It always points to the object itself. Every object inheriting from NSObject has it.
As you say, self refers to the instance. Well, it is not only valid in the context of creating instances. It is always there. And it is very helpful.
[self myProperty] or self.myProperty refers explicitely (laugh more or less explicitely but it does) to the getter (or the setter) of the property myProperty while just typing myProperty within a method refers directly to the property without passing the getter.
Another example is someOjbect.delegate = self; or so.
So, as self alsways refers to an object, to the very object, it has a self property that refers to the very object which has a self property ...
BTW, classes are objects in Objective-C that inherit from Class. In the context of a class, i.e. in class methods, it refers to the class object of the very class. You can play the same game there. If you start off with an instance, then you can play the game with the class property.
self.class.class.class == [self class].self.class.self
should evaluate to YES. (Well, I never tried that myself. If you actually try it and find this wrong, then please let me know)
self is a method in the NSObject protocol. It returns the object it is called on, it is rather pointless.
This is distinct from the local variable self, which within a method refers to the object the method was called on.
Both the method and the local variable apply to class objects as well as standard instances, so a class method has a self local variable and a class object a self method.

Objective-c interfaces and implementations

Is interface to an implementation is just like a function declaration (in a header file) to a function definition?
What if I didn't list in the interface all methods that are already implemented? What about instance variables as well?
Yes interface and implementation could be considered analogous to header and definition.
If you don't list some of the implemented methods, you won't be able to used them from other classes. Also if they are not defined in the #interface section, the compiler will complain if you try to use a function that has been implemented after the call
#implementation
- (void) functionA
{
[self functionB]; // error, because 'so far' functionB has not been defined
}
- (void) functionB
{
}
EDIT: See Martin's comment below. END EDIT
If you don't define instance variables, and you use them you'll get errors. Any variable that you use MUST be defined, either locally or in the class.
Answers to your questions:
Is interface to an implementation is just like a function declaration (in a header file) to a function definition?
YES
What if I didn't list in the interface all methods that are already implemented? What about instance variables as well?
These methods will be taken as private methods and variables which will be accessible in that particular class.
variables declared in your interface, as in 1., are visible in other classes that instantiate objects of MyClass. The variable declared in 2. will only be visible inside of MyClass. Here is something you should read: http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/
http://iosmadesimple.blogspot.in/2012/11/interface-and-implementation.html
I guess all these will help you in understanding these things in deeper.

objective C underscore property vs self

I'm was playing around with the standard sample split view that gets created when you select a split view application in Xcode, and after adding a few fields i needed to add a few fields to display them in the detail view.
and something interesting happend
in the original sample, the master view sets a "detailItem" property in the detail view and the detail view displays it.
- (void)setDetailItem:(id) newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
i understand what that does and all, so while i was playing around with it. i thought it would be the same if instead of _detailItem i used self.detailItem, since it's a property of the class.
however, when i used
self.detailItem != newDetailItem
i actually got stuck in a loop where this method is constantly called and i cant do anything else in the simulator.
my question is, whats the actual difference between the underscore variables(ivar?) and the properties?
i read some posts here it seems to be just some objective C convention, but it actually made some difference.
_property means you are directly accessing the property.
self.property means you are using accessors.
In your case, in the setter method you are calling it, creating a recursive call.
In the course of your experiment, you've set up an endless loop which is why the simulator goes non-responsive.
Calling self.detailItem within the scope of setDetailItem: calls setDetailItem: recursively since your class implements a custom setter method for the property detailItem.
I would refer you to the Apple documentation on declared properties for the scoop on properties, ivars, etc; but briefly, declared properties are a simplified way of providing accessor methods for your class. Rather than having to write your own accessor methods (as we had to do before Objective-C 2.0) they are now generated for you through the property syntax.
The properties are basically a way of the compiler to generate a setter and getter for a given instance variable.
So when you use something like:
id detailItem = self.detailItem;
what you are doing under the hood is:
id detailItem = [self detailItem];
Same for:
self.detailItem = otherDetailItem;
would be:
[self setDetailItem:otherDetailItem];
So when you write the setter yourself.. you get in an infinite loop since you access the method itself in itself.
You can freely make use of the 'self.' notation in your class, just not when you're overriding the setter or accessor because of the mechanism I described above.
Cases in a class where I use the . notation over simply accessing the ivar is when I change the value, you never know inside your class what needs to happen when you change the value. do you have something in terms of a status that should notify some delegate that a status changed? Usually this is not the case, however, just by using the . notation you are making sure that in the future you won't have to refactor some code if you did decide to do some magic in your setter method.
I'll make an example (without ARC enabled):
#property (nonatomic, retain) NSNumber* number;
If you don't synthesize it, you can access it this way:
self.number= [NSNumber numberWithBool: YES];
This case the number is retained.If instead you synthesize it and don't use the property:
#synthesize number;
Later in the file:
number=[NSNUmber numberWithBool: YES];
You haven't used the property, so the number is not retained.That makes a relevant difference between using accessors and synthesized properties.

Automatically call class method in objective c

my situation:
a dashboard controller who register the widgets inside it and automatically builds the view.
widget classes that are going to populate the dashboard, who adopt <widget> protocol(some informal methods required), and need to be registered in the dashboard class so the dashboard singleton knows who wants to be in.
the dashboard class has +(void)register:(Class<widget>)w; that simply register the classes who wants to be in in an NSArray
I need each widget class to call automatically that method.in c++ i used to make a boolean static variable that i would initialize with that method.
Language = objective-c
The objective-c runtime will call two methods when a class is first loaded. +load and +initialize. I believe what you want could be done by calling [self register] from within +initialize.
A way you could do it is with the runtime:
Grab a list of all the classes known to the runtime.
Iterate the list, and check to see if the class conforms to your widget protocol
If it does conform to the protocol, invoke the +register: method or whatever
Regarding step #2, you can't use the +conformsToProtocol: method, because one of the classes you'll iterate is the NSZombie class, which triggers an exception whenever you invoke a method on it. Thus, you'd want to use the class_conformsToProtocol() runtime function instead.