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

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.

Related

Objective-C message syntax

while learning Objective-C I stumbled across the following code, which I do not understand:
RootViewController *rootViewController = (RootViewController *)[self.navigationController topViewController];
As far as I understand
[self.navigationController topViewController]
is sending the message (calling the method) topViewController to self.navigationController.
Looking in the .h File I only find topViewControllerbeing a property, not a function:
#property(nonatomic,readonly,retain) UIViewController *topViewController; // The top view controller on the stack.
Can somebody explain what is happening there?
Thanks in advance!
Either syntax is fine:
[self.navigationController topViewController]
and:
self.navigationController.topViewController
The latter is calling the property's getter method, which probably looks like this:
- (UIViewController *)topViewController
{
return _topViewController;
}
I would prefer the latter if it's been defined as a #property.
The "dot syntax" is another way of calling a method (only methods that do not have any arguments may be called this way).
So the statement:
[self.navigationController topViewController]
is actually interpreted as:
[[self navigationController] topViewController]
which means:
The message navigationController is sent to the object self.
The message topViewController is sent to the object that was returned by navigationController.
A property itself is just a fancy way of defining methods. A readonly property only provides a getter (foo), a read/write property also provides a setter (setFoo:). By default, the compiler generates these methods to access an also implicitly defined variable _foo.
A property is really a convention that means you have ivars with accessor methods, setters and getters, that meet a standard style and provides additional functionality that is derived from the conventional style.
With Objective-C 2.0 we got synthesized properties. That is the compiler will generate a lot of boilerplate code to make ivars and associated setter and getter methods for you that adhere to conventions and provide most importantly consistent memory management and KVC and KVO. (Google those separately).
It also brought the dot syntax, which is syntactic sugar, in other words the compiler interprets it the same way as corresponding bracket syntax.
Both dot and bracket syntax are transformed the same way by the compiler into the same kinds of calls.
There is no functional difference.

Dot vs arrow notation in Objective-C for non structs

I've seen examples of arrow notation used for structs. In one tutorial, I saw this syntax in a view controller implementation file:
self->webView.canGoBack) backButton.enabled = YES;
I have no idea why they did not use dot notation. No explanation was given. I tried this in a simple project that has a button and text field. Below is what I put in the button press method:
//header file
#property (strong, nonatomic) IBOutlet UITextField *myInputField;
//implementation file
self.myInputField.text = #"another test";
//self->_myInputField.text = #"text field test";
Either line of code works without issue. So why use one of the above lines over the other?
Also, notice that the arrow notation produces _myInputField.text. What is the significance of the underscore?
In Objective-C, objects are also c structs. If you're new to the language, that knowledge will get you in more trouble than it will help. But it helps explain what you're seeing.
An Objective-C property is a helpful construct that creates an ivar in the object (a new field in the class's struct) that defaults to the property name prefixed by an underscore. A property will also create getter and setter methods, e.g. - (UITextFeild *)myInputField and - (void)setMyInfputField.
Dot notation is Objective-C syntactic sugar that calls the Objective-C setter and getter methods. The -> arrow notation is C syntax that will dereference the object's pointer and access the struct field for the object's ivar.
It is important to understand that the dot syntax is actually generating calls to these methods, so you don't try and override those methods and inadvertently include calls to themselves.
The default implementation of a generated method like - (UITextFeild *)myInputField looks something like this
- (UITextFeild *)myInputField {
return self->_myInputField;
}
But Objective-C has yet another syntactic helper allowing you to access _myInputField without writing out self->. So the following implementation is identical.
- (UITextFeild *)myInputField {
return _myInputField;
}
There are some good reasons for using direct ivar access -- the biggest reasons being implementation of custom setters and getters, performance, and careful control over KVO language features. But in modern Objective-C it should be avoided unless you really know what you're doing.
If you want to learn more, read Apple's documentation on Objective-C
self.myInputField.text = #"another test";
That code calls the myInputField getter method. There can be good reason for doing this, so it is usually safest.
self->_myInputField.text = #"text field test";
That code directly accesses the _myInputField instance variable.
The myInputField getter method in this case also accesses the _myInputField instance variable, which is why the two calls seem to do the same thing. But that is just an implementation detail; it is perfectly possible for a getter method to access a differently named instance variable, to perform other actions (side effects), or to access no instance variable at all.

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.

Objective C shenanigans

In my quest to be the grandmaster of Objective C, I keep running into it's subtleties, which I want to share with ya'll and gain an understanding why
1) I have two init methods, the one that is inherited by NSObject for my Objective C class and one is a custom method that I create off my own, let's say
initCustomMethod:(int)par1 argument2:(int)par2;
My Aim is to call initCustomMethod through the provided init method, essentially
-(id)init{
return [self initCustomMethod:1 argument2:3];
}
Naturally, maintaining the order, I have init appearing before initCustomMethod in the .m file. Xcode warns me telling me that the initCustomMethod is not found, I go ahead and shuffle the order and have init appearing after initCustomMethod is declared and there is no such warning message anymore and everything is fine.
I concur that the order is important since it's essentially derived from C, however I am not sure of this. Because, i shuffled the order of some properties and their custom methods, with the properties #synthesize being declared after the custom setter method for a given property, but there was no such error replica.
Can anyone point out the malice here?
Thanks guys!!!
Very cool guys, thanks for helping me out with this. Also, since I have a custom init method, I am initializing the super in this method and using the original init method to call the custom init method.
Anything wrong with this?
Before you reference it anywhere, you should declare initCustomMethod:argument2 in your interface, which would usually be in your header file.
For example, you would usually have a .h file that looks like:
#interface MyClass
{
//instance variables
int anInstanceVariable;
}
// properties
#property (nonatomic, assign) int aProperty;
// methods
-(id)initCustomMethod:(int)par1 argument2:(int)par2;
#end
And if you did this, the order in which you define init and initCustomMethod:argument2: won't matter. This is because the declaration tells the compiler that you are going to define the method, and what it will look like, so it isn't confused when you use it later.
It's a bad idea in Objective-C to use a function or a method before it is either declared or defined. Putting initCustomMethod:argument2: before init means that the former is already defined in the latter. But if you'd just declare it in the header, it wouldn't matter which order they went in.
Add your custom method name in your header file - the compiler just goes through things in order. If you don't have a forward declaration, the compiler won't know what to do with that call. You're going to need to put it in the header if you want other parts of your program to be able to call it anyway.

