Clicking a button in UIActionSheet causes my app to crash - iphone

I'm trying to implement a UIActionSheet which will have some sharing buttons on it for sharing to twitter, facebook, email and print.
Here is my share view controller.h
#interface ShareViewController : UITableViewController <UIActionSheetDelegate, MFMailComposeViewControllerDelegate>
#property (nonatomic, strong) NSMutableDictionary *services;
#property (strong, nonatomic) UIActionSheet *actionSheet;
#property (strong, nonatomic) id <ShareViewControllerDelegate> delegate;
#property (nonatomic, strong) UIPopoverController *popCon;
#property (nonatomic, strong) NSString *serviceTitle;
-(IBAction)loadActionSheet:(id)sender;
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
- (void)tweetThis;
- (void)printThis;
- (void)openMail;
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error;
#end
Here is my share view controller.m
-(IBAction)loadActionSheet:(id)sender{
if (self.actionSheet) {
// do nothing
}
else {
UIActionSheet *sharing = [[UIActionSheet alloc]
initWithTitle:nil
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:#"Twitter", #"Facebook", #"Email", #"Print", nil];
[sharing showFromBarButtonItem:sender animated:YES];
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(#"Button index: %d",buttonIndex);
switch (buttonIndex) {
case 0:
[self tweetThis];
break;
case 1:
[self sendToFacebook];
break;
case 2:
NSLog(#"email");
[self openMail];
break;
case 3:
NSLog(#"Print");
[self printThis];
break;
default:
NSLog(#"Error");
break;
}
}
I ma initiaalising my share view controller in main view controller.m as follows:
- (IBAction)shareButtonTapped:(id)sender {
ShareViewController *svc = [[ShareViewController alloc] initWithStyle:UIActionSheetStyleDefault];
[svc loadActionSheet:(id)sender];
}
I can open the action sheet fine, but when I click on any of the buttons, it crashes the app. Any ideas as to why?

This is most likely a memory-management issue. It looks like you're using ARC, so after the shareButtonTapped method returns, ARC will automatically release svc, as it's no longer referenced anywhere. The delegate property of the action sheet is weak, so it's not retained by that either.
I don't really see why ShareViewController is a view controller in the first place, as you never seem to be loading its view, but you may have your reasons... In any case, you should make that controller a strong property or instance variable of your other (main) view controller, so that it's not automatically released before the action sheet finishes.

Yes. Go to your .xib file.
You should see all the buttons you have.
Click on a button and go to the "Connections Inspector"
Delete the referencing outlet.
Drag the referencing outlet to the button and set the button to the "ID" you want.
Let me know if that works.

Just a stupid answer - the methods like - (void) sendToFacebook; are implemented, right?

Related

iOS: trouble sharing data between two view controllers

I have an app, which has a first view controller called MainViewController that's sorta like a stopwatch, and when I click finish, it displays a UIAlertView pushes another view controller, EndViewController, which shows how long the stopwatch was running and how long it was paused. I am getting the following errors:
My Point[851:c07] -[EndViewController topViewController]: unrecognized selector sent to instance 0x754db60
My Point[851:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[EndViewController topViewController]: unrecognized selector sent to instance 0x754db60'
Can anyone point ou to me what's wrong?
heres my code:
MainViewController.h:
#import "EndViewController.h"
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate, UIAlertViewDelegate>
#property (strong, nonatomic) IBOutlet UILabel *out;
#property (strong, nonatomic) IBOutlet UILabel *in;
#end
MainViewController.m:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"endtask"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
EndViewController *controller = (EndViewController *)navController.topViewController;
controller.timeIn.text=_in.text;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
_alert = [[UIAlertView alloc] initWithTitle:#"Are you sure?"
message:nil
delegate:self
cancelButtonTitle:#"NO"
otherButtonTitles:#"YES", nil];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
//do nothing
}
else if (buttonIndex == 1) {
[self performSegueWithIdentifier:#"endtask" sender:self];
}}
- (IBAction)endButton:(UIButton *)sender {
[_alert show];
}
- (IBAction)endButton:(UIButton *)sender {
[_alert show];
}
EndViewController.h:
#interface EndViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *timeIn;
#end
You're calling a method named topViewController on an object which doesn't have the method/property. It's this line here:
EndViewController *controller = (EndViewController *)navController.topViewController;
I would suspect its because the view controller you are assigning to navController isn't actually a navigation controller, but is something else. Check your storyboards/nibs for this.
Also, try logging navController, as one commentor said, and see what that gives you.
NSLog(#"%#", navController);
If you are passing a string with timeIn you should have #property of a NSString in the endViewController.h
#property (strong, nonatomic) NSString * timeIn ;
Then in you endViewController.m you put the timeIn into a labe for example.
myLabel.text = timeIn;

Trying to dismiss a view controller by tap on cancel using delegation (Not working at all)

Having two view controller within a navigation controller:
PhoneNumbersTVC > holds a list of phone numbers added by NewPhoneNumberTVC
NewPhoneNumberTVC > a controller for adding phone numbers
When I tap on cancel on NewPhoneNumberTVC I like to get back to PhoneNumbersTVC with a delegation as follow.
PhoneNumbersTVC.h
#import <UIKit/UIKit.h>
#import "NewPhoneNumberTVC.h"
#interface PhoneNumbersTVC : UITableViewController <NewPhoneNumberTVCDelegate>
#end
PhoneNumbersTVC.m
- (void)saveBtnWasTappedOnNewPhoneNumberTVC:(NewPhoneNumberTVC *)newPhoneNumberTVC
{
NSLog(#"saveBtnWasTappedOnNewPhoneNumberTVC");
[newPhoneNumberTVC.navigationController popViewControllerAnimated:YES];
}
- (void)cancelBtnWasTappedOnNewPhoneNumberTVC:(NewPhoneNumberTVC *)newPhoneNumberTVC
{
NSLog(#"cancelBtnWasTappedOnNewPhoneNumberTVC");
[newPhoneNumberTVC.navigationController popViewControllerAnimated:YES];
}
NewPhoneNumberTVC.h
#import <UIKit/UIKit.h>
#class NewPhoneNumberTVC;
#protocol NewPhoneNumberTVCDelegate <NSObject>
- (void)saveBtnWasTappedOnNewPhoneNumberTVC:(NewPhoneNumberTVC *)newPhoneNumberTVC;
- (void)cancelBtnWasTappedOnNewPhoneNumberTVC:(NewPhoneNumberTVC *)newPhoneNumberTVC;
#end
#interface NewPhoneNumberTVC : UITableViewController
#property (weak, nonatomic) id <NewPhoneNumberTVCDelegate> delegate;
#property (strong, nonatomic) NSManagedObjectContext *managedOC;
#property (weak, nonatomic) IBOutlet UITextField *phoneNumberTextField;
- (IBAction)saveBtnTapped:(UIBarButtonItem *)sender;
- (IBAction)cancelBtnTapped:(UIBarButtonItem *)sender;
#end
NewPhoneNumberTVC.m
- (IBAction)cancelBtnTapped:(UIBarButtonItem *)sender
{
NSLog(#"cancelBtnTapped");
self.phoneNumberTextField.text = #"";
self.phoneKindTextField.text = #"";
[self.delegate cancelBtnWasTappedOnNewPhoneNumberTVC:self];
}
When I tap on cancel on NewPhoneNumberTVC I see that above method cancelBtnTapped fires but delegation does not work, no method executes in PhoneNumbersTVC. View doesn't go away and I don't see: cancelBtnWasTappedOnNewPhoneNumberTVC on console.
If you want this method cancelBtnWasTappedOnNewPhoneNumberTVC: get called, you definitely need to set the delegate of your NewPhoneNumberTVC object to a PhoneNumbersTVC object. For example, there should be existing some codes in PhoneNumbersTVC.m :
NewPhoneNumberTVC *myNewPhoneNumberTVC = [[NewPhoneNumberTVC alloc] init];
myNewPhoneNumberTVC.delegate = self;
You can log as following to verify that the delegate is set successfully or not"
NewPhoneNumberTVC.m
- (IBAction)cancelBtnTapped:(UIBarButtonItem *)sender
{
NSLog(#"cancelBtnTapped");
self.phoneNumberTextField.text = #"";
self.phoneKindTextField.text = #"";
NSLog(#"self.delegate :%#",self.delegate);
[self.delegate cancelBtnWasTappedOnNewPhoneNumberTVC:self];
}

How to send data from UItextfields of one viewcontroller to new view controller? [duplicate]

I am a bit stuck on trying to pass data from two UITextfields on one viewcontroller to another viewcontroller. Basically I got the items below:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UITextfield *Textfield1;
IBOutlet UITextfield *Textfield2;
}
-(IBAction)GoNextView:(id)sender;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
(IBAction)GoNextView:(id)sender {
SecondView *second = [[SecondView alloc] initWithNibName:nil bundle:nil];
[self presentViewController:second animated:YES completion:NULL];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIViewController {
IBOutlet UILabel *ShowTextfield1;
IBOutlet UILabel *ShowTextfield2;
}
-(IBAction)GoBack:(id)sender;
#end
SecondView.m
#interface SecondView ()
#end
#implementation SecondView
- (IBAction)GoBack:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
What I want is, that when the button GoNextView is pressed it should pass the data in the UITextfield to the SecondView. And the go to the next page. The data should now be displayed in the two Labels on the SecondView. I've been struggling with this for many hours now and its killing me. I know I have to use some NSString and #property(nonatomic, retain) NSString *asdas. But I simply can't make it work. So based on the above code how do I pass data from the two UITextfield to the two labels on the next view?
Instead of navigating to the second view through a function, use Storyboard Segues. Create a storybaord application. To Create a segue you need a navigation view controller. You can do that by the following steps.
Select the first view controller and go to Editor -> Embed In -> Navigation Controller.
Then Ctrl+Click on the "GoNextView" button, and drag and drop in the SecondView.
You will get three options: push, model, custom. Click push then a segue will be created between these two views.
Click that segue and click the "Show the Attribute Inspector" on the right side property window. Now name it as "connector" or which ever name you prefer.
Now, in SecondView.h create two strings,
#property (nonatomic, retain) NSString *str1;
#property (nonatomic, retain) NSString *str2;
and synthesize them in SecondView.m.
Lets name your UITextFields as "text1" and "text2" which are in your ViewController. Go to the ViewController.h and add #import "SecondView.h"
In ViewController.m do the following,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"connector"])
{
ViewController *VC = [segue destinationViewController];
VC.str1 = text1.text;
VC.str2 = text2.text;
}
}
Now you can display these strings in your SecondView. In Secondview.m,
label.text = str1;
and it will be displayed.
Use NSUserDefaults or the normal synthesising common interface variables. For example,
NSUserDefaults
From sender's view controller,
NSString *text=textField1.text;
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
[prefs setObject:text forKey:#"text1value"];
And you can get the value from any view controller as,
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
NSString *received string= [prefs stringForKey:#"text1value"];
Normal assigners,
I believe you must be using performsegue to navigate view controllers. There is a delegate method called "prepareforsegue" and you can assign the textfield values into the interface variables. For example,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"seguename"]) {
destViewController *destViewController = segue.destinationViewController;
destViewController.name = #"some text";
}
}
In the receiver's view controller, getter variable is actually defined as,
In .h file, #property(nonatomic, strong) NSString *name;
In .m file, Don't forget to synthesis the variable after implementation
#implementation destViewController
#synthesize name;
Hope it helps!

Why won't my UIButton work?

I'm trying to call Sharekit with a UIButton, but when I tap the button running on my device, nothing happens.
This should be the relevant code in my view controller's .h
#import "SHK.h"
#import "SHKFacebook.h"
#interface ViewController : UIViewController <CaptureManagerDelegate>
{
IBOutlet UIButton *upload;
}
#property (nonatomic, retain) IBOutlet UIButton *upload;
-(IBAction)buttonPressed:(id)sender;
And in my view controller's .m (using code from example here http://gazapps.com/wp/2011/07/17/basic-sharekit-customization)
#synthesize upload;
-(IBAction)buttonPressed:(id)sender {
SHKItem *item;
NSURL *url = [NSURL URLWithString:#"http://www.gazapps.com"];
item = [SHKItem URL:url title:#"Checkout this site"];
[SHKFacebook shareItem:item];
}
-(void)dealloc
{
[upload release];
}
Besides trying to use a UIButton instead of UIBarButton, I've followed Sharekit's install instructions to the letter. In my storyboard, I CTRL-dragged to the "first responder" and linked up my button to buttonPressed. I'm not getting any warnings or errors in xcode. But nothing happens when I tap the button.
You code seems fine. The problem is probably within the nib file. Check your connections again.
Are you doing anything else with your upload (UIButton) property? You don't need that Outlet at all, if you only want to trigger one IBAction.
You could put a breakpoint in your buttonPressed method, to see if the connections are setup correctly.
you should use SHKActionSheet
SHKActionSheet *actionSheet = [EDShareActionSheet actionSheetForItem:item];
[actionSheet showFromToolbar:self.navigationController.toolbar];

Interface builder connections cause crash in tab bar application

for exercise I'm trying to develop a simple iPhone application based on a tab bar from scratch, but I had some problem..
I've follow up these steps: http://www.techotopia.com/index.php/Creating_an_iPhone_Multiview_Application_using_the_Tab_Bar
The app loads correctly the three views until there's no connection within; if I connect any outlets or action to a label or button of the subviews, the app crash.
For example, my firstView.h contains:
#import <UIKit/UIKit.h>
#interface firstView : UIViewController {
IBOutlet UILabel *resultLabel;
}
-(IBAction)randomizeAction;
#property (nonatomic , retain) IBOutlet UILabel *resultLabel;
#end
and the firstView.m
-(IBAction)randomizeAction:(id)sender
{
//NSInteger rand = arc4random() % 75;
//resultLabel.text = [ [NSString alloc] initWithFormat:#"Random integer: #%",rand];
UIAlertView *alert = [ [UIAlertView alloc] initWithTitle:#"Yeah!" message:#"Yeah" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil ];
[alert show];
[alert release];
}
If I connect a label to the resultOutlet or a button to the "randomizeAction" method, the app crash when I switch to the related views..
Where is the mistake?
in .h file you declare a property to be IBOutlet twice. As I don't think this causes the problem but it's just unnecessary. Also you declared randomizeAction in the .h file wihout the parameter and you implemented it with a parameter.
Your code should look like this:
#import <UIKit/UIKit.h>
#interface firstView : UIViewController {
UILabel *resultLabel;
}
#property (nonatomic , retain) IBOutlet UILabel *resultLabel;
-(IBAction)randomizeAction:(id)sender;
#end
and the firstView.m
-(IBAction)randomizeAction:(id)sender
{
//do stuff
}
From that error message it looks like your view controller isn't hooked up properly in Interface Builder. Are you sure your view controller (File's Owner in IB) is identified as an instance of firstView? Check what class it is in the Identity Inspector in XCode.
Also it would be helpful if you can show the code where your view controller is declared and created (most likely in the App Delegate).
I'm not sure, but I think you have to change this:
#interface DetailViewController : UIViewController
To:
#interface firstView : UIViewController