I have a custom UISplitViewController, created so I can present a login screen to the user. In this controller I also have a logout method.
The logout button is in the navigation bar of the MasterViewController. When the user clicks logout, I am trying to call the UISplitViewControllers logoutUser method. First I tried:
[self.splitViewController logoutUser:self];
This gave errors when trying to compile:
No visible #interface for 'UISplitViewController' declares the selector 'logoutUser:'
I then commented out the offending line and added the following if, checking to see if indeed my UISplitViewController responds to the selector.
if([self.splitViewController respondsToSelector:#selector(logoutUser:)]){
// [self.splitViewController logoutUser:self];
NSLog(#"Selector");
}else{
NSLog(#"No Selector");
}
In the log when running I get Selector. uncommenting the [self.splitViewController logoutUser:self] I get the same error.
I tried to clean the build and rebuild but it still gives this error. How cna I resolve this issue?
Thanks,
Bruce
It seems that self.splitViewController is of the base splitViewController and the compiler is not able to find the logoutUser method. However, at runtime the splitViewController can respond to the method.
As you said your splitViewController is custom, try casting to the custom controller:
[(yourCustomViewController *)self.splitViewController logoutUser:self];
Any message can be sent to any object in Objective-C, as long as the method is declared somewhere in the current scope (i.e. it is declared in some class in some header that is imported).
There could be two problems you are referring to:
You did not import a header that contains the method. (The class it's declared in doesn't even have to be the same as the class you're calling it on now; it just has to be declared somewhere.) In this case, you will get a warning that the method is not found, and it will assume that the method returns type id. You can fix this by importing the header of your custom view controller.
Since self.splitViewController is type UISplitViewController *, and logoutUser: is not a method of UISplitViewController, you may get a warning (not error) that it may not respond to that method. This is a result of static type checking because UISplitViewController * is a concrete type. You can fix this by either
Casting it to a type that does support that method, as Enrique's answer suggests; or
Casting it to type id so it does not do static type checking, e.g.
[(id)self.splitViewController logoutUser:self];
As commented above, I found the answer:
[self.splitViewController performSelector:#selector(logoutUser:) withObject:self];
Related
I am getting this error when I load a new tableview onto my navigational stack.
All of the data displays in the table that I am parsing onto it however once that has finished the app stops working and I get this error.
Just wondering if anyone knows what the problem might be? or how I might be able to debug it?
If you need more code let me know I just don't know what to provide because I'm not sure what the error refers too.
-[VehicleResultViewController stopAnimating]: unrecognized selector sent to instance 0x6a2a680
You need to post more code.
In general, an unrecognized selector error occurs when you try to invoke a method on a class that does not have the method implemented.
Is VehicleResultViewController a UITableViewController/UIViewController? Have you added the stopAnimating method? UIViewController and it's subclass, UITableViewController do not have a stopAnimating method in their default implementation.
If it's a UITableViewController or a UIViewController and you haven't added a stopAnimating method, then you're calling a method that VehicleResultViewController does not have hence the crash.
It's really hard to answer your question more accurately until you:
Post code for where you call the method
Post the header file for VehicleResultViewController so we can see what kind of class is it (or you could just tell us).
It could also be (and more probably is) that you have a UIActivityIndicatorView in your code which you want to stop spinning. In that case, are you sure it's named 'vehicleResultViewController'? Whatever your UIActivityIndicatorView is named, try calling:
[whatever_your_activity_indicator_view_is_named stopAnimating];
I'm trying to debug a problem I posted here: https://stackoverflow.com/questions/6852561/delegation-question-method-at-top-level-view. Basically it's a class at the lower level that does not inherit directly from a method at the top level, my coworker had each class hold a reference to another class, to another class, to another class, so that way the bottom level class could call that method from the MainView class. The MainView class also does extra functionality when that method is performed such as, creating the new view, adding buttons to the appropriate toolbars, etc.
Before he was adding all views at once in an NSArray and hiding them and showing them when needed based on a segment control. I fixed that and added the views programmatically only when needed. It works, except for the ability to call the function at the MainView level. The assignments are still there such as
self.newViewController.ParentVC = self;
where newViewController is the lower level viewController I add to my subView. The ParentVC is of my current controller object type. When I set a break point, I see the memory value of self, but when I check the newViewController's ParentVC value in the debugger, it keeps having 0x0 value. I'm not sure why it's not getting set anymore and what the problem would be. Any thoughts? Thanks.
try tracing just past the assignment you mention and type the following in your debug console:
po [[self newViewController] ParentVC]
What does that print?
My understanding about passing data back to a delegate completely revolves around making a new view controller and having it conform to a protocol.
I am trying to get a time input back from a UIDatePicker set with the UIDatePickerModeCountDownTimer mode and I am running into issues.
Inside of Main1.m I create a UIActionSheet *action, and set everything up so that it presents itself with a UIDatePicker on a click. Inside of Main.m I also say:
main.delegate = self;
If this were not a UIActionSheet, I would make a protocol reference inside the new ViewController and then have the new vc pass data to a method that Main has, but I can't do that with a UIActionSheet!!
What am I missing? I assume there is something inherently different about Action Sheets, ut I can't figure it out.
Thanks for your help!!!
EDIT:
Sorry! I was giving a generic name to my view controller. It isn't actually Main.m, its FirstViewController.h/m
I didn't realize that my generic reference was getting mixed up with the Main.m file that is completely different than a vc.
I don't exactly understand why you're putting your delegate assignment in Main.m. I assume that you're setting up your UIActionSheet in a ViewController, and launching it from there. In this case, your ViewController is your delegate object. So you need to make sure that your ViewController implements the UIActionSheetDelegate. ie:
#interface SomeController : UIViewController <UIActionSheetDelegate>
Then you simply implement the required methods of that delegate in your view controller class, and that should do it. If I'm missing something about how you're implementing this, then you need to provide more code examples to examine.
A description of the problem is as follows:
I have a view, say, view A. To enter certain data, I have an alert,with a text field inside it, which pops up. Once the user enters data into the text field, i have an alertView:didDismissWithButtonIndex: function as follows :
- (void)alertView:(UIAlertView *)alertView:didDismissWithButtonIndex:(NSInteger)buttonIndex {
[ amountEntered resignFirstResponder]; //dismiss keyboard
if (buttonIndex == 1) { //OK clicked, do something
if(lblShowTypedText.text)
data.investmentAmount = lblShowTypedText.text ;
[myTable reloadData];
}
}
Then I have a submit button on my View A, which when clicked pops back to the previous view. Here is where my app crashes. There is no message in the console, however after many runs, I got one message like this:
* -[NSCFType alertView:didDismissWithButtonIndex:]: unrecognized selector sent to instance 0x3c4dce0
2010-06-24 15:33:22.970 BankingAppln[2895:207] CoreAnimation: ignoring exception: * -[NSCFType alertView:didDismissWithButtonIndex:]: unrecognized selector sent to instance 0x3c4dce0
Thus i have narrowed down the problem to the alertView:didDismissWithButtonIndex: function. If I do not call the alert, but directly pop back to the previous view, everything is fine.
I must be doing something wrong in my alertView:didDismissWithButtonIndex: function.
Pls help!!
A few things to check:
You set the delegate of the AlertView to the right class (View A)?
Your class (View A) implements the UIAlertViewDelegate protocol.
Probably not, but you never know: You're classname is not equal to a name in apple's private api (don't laugh, happened to me a week ago, costed me 2 hours to figure out)?
EDIT:
Another thing to check:
Your delegate method has the right return type (I think it's "void" in that case)?
Do you really have this method, alertView:didDismissWithButtonIndex:, in your class? and post the code when you call it as well
You need to post where you call the method..but from the error message you gave, the problem is you are calling your method incorrectly.
if it is a method you defined yourself with the implementation above use
[self alertView:myAlertView didDismissWithButtonIndex:myIndex];
also, in your declaration, you have a semicolon after the parameter alertView and you just need a space.
I faced a similar problem and it turns out that with Automatic Reference Counting in place, I needed to keep a reference to the popup around as a property so that it would not be reference collected. That much was fine but I got overzealous and started doing stuff like popup = nil; explicitly and that got me into trouble because some of the delegate methods for the popup were called after I had nil'ed out the reference that I was holding onto and now this popup was not around anymore and the framework crashed due to this little fact.
[__NSCFString alertView:didDismissWithButtonIndex:]: unrecognized selector sent to instance 0x9117c0
So I decided to simply keep allocating a new popup when it was needed and not explicitly nil'ing out the older references. This fixed the issue for me.
I have a modal view controller that creates core data changes in it's own context, and when I click done, it saves the changes (that dispatches the merge changes notification), notifies the delegate and dismisses.
My problem is that I need the delegate to receive the message after my main context has merged with the changes of the editing context. I want the delegate call to take place on the next run loop but I'm having problems with object lifetimes. I've thought of the following:
Make call to [delegate performSelector:withObject:afterDelay:] however it seems that that message is not recognised. My delegate conforms to the NSObject protocol but that doesn't include the perform selector with delay.
Create a method in my view controller: informDelegateWithObject: that calls the delegate method, and call that method after a delay. I.e. [self performSelector:#selector(informDelegateWithObject:) withObject:.. afterDelay:..]. This could work, however, as my view controller is being dismissed, if the delay is several seconds then it would have been released from memory and wouldn't that cause a crash when it comes to invoking?
Create an instance of NSInvocation. I have thought about this, however, what is the lifetime of this object? If I create it using [NSInvocation invocationWithMethodSignature:] then wouldn't the NSInvocation object be autoreleased, and not be around for the next run loop? Let alone several seconds. And as my modal view controller is being dismissed and released, I can't store the invocation object in my view controller.
Any suggestions?
You should merge contexts into the delegate.
Say that you press Save into you modal controller: you will send a myViewController:didFinishSaving: to the delegate.
This delegate into myViewController:didFinishSaving: implementation will save, merge and dismiss the modal view controller.
I hope I have understood your problem.
Bye! :)
You might look at Apple's Core Data Books tutorial which works along the lines that muccy describes. Saving happens after the modal view is dismissed and control is returned to the parent view controller. The parent contains the update code and fires notifications required to merge changes (whether that happens in the delegate or elsewhere).
To question #1: performSelector:withObject:afterDelay: is defined in the NSObject class, not the NSObject protocol. Any object you are using is probably an instance of NSObject. You are probably referring to a compiler warning resulting from static type checking. (Technically, it's possible for an object that conforms to the NSObject protocol to not be an NSObject; NSProxy is one example. But any object you normally use will be an NSObject.) You can ignore this warning (in Objective-C, you can try to send any message to any object). Or, if you want, you can cast it to either id (which allows you to send any message without any warnings) or NSObject *.
To question #2: "if the delay is several seconds then it would have been released from memory" No, the documentation for performSelector:withObject:afterDelay: says "This method retains the receiver and the anArgument parameter until after the selector is performed."
You can also declare your delegate like this:
NSObject <MyClassDelegateProtocol> *delegate;
Then your delegate will also be an NSObject that conforms to your protocol.