"'Objects' may not respond to 'functions'" warnings - objective-c

for the last couple of weeks I've finally gotten into Obj-C from regular C and have started my first app. I've watched tutorials and read through a book along with a lot of webpages, but I know I've only just begun. Anyway, for most of the night and this morning, I've been trying to get this code to work, and now that it will compile, I have a few warnings. I've searched and found similar problems with solutions, but still no dice. What I'm trying to do is put an array made from a txt document into the popup list in a combo box.
AwesomeBoxList.h:
#import <Cocoa/Cocoa.h>
#interface AwesomeBoxList : NSObject
{
IBOutlet NSComboBox *ComboBoz;
}
-(NSArray *) getStringzFromTxtz;
- (void) awesomeBoxList;
#end
AwesomeBoxList.m:
#import "AwesomeBoxList.h"
#implementation AwesomeBoxList
-(NSArray *)getStringzFromTxtz
{
...
return combind;
}
- (void) awesomeBoxList
{
[ComboBoz setUsesDataSource:YES];
[ComboBoz setDataSource:
[ComboBoz getStringzFromTxtz]: //'NSComboBox' may not respond to 'getStringzFromTxtz'
[ComboBoz comboBox:(NSComboBox *)ComboBoz objectValueForItemAtIndex:
[ComboBoz numberOfItemsInComboBox:(NSComboBox *)ComboBoz]]];
/*'NSComboBox' may not respond to '-numberOfItemsInComboBox:'
'NSComboBox' may not respond to '-comboBox:objectValueForItemAtIndex:'
'NSComboBox' may not respond to '-setDataSource:'
*/
}
#end
So, with all of these errors and my still shallow knowledge of Obj-C, I must be making some sort of n00b mistake.
Thanks for the help.

There does seem to be a generally large amount of confusion here, mostly manifested in your last
(4) line(s) of code. You are aware that the ':' symbol is used to pass arguments to methods, not terminate a line? You are essentially daisy chaining those last 4 lines together in a way that makes no sense. As for the specific warnings, getStringzFromTxtz is a method you defined on AwesomeBoxList, not a method of NSComboBox. numberOfItemsInComboBox: and comboBox:objectValueForItemAtIndex: are NSComboBoxDataSource Protocol methods, intended to be implemented by your class on behalf of an NSComboBox, not NSComboBox methods. I would recommend doing a bit of reading on Delegates and Protocols.
To elaborate:
In order for your AwesomeBoxList class to use an NSComboBox, it needs to provide information to the combo box that the combo box needs to know. In the Apple Universe, situations like this are typically handled with the Delegate Design Pattern. Specifically, the combo box needs to know how many items it will be showing as well as the object representation for each of the shown items. The combo box declares the interface for doing this in the NSComboBoxDataSource Protocol. By providing this info, you are acting as the datasource for the combo box. You can tell the combo box that it should defer to your class for its data by setting yourself as its dataSource property in Interface Builder or with a call to
[ComboBoz setDataSource:self];
from somewhere in your AwesomeBoxList's implementation. That will ensure that the combo box calls methods in your class to populate itself with info. There are two methods specifically that your AwesomeBoxList class should implement, and which will be called by the combo box:
- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index {
switch (index) {
// Return some object that is represented by index in the combo box
}
}
- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox {
// return theNumberOfItemsInYourComboBox;
}
Providing a meaningful implementation is all you need to do to populate your combo box with data. I don't know the specifics of what you want here, but that is the pattern you want to follow. Hope that helps a bit more.

Well, the getStringzFromTxtz won't work being sent to an NSComboBox instance as that method is declared and defined in your AwesomeBoxList class. This method will not be found at runtime.
Also, I think you may need to get your head around delegates and data sources - the other methods are part of the NSComboBoxDataSource protocol. Check out the Combo Box Programming Guide in the docs for examples.

Those methods do not exist. See the NSComboBox documentation for more information.
Instead of:
[ComboBoz
comboBox:(NSComboBox *)ComboBoz
objectValueForItemAtIndex:[ComboBoz numberOfItemsInComboBox:(NSComboBox *)ComboBoz]];
Try:
[[comboBox objectValues] objectAtIndex:[comboBox numberOfItems] - 1];
Also, note that the platform convention is to use a lower-case letter at the beginning of an ivar.

Related

Removing an action from a subclass