Passing a value from one object into another with Objective-C

I have a class called GameScene, with is a subclass of a cocos2d Scene.
In there I have two layers. GameLayer and ControlsLayer. You can probably tell already that I want the ControlsLayer to move stuff around in the GameLayer. To be precise, I'm trying to control a cPBody in the GameLayer from the ControlsLayer.
At the moment, I'm trying to route the instructions from the ControlsLayer, back up into the GameScene and then back down into the GameLayer. If that makes sense. Anyway, I can't get it to work. I have a PHP background so I think I'm incorrectly applying my PHP experience to Obj-C.
My thinking is, I should be able to access a property inside a class/object using something like
aThing *someThing = someInstance->aThing;
From the sample code I've been looking at, it looks like this should work. But it doesn't. Here's the code, stripped down to as much as possible http://pastebin.com/d49c9d0be
Rather than knowing how to fix this particular issue, The question is, what don't I understand?
In Objective-C you need to define accessor methods to get at the instance variable, you can't directly access it like that unless you're calling it from the same class type (for instance when you're implementing the NSCopying protocol and need to set private variables, but don't worry about that now).
The easiest way to do that is to define a property in your header using #property(retain) SomeClass *name;, and have Objective-C generate it by putting #synthesize name = instanceVariable; in your implementation. You can then access the variable outside of that class using object.name; or [object name];. For more information take a look in the documentation for properties and Object Oriented programming.
You're not exposing the gameLayer.myBody property in any shape. You'd have to use the #property declaration (assuming objective-c 2.0) (here's an example).
I don't have any PHP background, so I don't know how it may be different in PHP.
The correct way to access a property in an object is as follows:
aThing * someThing = someInstance.aThing; // new style
or
aThing * someThing = [someInstance aThing]; // old style
If you were coding in c, the -> operator would make sense. In objective-c, however, objects are always passed around through pointers. No objective-c variable ever actually holds an object, they just hold pointers to objects. The language designers simply decided to use the [] or . syntax to access members, so that's what we have to do!