I receive the following error when trying to show an ActionSheet...
2012-11-16 04:07:03.878 MKS WebTech[814:c07] -[mksWorkOrderViewController _presentActionSheet:asPopoverFromBarButtonItem:orFromRect:inView:withPreferredArrowDirections:passthroughViews:backgroundStyle:animated:]: unrecognized selector sent to instance 0x75a5950
- (IBAction)ActionClick:(id)sender {
popupSheet = [[UIActionSheet alloc] init];
[popupSheet setDelegate:self];
[popupSheet addButtonWithTitle:#"Contact List"];
[popupSheet addButtonWithTitle:#"Zone Descriptions"];
[popupSheet addButtonWithTitle:#"Zone Testing"];
[popupSheet addButtonWithTitle:#"Panels"];
[popupSheet addButtonWithTitle:#"Time Sheet"];
[popupSheet addButtonWithTitle:#"Inventory"];
[popupSheet addButtonWithTitle:#"Other Appt."];
[popupSheet addButtonWithTitle:#"Alarm History"];
[popupSheet addButtonWithTitle:#"Service History"];
[popupSheet addButtonWithTitle:#"Complete"];
[popupSheet addButtonWithTitle:#"Cancel"];
[popupSheet setCancelButtonIndex:10];
// Prepare your action sheet
[popupSheet showFromBarButtonItem:bntAction animated:NO];
[popupSheet release];
}
The error happen "showFromBarButtonItem:bntAction" I also tried with sender but same result
also the canPerformAction fires with no problem...
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
return YES;
}
I had this problem once, it's not the same case, but for me, this worked:
Go to Interface Builder
Check ALL objects, the problem for me was that I connected an object to a variable that I later deleted, so it didn't exist.
Conclusion: I had connected an object to a variable that doesn't exist.
Otherwise, the code looks fine :)
For anyone else who runs into this in the future (as I just did): the problem is that UIActionSheet walks up the responder chain calling -canPerformAction:#selector(_presentActionSheet:asPopover... etc etc) on each.
So since the controller incorrectly responds YES, the UIActionSheet goes ahead and tries to call that method, an implementation doesn't exist, and you hit the error.
The correct fix is to reimplement your -canPerformAction:withSender: to only return YES to things you actually handle.
Related
I have a few questions regarding MFMessageComposeViewController:
Is there a way to know to whom the user actually sent the SMS to?
Or, at least be able to know to how many numbers the SMS was sent to?
What was the message that was actually sent?
Here is what I have so far, and it works OK. But It seems there is only one delegate, but it's so simple that it's pretty much useless.
- (void)showSMS:(NSArray *)numbers message:(NSString *)message {
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
[messageController setRecipients:numbers];
[messageController setBody:message];
[self presentViewController:messageController animated:YES completion:nil];
}
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult) result {
if (result == MessageComposeResultCancelled) {
NSLog(#"SMS cancelled");
}
else if (result == MessageComposeResultFailed) {
NSLog(#"SMS failed");
}
else if (result == MessageComposeResultSent) {
NSLog(#"SMS sent");
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Thanks.
This isn't possible. The iOS SDK doesn't expose a way to access this.
From Apple's documentation of MFMessageComposeViewController:
Important: The message composition interface itself is not
customizable and must not be modified by your app. In addition, after
presenting the interface, your app is unable to make further changes
to the message content. The user can edit the content using the
interface, but programmatic changes are ignored. Thus, you must set
the values of content fields, if desired, before presenting the
interface.
I've got two labels in a custom UITableViewCell. Their purpose is to indicate the status of a timing operation on the object represented by the cell.
One label displays a countup timer. The other simply blinks "Timer Sleeping." Their visibility is mutually exclusive (if one is visible, the other is not, and vice versa) according to a switch statement to determine which label is currently visible. Each is driven by a dedicated NSTimer.
Everything works fine--until I do a modal segue to another View Controller (for the purpose of adding another entity or other task) and then return to the original VC via Cancel or Savethrough delegation. Then, regardless of which label had been visible (and updating via its timer) prior to the segue, no label is to be seen. The cell appears blank.
The weird thing is that when I segue to yet another VC via a push segue, then return via the "Home" button, the labels appear, blinking or counting up, just as though nothing had happened. The only obvious difference I can see between the two return methods is that the modal is handled via delegation whereas the push is unwound through a nav controller.
Any ideas? I can supply any relevant code, but didn't know where to start and didn't want to paste all of it.
Thanks!
EDIT for clarification in response to question below:
I'm returning via delegation. Here's the code in the modal:
- (IBAction)saveButton:(UIBarButtonItem *)sender
{
if (self.activityField.text.length > 0)
{
if (self.categoryLabel.text.length < 1)
{
// self.thisActivity.category = #"Uncategorized";
// self.thisActivity.name =self.activityField.text;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No category selected"
message:#"Please select a category or Cancel"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
else
{
self.thisCategory.name = self.categoryLabel.text;
self.thisActivity.name = self.activityField.text;
self.thisActivity.category = self.thisCategory.name;
NSLog(#"Category name is %#", self.thisCategory.name);
NSLog(#"Activity name is %#", self.thisActivity.name);
[self.delegate addActivityViewControllerDidSave];
}
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No activity entered"
message:#"Please enter a new activity or Cancel"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
- (IBAction)cancelButton:(UIBarButtonItem *)sender
{
[self.delegate addActivityViewControllerDidCancel:self.thisActivity];
NSLog(#"delegate is %#",self.delegate);
}
And here's the delegate method implementation code from the original VC:
#pragma mark - AddViewControllerDelegate stuff
-(void) addActivityViewControllerDidSave
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
-(void) addActivityViewControllerDidCancel:(WMDGActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
2nd edit:
Here's the refreshData code:
-(void) refreshData
{
actFRC = [WMDGActivity MR_fetchAllSortedBy:#"category,name"
ascending:YES withPredicate:nil
groupBy:#"category"
delegate:nil];
[self.myTableView reloadData];
}
I've tried calling this method in viewDidLoad, and NOT calling it there. Same results.
UPDATE, 3/26/2014:
OK, I've discovered that if I remove the call to refreshData from my addActivityViewControllerDidCancel method, the labels work fine. They likewise work fine if I remove the same line from addActivityViewControllerDidSave. Unfortunately, this prevents newly added items from appearing in the HomeViewController table view until the app is relaunched.
Here is my current code for the cancel and save methods:
-(void) addActivityViewControllerDidSave
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self refreshData];
}
-(void) addActivityViewControllerDidCancel:(WMDGActivity *) activityToDelete
{
[activityToDelete MR_deleteEntity];
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext MR_saveToPersistentStoreAndWait];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
// [self refreshData];
}
I view this as a temporary, or interim, fix. Sure would be grateful for a real cure.
Thanks!
In my app, the user can create events. This is achieved by presenting the user the UI of iOS for creating an event:
- (IBAction)addTermin:(id)sender
{
// Create an instance of EKEventEditViewController
EKEventEditViewController *addController = [[EKEventEditViewController alloc] init];
// Set addController's event store to the current event store
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self presentViewController:addController animated:YES completion:nil];
}
So, I implement the delegate method:
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
{
MRHomeViewController * __weak weakSelf = self;
// Dismiss the modal view controller
[self dismissViewControllerAnimated:YES completion:^
{
if (action != EKEventEditViewActionCanceled)
{
dispatch_async(dispatch_get_main_queue(), ^{
// Re-fetch all events happening in the next 24 hours
weakSelf.eventsList = [self fetchEvents];
// Update the UI with the above events
[weakSelf.termineTableView reloadData];
});
}
}];
}
So, later I want to retrieve the events a user has created. I was thinking , that somewhere, somehow in the delegate method, I can obtain a reference to the new created event?
Or is there another way to later fetch only events created by the user?
To make this work, you need to first create a new EKEvent, keep a reference to it, and pass it into your EKEventEditViewController:
self.newEvent = [EKEvent eventWithEventStore:self.eventStore];
addController.event = newEvent;
In the delegate method, check for EKEventEditViewActionSaved and then consult self.newEvent to find what you need about the event. If you want to maintain a longer term reference to the event, you can store the eventIdentifier or other fields for later lookup.
I have created an application that uses the SMS and after the user clicks the sms button it opens up with my number already in and no message (thats their job). But when it loads up the sms message page it set the curser thing is up where the recipients are not where the message is. To explain that better, after the sms loads if they were to just start typing they would be adding another person to send the message to, not typing the message. For example if I would like to load up to a specific row on my UIPicker on startup I would:
[picker selectRow:3 inComponent:0 animated:NO];
sms load up:
- (IBAction)sms {
MFMessageComposeViewController *textComposer = [[MFMessageComposeViewController alloc] init];
[textComposer setMessageComposeDelegate:self];
if ([MFMessageComposeViewController canSendText]) {
[textComposer setRecipients:[NSArray arrayWithObjects: #"support#nicmacengineering.com", nil]];
[textComposer setBody:#""];
[self presentViewController:textComposer animated:YES completion:NULL];
} else {
NSLog(#"Can't Open Text");
}
}
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MessageComposeResultCancelled:
NSLog(#"Cancelled");
break;
case MessageComposeResultFailed:
break;
case MessageComposeResultSent:
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
First, your question is fairly hard to understand. Here's my impression of it:
Can I set the cursor to the message field by default in an SMS controller?
And the answer is:
No.
Since it is an Apple framework, with no public method to switch fields (here's the class reference).
Because of this, you won't be able to automatically set the position of the cursor.
I have a webview object (aWebView) which was added on top of current window like this -
UIWindow *webWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 20, 320,460)];
[webWindow addSubview:aWebView];
[webWindow makeKeyAndVisible];
I have a ViewController (viewcontrollerobj) which is subView of aWebView -
[webView addSubview:viewcontrollerobj.view];
Then I am calling sendInAppMail method in the ViewController-
[sviewcontroller sendInAppMail];
SendInAppMail looks like this -
MFMailComposeViewController *mailController = [[[MFMailComposeViewController alloc] init] autorelease];
if([MFMailComposeViewController canSendMail])
{
[mailController setMessageBody:#"hello" isHTML:NO];
[mailController setSubject:#"subject"];
mailController.mailComposeDelegate = self;
[self presentModalViewController:mailController animated:YES];
[mailController release];
}
didFinishWithResult looks like this -
- (void)mailComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSent:
break;
default:
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Mail viewcontroller shows up fine. The problem is that when I hit cancel it shows the delete/save draf t option and after clicking either delete/save the mail viewcontroller doesn't go away!
When I look at console it shows this log message -
"Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:]."
I am not using UIActionSheet anywhere and haven't used in the past so I am not able to understand what it is saying.
I looked at this - https://stackoverflow.com/a/6015957/516938
But it seems like the solution given is very specific to a situation.
Not sure this is the issue, but this is the first thing I would look at.
Based on the error message that you got it sounds like either one of the views (the aWebView or the one from viewcontrollerobj that you defined) doesn't allow enough space for the MFMailComposeViewController, meaning that the dimensions of it are smaller than the MFMailComposeViewController requires. It isn't actually clipping the content, so you see it, but it is blocking the touches so that they don't get to the MFMailComposeViewController.
I hope that is clear enough - I had a hard time describing my thoughts here correctly.