My NSDocument subclass implements selectAll:. Only problem is, I'm using NSTableView, and it also implements selectAll:. However, the selectAll: action in NSTableView doesn't do what I want, and it does prevent the selectAll: method in my Document class from ever being reached in the responder chain.
I already have a subclass of NSTableView, and after poking around a bit I got things working the way I want by adding a respondsToSelector: method to my NSTableView subclass which lies to the runtime by telling it there is no selectAll: action:
-(BOOL)respondsToSelector:(SEL)targetSelector
{
if (targetSelector == #selector(selectAll:)) {
return FALSE; // we don't want tableView's implementation of selectAll
}
return [super respondsToSelector:targetSelector];
}
This seems to work fine, allowing the selectAll: method in my document subclass to do its thing. But this solution leaves me a bit uneasy. What about other action methods I have implemented in this subclass? Do I need to manually check and return true for each of them? I do have two actions defined in this subclass, moveLeft: and moveRight:, and they seem to work, even though I am not handling them in respondsToSelector:. So my question is, am I doing this correctly, or is there something I am missing? Or perhaps there is some entirely different way to do this properly?
By the way, I got the idea of overriding respondsToSelector from this post on the OmniGroup forum:
http://mac-os-x.10953.n7.nabble.com/Removing-an-action-from-a-subclass-td27045.html
Sending a message to super affects which implementation of that method we use. It doesn't change who self is.
So let's try to imagine how respondsToSelector: works. Given a selector mySelector, it probably introspects every class up the superclass chain, starting with [self class], to see whether it actually implements mySelector.
Now then, let's say your subclass is called MyTableView. When MyTableView says
[super respondsToSelector:targetSelector]
what happens? The runtime will look up the superclass chain for another implementation of respondsToSelector:, and eventually will find NSObject's original implementation. What does that implementation do? Well, we just answered that: it starts the search for an implementation of targetSelector in [self class]. That's still the MyTableView class! So if you have defined moveLeft: in MyTableView, respondsToSelector: will find it and will return YES for moveLeft:, exactly as you hope and expect.
Thus, to generalize, the only selector for which this search has been perverted is the search for selectAll: - exactly as you hope and expect. So I think you can relax and believe that what you're doing is not only acceptable and workable but the normal solution to the problem you originally posed.
You might also like to look at the Message Forwarding chapter of Apple's Objective-C Runtime Programming Guide.

Delegate method naming convention if class name is long?

