iOS iPad UIActionSheet Issue - objective-c

I am currently developing an application which needs an option to 'share' using multiple services; such as email, twitter.
To to this, I have a UIBarButtonItem coded in and when touched, it triggers this:
UIActionSheet *sheet = [[UIActionSheet alloc]
initWithTitle:#""
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[sheet addButtonWithTitle:#"Email"];
[sheet addButtonWithTitle:#"Tweet"];
[sheet addButtonWithTitle:#"Cancel"];
sheet.cancelButtonIndex = sheet.numberOfButtons-1;
[sheet showFromRect:self.view.bounds inView:self.view animated:YES];
[sheet release];
In conjunction with this to detect which button is selected:
clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == actionSheet.cancelButtonIndex) { return; }
switch (buttonIndex) {
case 0:
{
[self emailThis];
break;
}
case 1:
{
[self tweetThis];
break;
}
}
This works a treat on the iPhone. But unfortunately it displays incorrectly on the iPad. It looks like it is trying to display the UIPopoverController, but it is positioned center of the navbar with practically no height.
I have looked into using the UIPopoverController, but I cannot seem to find out how to use it with buttons. Is there anyway I can adapt the code above to properly display the buttons, as it's trying to already.
Many thanks,
Ryan
PS: I'm new to objective-c/iOS coding, so please be specific. Thank you :)
EDIT:
I have tried using:
[sheet showFromBarButtonItem:[self share] animated:YES];
But it doesn't work. Here is my code for the button:
UIBarButtonItem *share = [[UIBarButtonItem alloc]
initWithTitle:#"Share"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(loadShare)];
self.navigationItem.rightBarButtonItem = share;
[share release];
Also here is the code in the .h file:
#interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
UIBarButtonItem *share;
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem *share;
Here is the debug error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '* -[__NSPlaceholderArray
initWithObjects:count:]: attempt to insert nil object from objects[0]'

self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(actionPhotoShare:)] autorelease];
...
-(void)actionPhotoShare:(id)sender
{
actionSheetShare = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:NSLocalizedString(#"ActionSheet_Cancel", #"")
otherButtonTitles:NSLocalizedString(#"ActionSheet_Email", #""),nil];
if (IS_DEVICE_IPAD) {
[actionSheetShare showFromBarButtonItem:sender animated:YES];
}else {
[actionSheetShare showInView:self.view];
}
}

Instead of [sheet showFromRect], use [sheet showFromBarButtonItem], and point it to your Share UIBarButtonItem.
Note: you may need to create an IBOutlet or ivar for your UIBarButtonItem if you don't have one already, but that's extremely simple and I'm guessing you can do that.

Your issue is that you are using showFromRect with the rect being the entire screen. That means the popup is placing the "arrow" the best it can to center on the screen. What you want is either showFromBarButtonItem or pass in the rect (self.shareButtonItem.frame) of the button.

Related

What is wrong with my camera button delegate?

I created a camera button in a collection view controller cell to take a picture, and output it to a UIImageView the size of the cell. Right now I'm getting a error with the delegate and I'm not quite sure what it wants me to do.
- (IBAction)cameraButtonClicked:(id)sender {
if (![UIImagePickerController isSourceTypeAvailable:(UIImagePickerControllerSourceTypeCamera)]) {
UIAlertView *cameraAlertView = [[UIAlertView alloc] initWithTitle:#"Camera Not Available" message:#"There is no camera on this device which really defeats the purpose of this game. We suggest you get an iDevice with a camera." delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[cameraAlertView show];
}else{
//Show the Image Picker Controller Here
UIImagePickerController * ipc = [[UIImagePickerController alloc] init];
ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.allowsEditing = NO;
//Set the Delegate
ipc.delegate = self;
[self.navigationController presentViewController:ipc animated:YES completion:nil];
}
}
It's telling you that self does not conform to the UINavigationControllerDelegate and/or UIImagePickerControllerDelegate protocols. Implement those protocols on your class.
Did you specify the UIImagePickerControllerDelegate protocol in your header?

error: address doesn't contain a section that points to a section in a object file

Hi i have searched here on the forum but no help found so i am posting it new. Here is the scenario, i am creating a mfmailcomposeviewcontroller in the main rootviewcontroller, i am displaying it by calling presentviewcontroller but when it is dismissed i get this error :
error: address doesn't contain a section that points to a section in a object file
The code i am using is given below:
-(void) mailButtonTapped
{
if ([MFMailComposeViewController canSendMail]) {
mailViewController_ = [[MFMailComposeViewController alloc] init];
mailViewController_.mailComposeDelegate = self;
[mailViewController_ setSubject:#"Try ..."];
[mailViewController_ setMessageBody:#"Hey I just tried ..." isHTML:NO];
NSData *videoData = [NSData dataWithContentsOfURL:movieURL_];
[mailViewController_ addAttachmentData:videoData mimeType:#"video/quicktime" fileName:#"Video.mov"];
[self presentViewController:mailViewController_ animated:YES completion:nil];
}
else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sharing Not Possible" message:#"Configure your mail to send the mail" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
[alertView release];
}
}
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
NSString *title = #"Email";
NSString *msg = nil;
if (result == MFMailComposeResultFailed)
msg = #"Unable to send, check your email settings";
else if (result == MFMailComposeResultSent)
msg = #"Email Sent Successfully!";
else if (result == MFMailComposeResultCancelled || result == MFMailComposeResultSaved)
msg = #"Sending Cancelled";
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
[self dismissViewControllerAnimated:YES completion:nil];
}
After dismissing i receive the error:
error: address doesn't contain a section that points to a section in a object file
Please help me
I also had this error but with another scenario. I had a block property defined with #property (assign, nonatomic).
To fix this issue, I declared my block property with #property (copy, nonatomic).
Cheers
This error happens when an object / pointer is being accessed that doesn't exist anymore . And can also cause other bad access, 0x00000 value accessed etc.. errors.
So you are deleting/releasing a pointer , and then accessing later .
From looking at the code, and this is just a guess without debugging, you set the second AlertView's delegate to self, but then immediately dismiss the viewcontroller.
Try dismissing after the alert view is dismissed or the button is pressed, or maybe just setting the AlertView delegate to nil.
Even if that's not exactly the error, the main reason is somewhere you are releasing an object then trying to call a function or access it.
You can use it like this:
MFMailComposeViewController *mailViewController_ = [[MFMailComposeViewController alloc] init];
mailViewController_.mailComposeDelegate = self;
[mailViewController_ setSubject:#"Try ..."];
[mailViewController_ setMessageBody:#"Hey I just tried ..." isHTML:NO];
NSData *videoData = [NSData dataWithContentsOfURL:movieURL_];
[mailViewController_ addAttachmentData:videoData mimeType:#"video/quicktime" fileName:#"Video.mov"];
[self presentViewController:mailViewController_ animated:YES completion:nil];
[mailViewController_ release];
I also had this problem but caused by a very silly error, i wrote a property called frameon a class that inherits from UIView (it was a UITableViewCell but i think this would happen with every class that inherits from UIView) this overwrote the original frame property and caused this error.
Fixed just by changing property name.
The completion expects a block to be called when the animation of dismissal is completed.
Just remove "completion:nil" and it should work!
Regards.

Creating a UIPopoverController

I'm creating a popover in Xcode 4.3.
I don't get any error messages but when I click build and run and I press the button that is supposed to open the popover screen, the app crashes and highlights in green a line in my code and says:
Thread 1: breakpoint 2.1..
What does this mean and how can I fix it?
- (IBAction)popOver
{
SecondView *secondview = [[SecondView alloc] init];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:secondview];
[popover setDelegate:self];
[popover presentPopoverFromRect:CGRectMake(801, 401, 300, 200) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
[popover setPopoverContentSize:CGSizeMake(300, 200)];
}
Thanks in advance.
Few suggestions here...
First, are you using Automatic Reference Counting (ARC)? if yes you need to have an instance variable to control your UIPopoverController. For example:
#property (strong, nonatomic) UIPopoverController* popover;
if you are not using ARC create a retain one:
#property (retain, nonatomic) UIPopoverController* popover;
In the first case you have to do this because if not, ARC will release for you the just created popover at the end of your IBAction. In addition you do this to have a reference for your popover. See NOTE. This is valid also if you don't use ARC.
NOTE At some point you could have the necessity to release the popover. For example in - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController do
self.popover = nil;
Then, if your SecondView is a UIViewController call it SecondViewController. But this is a simple naming suggestion.
Finally, the correct way for display the popover from the action sender (e.g a UIButton), instead of hardcode positions, could be:
- (IBAction)openPopover:(id)sender
{
// create the popover here...
UIButton* senderButton = (UIButton*)sender;
[popover setPopoverContentSize:CGSizeMake(300, 200)];
[popover presentPopoverFromRect:senderButton.bounds inView:senderButton permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
-(IBAction)showpop:(id)sender
{
UIPopoverController *pop = [[UIPopoverController alloc]initWithContentViewController:popoverview];
[pop setDelegate:self];
[pop presentPopoverFromRect:popbutton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
The SecondView that you're passing into UIPopOverController is a UIView. Make it a UIViewController, because, what UIPopOverController expects is a UIViewController.
-Suraj
Make sure you simulate on iPad device
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
// We are using an iPhone
UIActionSheet *alertSheet = [[UIActionSheet alloc] initWithTitle:#"Where do you want to get your daily image?" delegate:(self) cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Camera", #"Library", nil];
[alertSheet setTag:0];
[alertSheet setDelegate:self];
[alertSheet showFromTabBar:[[self tabBarController] tabBar]];
[alertSheet release];
}else {
// We are using an iPad
/// here you should pass UIViewController inside the popover
/// follow #flexaddicted notes to implement the popover
}
Check below link for popover tutorial in ios
UIPopOverController Tutorial

UIAlertView with Button linking alternate ViewController

I needed a button that causes a UIAlertView with actions to pop up.
Once the Alert pops up it needs to have 1 button to cancel and stay on the same page and 1 button that links you to another ViewController.
This is what I pieced together from some forums but I have no idea what I'm doing and it gives me about 9 error messages. Please Help!
-(IBAction)Alert:(id)sender {
UIAlertView *Alert = [[UIAlertView alloc] initWithTitle:#"Alert"
message:#"Warning! By entering the Tutorial, all data will be lost. Are you sure you want to continue?"
delegate:self
cancelButtonTitle:#"Return to Data Collection"
otherButtonTitles:#"Continue", nil];
[Alert Show];
[Alert Release];
}
- (void)Alert:(UIAlertView *)Alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(Alert.tag==0) {
if(buttonIndex == 1)//OK button pressed
{
Tutorial *Info = [[Tutorial alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:Info animated:YES];
}
The first box of code works so that when I press a button on my home screen an alert with 2 buttons pops up.
However, I can't get the second button to link me to the next ViewController.
Objective-C is case-sensitive.
[Alert show];
[Alert release];
and
- (void)alertView:(UIAlertView *)Alert clickedButtonAtIndex:(NSInteger)buttonIndex
(How do you think, it can work, if you rename the methods???)
remove if(Alert.tag==0) {
Why are you not passing a name for a nib-file here: Tutorial *Info = [[Tutorial alloc] initWithNibName:nil bundle:nil];
Please stick to coding conventions. objects are named in camelCase.
Conclusion
get you a good book or videos to learn from the beginning. Some resources to do so.

stop Saving Image to photo library

How to stop saving image. which is already exist in iphone photo library.
This code is for savingImage.....
-(IBAction)saveImage:(id)sender
{
NSLog(#"calling save");
if (coverPage !=nil)
{
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancle" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
if image is saved and clicking again and again the photo is saving..... How to stop saving image once it saved.
Without having more context it is difficult to say, but broadly speaking you can use a variable to track whether or not you have previously saved the current coverPage and simply avoid re-saving it if you have. For example:
-(IBAction)saveImage:(id)sender{
NSLog(#"calling save");
if (coverPageAlreadySaved) {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Silly user, you already saved this image." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
else if (coverPage !=nil) {
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
coverPageAlreadySaved = YES;
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
...just be sure to set coverPageAlreadySaved = NO whenever the coverPage is changed (wherever you happen to be doing that in your code).
Alternately, since you already have the check against nil, you could just do:
-(IBAction)saveImage:(id)sender{
NSLog(#"calling save");
if (coverPage !=nil) {
NSData * imageData = UIImagePNGRepresentation(coverPage);
UIImage *theImage = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(theImage, self, nil, nil);
coverPage = nil;
}
else {
UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:#"Alert" message:#"Image is nil" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
[alertView show];
[alertView release];
}
}
...which will prevent the image from being re-saved until it gets updated somewhere else in your code (at which point I assume it counts as a new coverPage).
If it's just one image you're saving then you can perform this just with a BOOL ivar for flag, like:
BOOL imageSaved;
And whenever you tap the button it'll just check if !imageSaved then perform the saving.
But if it's more then one image then you can do this using NSMutableArray.Like:
NSMutableArray *savedImages;//it's an ivar
Then before performing the saving operation:
NSString *imageName=......//Here I asssume you can get the image's name
if(!imageSaved)
NSMutableArray *savedImages=[[NSMutableArray alloc]init];
if (![savedImages containsObject:imageName]){
.........here comes the saving operation
and at the end you add the imageName to the array
[savedimages addObject:imageName];
}
I've given you just an example. You might not know the names of the images you save. If that's the case you can mark the image (which can be performed in several ways) and add the image itself.
Set the UIButton as an IBOutlet as well. Then set the enabled property to NO in the IBAction. Set the UIButton IBOutlet back to YES somewhere else in your program to 'reset' the button. It is similar to using a UIStepper in that you have to declare it twice...once as an IBAction and once as an IBOutlet.
This will allow you to use the button once, then it is 'greyed out' or 'muted' to prevent further activation. Basically you are disabling the UIGestureRecognizer from the UIButton.
Set the IBAction and IBOutlet.
- (IBAction)saveImageButton:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *saveImageButton;
Set the enabled to NO in the IBAction.
- (IBAction)saveImageButton:(id)sender {
UIImageWriteToSavedPhotosAlbum(_processedImageView.image, nil, nil, nil);
_saveImageButton.enabled = NO;
}
Then change it to YES somewhere else in your program to 'reset' the button so you can use it again.
_saveImageButton.enabled = YES;