does EKEventEditViewController not support being pushed to a NavController? See code & error attached - iphone

does EKEventEditViewController not support being pushed to a NavController? See code & error attached.
I can present the EKEventEditViewController modally fine, BUT when I try to push via the nav controller I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Pushing a navigation controller is not supported'
Code is:
EKEventEditViewController *addController = [[[EKEventEditViewController alloc] initWithNibName:nil bundle:nil] autorelease];
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self.navigationController pushViewController:addController animated:TRUE]; // ERROR HERE

EKEventEditViewController is subclass of UINavigationController, so it can't be pushed to another UINavigationController.
EKEventEditViewController should be presented modally.
EKEventEditViewController Class Ref

In case you're looking for some code to jumpstart an iPad-with-popover implementation:
EKEventStore *eventStore [[EKEventStore alloc] init];
EKEventEditViewController *eventController = [[EKEventEditViewController alloc] init];
eventController.editViewDelegate = self;
eventController.eventStore = eventStore;
EKEvent *event = [EKEvent eventWithEventStore: eventStore];
event.title = #"New Event";
event.startDate = [[NSDate alloc] init];
event.endDate = [[NSDate alloc] initWithTimeInterval: 60 * 60 sinceDate: event.startDate];
eventController.event = event;
/* You can add EKEventEditViewController directly to the popover -- this had me baffled for _hours_ */
popover = [[UIPopoverController alloc] initWithContentViewController: eventController];
You will also want to include this delegate method to do whatever you need to when the user completes or cancels event editing:
- (void) eventEditViewController: (EKEventEditViewController *)controller didCompleteWithAction: (EKEventEditViewAction)action
{
EKEvent *thisEvent = controller.event;
switch (action) {
case EKEventEditViewActionCanceled:
NSLog(#"Canceled action");
break;
case EKEventEditViewActionSaved:
NSLog(#"Saved action: %#", thisEvent.startDate);
break;
case EKEventEditViewActionDeleted:
NSLog(#"Deleted action");
break;
default:
break;
}
[popover dismissPopoverAnimated: YES];
}
Enjoy!
Mark

For future readers:
EKEventEditViewController is a UINavigationController so you can just say:
EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];
// Set your properties here
[self.navigationController pushViewController:controller.viewControllers[0] animated:YES];
This works for me, but I don't know if you can do this for Apple.

Related

Ios MFMailComposeViewController not displaing

I trying to write rhodes native extension extension for opening iOS MailComposer.
Now code "works", but MFMailComposeViewController not displaying and xcode shows warning:
Attempt to present <MFMailComposeViewController: 0x12b60840> on <Iosmailto: 0xc1898d0> whose view is not in the window hierarchy!
I read that UIViewControllers must be in hierarchy, but i can't provide this from Rhodes ruby code or clear-C extension wrapper.
Now i'm trying to present my UIViewController with MFMailComposeController from [UIApplication sharedApplication].keyWindow.rootViewController but mail composer not show yet.
interface from iosmailto.h:
#interface Iosmailto : UIViewController<MFMailComposeViewControllerDelegate>
{
}
#property(nonatomic, assign) id delegate;
//-(IBAction)send_mail:(id)sender;
#end
implementation from iosmailto.m:
#implementation Iosmailto
- (void)viewDidLoad {
[super viewDidLoad];
[self send_mail];
}
- (void)send_mail {
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = self;
[composer setSubject:[NSString stringWithUTF8String:subj]];
NSArray *recipients_array = [NSArray arrayWithObject:[NSString stringWithUTF8String:recipients]];
[composer setToRecipients:recipients_array];
NSString *composerBody = [NSString stringWithUTF8String:message];
[composer setMessageBody:composerBody isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:composer animated:YES];
[composer release];
} else {
NSLog(#"Device is unable to send email in its current state.");
}
}
/* some unnecessary for this question methods */
#end
And C function defined in iosmailto.m thats called from Rhodes:
// find root vc
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
// find topmost vc
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
iosmailer = [[Iosmailto alloc] init];
iosmailer.delegate = topController;
[topController presentViewController:iosmailer animated:YES completion:nil];
This app is not for AppStore. Hacks is welcome if needed.
Update init for Iosmailto:
- (id)init
{
self = [super initWithNibName:nil bundle:nil];
return self;
}
Update 2 The short version of this code (without UIViewController wrapper) was my starting point. That's don't work too. And this have the same warning and one more:
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *composer = [[MFMailComposeViewController alloc] init];
composer.mailComposeDelegate = (id<MFMailComposeViewControllerDelegate>)topController ;
[composer setSubject:[NSString stringWithUTF8String:subj]];
NSArray *recipients_array = [NSArray arrayWithObject:[NSString stringWithUTF8String:recipients]];
[composer setToRecipients:recipients_array];
NSString *composerBody = [NSString stringWithUTF8String:message];
[composer setMessageBody:composerBody isHTML:NO];
[composer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[topController presentModalViewController:composer animated:YES];
[composer release];
} else {
}
Use this code to present view controller
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:composer
animated:YES
completion:nil];
Ok I think the problem is that your UIViewController doesn't have anything in its view property because you aren't using a .xib file to initialize it. See this question which programmatically creates a UIView and assigns it to the UIViewController's view property. I think that's the right way to go. See the implementation of their -(void)loadView method.
Your use-case is also a little strange, since it looks like your Iosmailto UIViewController doesn't have any content, and you're just using it as a wrapper around MFMailComposeViewController--you might consider reimplementing your C method to directly create a MFMailComposeViewController without the unnecessary layer of indirection of this unnecessary UIViewController that doesn't display anything itself.

Send SMS iPhone

I was trying to send SMS from within my app. I wrote this piece of code but it seems not to work.
No crash, no error log, simply nothing happen (of course I tried to log canSendText and the result is 1).
- (void)viewDidLoad
{
[super viewDidLoad];
messageComposer = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText]) {
[messageComposer setBody:#"Messaggio generato da SMSTest"];
[messageComposer setRecipients:[NSArray arrayWithObject:#"3333333333"]];
[messageComposer setDelegate:self];
[self presentModalViewController:messageComposer animated:YES];
}
}
Can anyone explain me what I'm doing wrong?
The problem is that presentModalViewController does not work in viewDidLoad yet as the view is loaded but might not even be on screen yet. If you put your code in viewWillAppear:animated, this should work.
Edit: As per Saphrosit's comment: viewDidAppear: is an even better place to do this.
I use this successfully:
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
controller.messageComposeDelegate = self;
controller.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:controller animated:YES];
Note that it's messageComposeDelegate, not 'delegate' as you do.
Tim
When i try the code on simulator i get an UIAlert saying text messaging is not available, because simulator canĀ“t send messages. Have you checked that your header file is a delegate of MFMessageComposeViewControllerDelegate ?
YourClassName : UIViewController <MFMessageComposeViewControllerDelegate>
//try this ... it will run ..
MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
controller.body = #"Hello from Kartik";
controller.recipients = [NSArray arrayWithObjects:#"12356478", nil];
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}

How to intilized controller with initWithmyData and with initWithStyle:UITableViewStyleGrouped?

I have one controller inheriting UITableViewController, and call the object as below
editAlarm *ob = [[editAlarm alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:ob];
ob.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:nc animated:YES];
[ob release];
ob = nil;
[nc release];
nc = nil;
now the table will initialized with groupstyle, but I want an object with it my data as normally I do in many of my projects
-(id)initwithData:(myFaceData *)dat{
id i=[super init];
self.data=dat; where data is object having some variables in it
return i;
}
myFaceData *data=[myArray objectAtIndex:tag];
editAlarm *ob = [[editAlarm alloc] initwithData:data];
[self.navigationController pushViewController:details animated:NO];
Now How can I do two init at same time, what is solution so that my object will pass along with init of new class(Controller)
If someone is not clear about question, then feel free to ask in comments
Thanks in Advance :-)
What you could do is make your data variable a Property (and synthesise it) so you can set it right after you init it in the class you are initialising it.
Alternatively you could create your own init method as follows:
- (id)initWithStyle:(UITableViewStyle)style andData:(myFaceData *)dat {
if ((self = [super initWithStyle:style])) {
self.dat = dat;
}
return self;
}
And to call your initialiser you could do this in the calling class (where theData is the data to be passed across):
editAlarm *ob = [editAlarm alloc] initWithStyle:UITableViewStyleGrouped andData:theData];