I am having a problem with method naming. I want to follow the method naming format as seen in UITableViewDataSource:
- (int)numberOfSectionsInTableView:(UITableView *)tableView;
but my class name is much longer than 'UITableView' -- it's XYPagedContentScrollView where XY is the class prefix for the project. I have a delegate protocol:
#protocol XYPagedContentScrollViewDelegate <NSObject>
- (CGFloat)defaultPageHeightForPagedContentScrollView:(XYPagedContentScrollView *)pagedContentScrollView;
#end
and this method name looks ridiculously long. I know it is not a strict rule, but I just wonder is there any way to deal with the long name and still conform to Apple's naming convention? Something like:
#protocol XYPagedContentScrollViewDelegate <NSObject>
- (CGFloat)defaultPageHeightForPagedContentScrollView:(XYPagedContentScrollView *)pagedContentSV;
#end
or even:
#protocol XYPagedContentScrollViewDelegate <NSObject>
- (CGFloat)defaultPageHeightForPCScrollView:(XYPagedContentScrollView *)pagedContentSV;
#end
Can anyone help?
The length of a method is not limited by the language in any way, so feel free to make it as long as you want.
It may look bad at first, but the more verbose it is, the less chance you have of conflicts later down the line.
My rule is, if it looks like it could conflict with another method (especially if it's a delegate method), it needs a longer name.
Now, with that said, don't make names ridiculously long,so that they are 100s of characters in length, like this:
-(void) fooBarViewController:(FooBarViewController *) controller didTapRightMarginAtPoint:(CGPoint point) ofPage:(NSUInteger) page lengthHeld:(NSTimeInterval) tapLength fingers:(NSUInteger) fingerCount;
Instead, consider wrapping it in a dictionary of the event details:
-(void fooBarViewController:(FooBarViewController *) controller didTapMargin:(NSDictionary *) eventDetails;
/* eventDetails should contain the following information:
which margin?
touch location
page index
touch length
finger count
*/
This simplifies the method signature, and allows the receiver to only pull out the variables they need.
Personally, I would go with the long form: that's what autocomplete is for. That being said, if you do want to shorten it, I would drop adjectives. Something like:
#protocol XYPagedContentScrollViewDelegate <NSObject>
- (CGFloat)defaultPageHeightForScrollView:(XYPagedContentScrollView *)pagedContentSV;
#end
I wouldn't worry about name conflicts with delegate methods because if an object is ever the delegate of two different object with the same delegate methods, then it will use the passed (i.e. calling) object to distinguish them. (For example, If you're the delegate of two scroll views, you just test the passed view to find which scroll view it's talking about.)

multiple delegates in objective-c

i have been working on moving one of my apps away from the "shared appdelegate" process which seems to be frowned up, despite its over whelming use. i have been attempting to setup protocol methods for what i want to do but am having zero luck. my question is, can you even have lets say a single viewcontroller send delegate requests to multiple classes? from what im finding out it doesn't seem like you can. which doesn't make sense because i thought that was the whole point of delegates and protocols with mvc. now just to clarify, i know you can have a single viewcontroller act as the delegate for multiple other viewcontrollers. but that's not what i am asking. for a simple example, lets say you have apples flip-utility template. the "done" button just calls a delegate method to the mainvc to dismiss it. now lets say we added a new class called...
#interface NewClass : NSObject <TheOtherDelegate>
and it had a delegate method...
- (void)doSomething
{
NSLog(#"The Delegate did something...");
}
can we have a button on the flipsideviewcontroller, that we wanted to call that delegate method, but still keep the "done" button call to the delegate method on the mainviewcontroller that dismisses it?
that being said, i put together a quicky project just to see if it would work and it doesn't. i came across an "answer" that says you have to instantiate the class first you want to be the delegate...
NewClass *myDelegate = [NewClass alloc] init]
[fillInMethodHere setDelegate:myDelegate];
not sure why it got a correct answer check, because needless to say it doesn't work. is there something i am missing? i scoured ib to see if there is some "delegate" connection somewhere but i couldn't find anything.
on a side note, as i was working in my working project, i read a suggestion about removing the #import and adding #class. again, that broke all kinds of things. the strange thing is before doing that, what i had so far was working and building fine. when i removed the new #class and un-commented the #import. xcode all of a sudden gave me an error "cannot find protocol deceleration for..." but yet, it worked seconds earlier. i would up having to remove the protocol code and re-add it for it to work again. very starge.
any help would be appreciated. everything iv read in docs, google, stack, etc that say something should work, don't in an actual project.
A "delegate" isn't some fancy object. It's simply a synthesized property of type id called delegate. If you wanted to, you could have an arbitrary number of properties that all conformed to the same protocol. Then when you wanted to issue a callback, you would just address all of them:
[self.mydelegateA doSomething];
[self.mydelegateB doSomething];
etc.
You could also have an NSMutableArray property that you could add objects to, and then use [self.myMutableArrayOfDelegates makeObjectsPerformSelector:#selector(doSomething)].
Finally, there's always the route of NSNotificationCenter (not to be confused with push notifications) is a class that provides an inter-object messaging system. Many objects can register for a message that any other object can send.
Please see the Apple's documentation for more information. Click Here.
Regardless of the fact that this is OS X documentation, it's still quite good at explaining things visually: click here.
Here's an example of simply changing the name of the delegate property: click here
And here's an example of adding another protocol and a second delegate: click here
Finally, here's an example that builds on the previous two and has a third delegate that also conforms to the same protocol: click here

Why cant I see all available methods or properties present in a Class in XCode?

I am noob to XCode and Obj-C world, so pardon me for my naive question.
Following a tutorial, I was writing a basic program in Cocos2D that would accept touch input.
And one of the task was to add implement ccTouchBegan method, but that would not show up in XCode's code sense.
I wanted to implement this method
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
but I would find only this one (related to touch began)
-(BOOL) ccTouchesBeganWithEvent:(*)event
Now that I a noob, how do I explore list of all available methods and properties for a particular Class?
The image shows list of available methods that starts with ccT. ccTouchBegan and ccTouchEnded showed up because I have implemented them already. Else, they would not show just like ccTouchCancelled and ccTouchMoved events didn't show up.
How do I see all available methods & properties of a Class or Object?
To see all the available methods & properties just press Ctrl+Space
Option+Click on the object (in this case, that would be the delegate name in the header file between the < >). A small help popup will appear. Click the blue text inside the popup and the Organizer window will open at the documentation for the Class. The Documentation has all methods and properties you can use.
Just press Backspace 3 times to delete the ccT you typed in. The list will increase with every character you erase. The full list not only shows methods, as you will see.
Maybe it does not show up because you have already defined it in your code? That would be logical, as double implementation would lead to a compiler error.

Can somebody explain this Objective-C method declaration syntax

I'm working through an iPhone development book* without really knowing Objective C. For the most part I'm able to follow what's going on, but there are a few method declarations like the one below that I'm having a bit of trouble parsing. For example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return [self.controllers count]; //controllers is an instance variable of type NSArray in this class
}
It looks this is a method called numberOfRowsInSection, and it returns an NSInteger, and takes an NSInteger as a parameter which is locally called 'section'. But I don't understand all the references to tableView, or why this takes a parameter when it is not used within the method. Can somebody clarify this? Thanks.
*p. 258, Beginning iPhone 3 Development, by Mark and LaMarche, published by Apress
Update: I was able to find another SO thread that goes into a bit more detail: Method Syntax in Objective C
This is a method called:
tableView:numberOfRowsInSection:
It takes two parameters:
a UITableView*
a NSInteger
The method also takes an implicit self parameter , which is the instance it is called with. As dreamlax notes, it also takes an implicit _cmd, which is the method that currently gets invoked.
As Mark says, it is completely common to not use certain parameters if you are conforming to a certain interface.
This is a method called tableView:rowsInSection: that UITableView specifies for its delegates. The tableView argument is there in case you have one controller in charge of several UITableViews, so that it can tell which one is talking to it. It's also useful if you need to query the UITableView for information in order to decide what you want to do. This is very common in delegate methods.
This method is conforming to the UITableViewDataSource protocol. If you're familiar with C# or Java, a protocol is like an interface.
It's completely legal and not too abnormal for a method conforming to an interface or protocol to ignore some of the arguments.