I would like to learn how would I make a UITextField get text from a UIPopover view. Let's say I have buttons with numbers on my popover and I want these numbers to be input into the textfield.
Some people sugested to us BOOL like this:
- (BOOL)textFieldShouldBeginEditing:(UITextField *) textField {
[self.myPopover presentPopoverFromRect:textField.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
return NO;
}
And one more:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
if(popoverController == nil){ //make sure popover isn't displayed more than once in the view
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverDetailContent];
}
[popoverController presentPopoverFromRect:textView.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
popoverController.delegate = self;
return NO; // tells the textfield not to start its own editing process (ie show the keyboard)
}
Both are not making much change, my textField still calls the default iPad keyboard instead of my popover.
Second example uses delegate popoverController and my controller is flipsidePopoverController.
Could I use an IBAction like this?
- (IBAction)togglePopover:(id)sender {
if (self.flipsidePopoverController) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
self.flipsidePopoverController = nil;
} else {
[self performSegueWithIdentifier:#"showAlternate" sender:sender];
}
}
Related
I have a tableview that requires a subview that's used to add content. The subview contains a UITextView that's used to enter text. Prior to 7.1 The following would happen:
The subview is glued to the bottom of the tableview via scrollViewDidScroll
When activated, the keyboard would show, the view animates up with the keyboard
When text is typed in, the textView would expand upwards if required, with the bottom of the textView remaining in place.
NOW after 7.1, the following behavior takes place:
The subview animates upwards with the keyboard fine
If the text forces a new line, instead of expanding, textViewDidEndEditing get's triggered and the keyboard dismisses.
No further editing is allowed in the textview, any edits makes the keyboard immediately dismiss.
Any suggestions on what changed with 7.1 that would make existing, working code break? Here is all the relevant code. I'll be happy to provide any additional details. I've been at this a while now and it's driving me mental.
tableViewController.m - The code that adds in the subview. The subview has it's own xib. The xib was created in IB. I stripped out the parts that pertain to other components.
- (void)viewDidLoad {
//Setup contentBar
if (self.contentBar == nil) {
//Add subView to View
NSArray *subviewArray = [[NSArray alloc] init];
subviewArray = [[NSBundle mainBundle] loadNibNamed:contentIdentifier owner:self options:nil];
self.contentBar = [subviewArray objectAtIndex:0];
[self.view addSubview:self.contentBar];
//Setup textView
UITextView *addContentTextView = (UITextView *)[self.contentBar viewWithTag:2];
addContentTextView.text = [NSString stringWithFormat:#"text (optional)"];
addContentTextView.delegate = self;
}
}
My textView delegates
#pragma mark - TextView Delegate
- (void)textViewDidEndEditing:(UITextView *)textView{
NSLog(#"textViewDidEndEditing:");
if ([textView.text isEqualToString:#""]) {
textView.text = #"text (optional)";
textView.textColor = [UIColor lightGrayColor]; //optional
}
[textView resignFirstResponder];
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(#"textViewDidBeginEditing:");
if ([textView.text isEqualToString:#"text (optional)"]) {
textView.text = #"";
textView.textColor = [UIColor blackColor]; //optional
}
[textView becomeFirstResponder];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text];
if ([newText length] > 0 || _image) {
_addContentButton.enabled = YES;
} else {
_addContentButton.enabled = NO;
}
if([text isEqualToString:[text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]]) {
return YES;
} else {
NSLog(#"return pressed");
[textView resignFirstResponder];
[self addedContent:nil];
}
return YES;
}
- (void)textViewDidChange:(UITextView *)textView
{
NSLog(#"textViewDidChange");
[self sizeTextView];
}
- (void)sizeTextView
{
NSLog(#"sizeTextView");
UIImageView *barImage = (UIImageView *)[self.contentBar viewWithTag:87];
UITextView *textView = (UITextView *)[self.contentBar viewWithTag:2];
CGSize sizeThatShouldFitTheContent = [textView sizeThatFits:textView.frame.size];
CGRect newTextViewFrame = textView.frame;
newTextViewFrame.size.height = sizeThatShouldFitTheContent.height;
CGFloat adjustment = sizeThatShouldFitTheContent.height - textView.frame.size.height;
newTextViewFrame.origin.y = textView.frame.origin.y - adjustment;
textView.frame = newTextViewFrame;
CGRect newImageViewFrame = barImage.frame;
newImageViewFrame.size.height = barImage.frame.size.height + adjustment;
newImageViewFrame.origin.y = barImage.frame.origin.y - adjustment;
barImage.frame = newImageViewFrame;
}
If you want to see anything else, I'll be glad to post it.
I have solved this issue by implementing the following:
Rewrote my tableview controller as a standard ViewController, not a TableViewController
Added a tableview to the ViewController and a separate "contentWrapper" view.
The content wrapper consists of the example shown here: https://github.com/datwelk/RDRStickyKeyboardView
I'm still not sure what in iOS 7.1 caused this issue, but using the RDRStickyKeyboardView works great and solved all of my issues.
I've read that tableviews shouldn't be parents of other views, so this solution also works well for good coding practice.
I have a Navigation Controller. I want to put the edit button on the bottom in the toolbar instead of in the top navigation bar.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
The problem I have is that when I add the edit button to the Bottom Toolbar. like this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.christmasGifts removeGiftAtIndexPath:indexPath];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:YES];
//Do not let the user add if the app is in edit mode.
if(editing)
self.navigationItem.rightBarButtonItem.enabled = YES;
else
self.navigationItem.rightBarButtonItem.enabled = YES;
}
And then link the edit button setEditing: in the toolbar it does not show a done button like the Edit button in the top navigation. it just stays the same.
But you can delete an item, but you cannot reset the state to normal again with the bottom button.
I need to be able to go back to the previous controller from this Navigation Controller. but the edit button hides the back button.
Edit.
I know I can by code add the toolbar.
UIBarButtonItem *editButton = [[UIBarButtonItem alloc]
initWithTitle:#"Edit"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(setEditing:)];
[[UIBarButtonItem appearance] setTintColor:[UIColor colorWithRed:70/255.0f green:155/255.0f blue:19/255.0f alpha:1.0]];
NSArray *arrBtns = [[NSArray alloc]initWithObjects:editButton,anotherButton, nil];
self.toolbarItems = arrBtns;
and
[self.navigationController setToolbarHidden:NO];
or even
UIToolbar *toolBar=[[UIToolbar alloc]initWithFrame:CGRectMake(0, 500, 400, 40)];
[self.tableView addSubview:toolBar];
In your ViewController.h, declare (and connect them in XIB)
#property (strong, nonatomic) IBOutlet UIToolbar *toolbar;
#property (strong, nonatomic) IBOutlet UIBarButtonItem *toolbarbutton;
- (IBAction)toolbarbuttonTouched:(id)sender; // Connect with UIBarButtonItem in XIB
In your ViewController.m, paste down the following function.
- (IBAction)toolbarbuttonTouched:(id)sender
{
if ([self.toolbarbutton.title isEqualToString:#"Edit"])
{
[self.tableView setEditing:YES animated:YES];
self.toolbarbutton.title = #"Done";
}
else
{
[self.tableView setEditing:NO animated:YES];
self.toolbarbutton.title = #"Edit";
}
}
And you are all set to go.
Points
Your UIBarButtonItem's initial value for property title must be
set to "Edit"
Code for editingStyle == UITableViewCellEditingStyleDelete should
be working perfectly
EDIT
You don't need the following code:
self.navigationItem.leftBarButtonItem = self.editButtonItem;
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:YES];
//Do not let the user add if the app is in edit mode.
if(editing)
self.navigationItem.rightBarButtonItem.enabled = YES;
else
self.navigationItem.rightBarButtonItem.enabled = YES;
}
Let me know, If it works for you or not.
I was able to do this more simply by using UIViewController's editButtonItem method:
- (void)viewDidLoad {
[super viewDidLoad];
// Place table view Edit button in toolbar, after existing buttons.
NSMutableArray *items = [self.toolbarItems mutableCopy];
[items addObject:self.editButtonItem];
[self setToolbarItems:items animated:YES];
}
This gets the existing array of toolbar buttons (if any) and makes a mutable copy of the array so it can be changed. It then adds UIViewController's built-in Edit button to the toolbar.
The result is a functioning Edit/Done toolbar button that toggles Edit mode on and off, without having to write your own action method to handle that.
Here is the set up of my view:
When the UIBarButtonItem is clicked, it should bring up a UIImagePickerController. I have to do this using a UIPopoverController, which is invoked by clicking on the "reset" button, because it is necessary on the iPad. Here is my code:
-(IBAction) btnReset:(id)sender {
[self chooseImage];
}
-(void) chooseImage {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagepicker = [[UIImagePickerController alloc] init];
imagepicker.allowsEditing = NO;
imagepicker.delegate = self;
imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagepicker.navigationBar.opaque = true;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];
[popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {
[self presentModalViewController:imagepicker animated:YES];
}
}
}
However, when this is called, the view crashes with the error:
'NSInvalidArgumentException', reason: '-[UIPopoverController presentPopoverFromRect:inView:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window.'
What am I doing wrong? Thank you in advance.
It looks like you are trying to create a popover on an item which is not on the view hierarchy. If this method is being invoked by your button then change the method header to -(void) chooseImage:(id)sender and try presenting the popover from the UIBarButton you have on your toolbar.
Also if you are using ARC (which it looks like you are) you have to hold on to your UIPopover otherwise it will be released when it is still required see this stack overflow post. You may already be doing this but I thought I would raise it as a I can't see if/how you have specified your popoverController.
Ive created a UIPopover Controller in my view controller which opens a popup that contains a list of items in it. Im wanting it so that if I choose an item in the list a label on the main view is updated to show this selection. Ive tried using the code below so far but when I click on an item on the list I get the following error: -[ASHAppDelegate portfolioLabel]: unrecognized selector sent to instance 0x6e4fe80
The code Ive used for the UIPopOverController is shown below:
-(IBAction) portFoliosButtonPress:(id)sender {
if (self.portfolioPopoverController == nil) {
ASHPortfolioViewController *portfoliosTableViewController = [[ASHPortfolioViewController alloc] initWithStyle:UITableViewStylePlain];
//CGSize frame = {portfoliosTableViewController.view.frame.size.width, 200.0};
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:portfoliosTableViewController];
CGSize frame = {300.0, 230.0};
[popover setPopoverContentSize:frame];
popover.delegate = self;
self.portfolioPopoverController = popover;
//self.contentSizeForViewInPopover.height = CGSizeMake(150.0, 140.0);
}
if ([self.portfolioPopoverController isPopoverVisible]) {
[self.portfolioPopoverController dismissPopoverAnimated:YES];
}
else {
[self.portfolioPopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
self.portfolioLabel.text = #"hi";
}
#pragma mark - Popover lifecycle
//---called when the user clicks outside the popover view---
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {
NSLog(#"popover about to be dismissed");
return YES;
}
//---called when the popover view is dismissed---
- (void)popoverControllerDidDismissPopover:
(UIPopoverController *)popoverController {
NSLog(#"popover dismissed");
}
The code used in my UITableView that the popover controller contains is shown below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ASHFirstViewController *appDelegate =(ASHFirstViewController *)[[UIApplication sharedApplication] delegate];
appDelegate.portfolioLabel.text = #"Test";
}
'portfolioLabel' is an IBOutlet UIlabel I have in my view controller.
I want to present a modal mail dialogue like so in the iPad app:
MFMailComposeViewController* picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:title];
[picker setMessageBody:[NSString stringWithFormat:[self emailBody], title, [link absoluteString]] isHTML:YES];
[self.viewController presentModalViewController:picker animated:YES];
The following delegate is called when the user sends/cancels:
- (void) mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self.viewController dismissModalViewControllerAnimated:YES];
}
This works great in portrait mode. In landscape mode the right hand pane of the UISplitViewController completely disappears.
You can only present these from the primary view of your application. In this case, presenting from the UISplitViewController works.