Can't set recipients of MFMessageComposeViewController?

I have a method like this:
void sendSMS{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.recipients = [NSArray arrayWithObject:#"0933660805"];
[picker setBody:#"Message body"];
picker.messageComposeDelegate = self;
[self.navigationController presentModalViewController:picker animated:YES];
//[picker release];
return;
}
}
Message composer open but recipients and message body are empty (image below). Anybody know how can i fix it :(
Go for this ones and then check may be it will resolve your issue
void sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSMutableArray *toRecipients = [[NSMutableArray alloc]init];
[toRecipients addObject:#"0933660805"];
[picker setRecipients:(NSArray *)toRecipients];
[toRecipients release];
bodyString = [NSString stringWithFormat: #"Message body"];
[picker setBody:bodyString];
[self presentModalViewController:picker animated:YES];
[picker release];
}
Also take a look at this tutorial http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/
Good Luck!
OK I answered my own question. Now I want no one else to have to go thru this. I was calling this method from just an NSObject. It was a delegate to MFMessageComposeViewControllerDelegate but that made no difference. I had to move this method to my MainViewController, then it worked.
iOS 10.0 is here and this is still a problem for me. So, I have fashioned a workaround.
According to previous comments that initializing the MFMessageComposeViewController in the viewDidLoad() won't solve the problem (which I can attest to), unless the view controller gets presented, it won't be cached. So, the hack here is to make a window, set its root view controller, present a dummy MFMessageComposeViewController instance and immediately dismiss it, somewhere before your actual need (like in viewDidLoad())
Here is a sample code I'm using (Swift 3.0 - Let me know if you were interested in Obj-C counterpart):
let window = UIWindow()
let vc = UIViewController()
window.rootViewController = vc
let messageCompose = MFMessageComposeViewController()
vc.present(messageCompose, animated: false) { [weak messageCompose] in
messageCompose?.dismiss(animated: false, completion: nil)
}
The thing here is that if you present it in the currently active window's view controller chain, it will mess up your UI by showing and hiding the keyboard abruptly (no matter how you try to hide the controller's view and what not), due to the message body selection on present. But adding it to a whole new window which is not in view cycle, it will be correctly initialized and there will be no trace of such transaction on view. Plus, you won't boggle the memory too much this way (because the scope of the controller should be minimal now) and you can initialize your actual MFMessageComposeViewController any time you want and get it much faster now. If your application heavily relies on MFMessageComposeViewController (which I doubt) you can move this to your AppDelegate to be ready anywhere around your app's life cycle.
Cheers,
M.
Try this
- (void)sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSArray *toRecipients = [NSArray arrayWithObject:#"NUMBER HERE"];
[picker setRecipients:toRecipients];
[self presentModalViewController:picker animated:YES];
[picker release];
}
In my case (on iPhone 3g s) the problem was when I called [self.navigationController pushViewController... ], when i tried call [self presentModalViewController ...] it worked, I dont know why, but it is. Try it.
set the MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
before if ([MFMessageComposeViewController canSendText]) {...}
Try this.
Try this.
- (void)forwardPromo
{
MFMessageComposeViewController *composeViewController = [[MFMessageComposeViewController alloc] init];
composeViewController.body = #"Message body";
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805"];
composeViewController.messageComposeDelegate = self;
[self presentViewController:composeViewController animated:YES completion:nil];
}
You should have a "nil" at the end of the array:
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805", nil];

NSInvalidArgumentException

I Am creating an iPhone application which displays an UITableView at the start with some text in the cells. When a user taps a cell it should transition to another view. When I run the application in the iPhone Simulator and click on a cell I get the following error:
2009-09-23 12:20:03.554 ZDFMobiel[751:20b] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[RootViewController eigenRisicoView]:
unrecognized selector sent to instance 0xd1d1a0'
2009-09-23 12:20:03.555 ZDFMobiel[751:20b] Stack: (
Here is the function (In RootViewController.m) where the error occurred. It happens at the
if(self.eigenRisicoView == nil) {
line or the at the other if statements, depending on which cell you click.
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ZDFMobielAppDelegate *appDelegate = (ZDFMobielAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *content = (NSString *)[appDelegate.menuItems objectAtIndex:indexPath.row];
switch (indexPath.row) {
case 0:
if(self.eigenRisicoView == nil) {
EigenRisicoViewController *viewController = [[EigenRisicoViewController alloc] initWithNibName:#"EigenRisicoViewController" bundle:[NSBundle mainBundle]];
self.eigenRisicoView = viewController;
[viewController release];
}
[self.navigationController pushViewController:self.eigenRisicoView animated:YES];
self.eigenRisicoView.title = content;
break;
case 1:
if(self.declaratieStatusView == nil) {
DeclaratieStatusViewController *viewController = [[DeclaratieStatusViewController alloc] initWithNibName:#"DeclaratieStatusViewController" bundle:[NSBundle mainBundle]];
self.declaratieStatusView = viewController;
[viewController release];
}
[self.navigationController pushViewController:self.declaratieStatusView animated:YES];
self.declaratieStatusView.title = content;
break;
case 2:
if(self.vergoedingenView == nil) {
VergoedingenViewController *viewController = [[VergoedingenViewController alloc] initWithNibName:#"VergoedingenViewController" bundle:[NSBundle mainBundle]];
self.vergoedingenView = viewController;
[viewController release];
}
[self.navigationController pushViewController:self.vergoedingenView animated:YES];
self.vergoedingenView.title = content;
break;
case 3:
if(self.zoekenZorgInstView == nil) {
ZoekenZorgInstViewController *viewController = [[ZoekenZorgInstViewController alloc] initWithNibName:#"ZoekenZorgInstViewController" bundle:[NSBundle mainBundle]];
self.zoekenZorgInstView = viewController;
[viewController release];
}
[self.navigationController pushViewController:self.zoekenZorgInstView animated:YES];
self.zoekenZorgInstView.title = content;
break;
default:
break;
}
// Navigation logic may go here -- for example, create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController animated:YES];
// [anotherViewController release];
}
This is my RootControllerView.h file
#import "EigenRisicoViewController.h";
#import "DeclaratieStatusViewController.h";
#import "VergoedingenViewController.h";
#import "ZoekenZorgInstViewController.h";
#import "ZDFMobielAppDelegate.h";
#interface RootViewController : UITableViewController {
EigenRisicoViewController *eigenRisicoView;
DeclaratieStatusViewController *declaratieStatusView;
VergoedingenViewController *vergoedingenView;
ZoekenZorgInstViewController *zoekenZorgInstView;
}
#property(nonatomic,retain) EigenRisicoViewController *eigenRisicoView;
#property(nonatomic,retain) DeclaratieStatusViewController *declaratieStatusView;
#property(nonatomic,retain) VergoedingenViewController *vergoedingenView;
#property(nonatomic,retain) ZoekenZorgInstViewController *zoekenZorgInstView;
#end
I Am new to iPhone development, Objective C and XCode so I don't understand what the error means..
Does anyone know what I am doing wrong?
I'd need to see the whole implementation, but it sounds like you didnt #synthesize eigenRisicoView;