Trigger setEditing: animated: without using an edit button - objective-c

I have a UITableView with some custom cells in it. In these custom cells I defined a UILongPressGestureRecognizer that triggers the edit mode of this table. So when someone presses and holds a cell for like 1.5 sec, the table goes into edit mode.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(startEditMode:)];
Which triggers:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
[table setEditing:YES animated:YES];
}
}
But what I want to do is detect when the table goes into edit mode because I need to show/hide some additional buttons in this case. But for some reason in my viewcontroller this is never executed:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
NSLog(#"SET EDITING");
[super setEditing:editing animated:animated];
}
Any suggestion why? Is this just being called when using a proper Edit Button as provided by default in the UINavigationController?
Or how can I detect when my UITableView goes into Edit Mode?

You're sending the message (setEditing) to the table view, you should be sending it to the view controller (presumably a UITableViewController subclass?). It will then take care of the table view for you.

Ok so in case someone else walks into this thread with the same problem, I will show you how I solved this.
In my custom UITableViewCell I have this method now:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
UITableViewController *control = (UITableViewController *)table.dataSource;
[control setEditing:YES animated:YES];
}
}

Related

Toggle edit button to done

Been trying to get the button to change from "edit" to "done". I am doing a tutorial and it seems to work on their end but not mine. I can't seem to find the issue.
The code:
- (IBAction)onEditButtonTapped:(UIBarButtonItem *)sender {
[self.tableView setEditing:true animated:true];
sender.style = UIBarButtonItemStyleDone;
sender.title = #"Done";
}
You are doing it the hard way. UIViewController already provides such a button.
Lets assume you want this button on the right side of the navigation bar.
In viewDidLoad, you want:
self.navigationItem.rightBarButtonItem = [self editButtonItem];
Then to handle the button, simply override the setEditing:animated: method:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
}
The button returned by the editButtonItem method is setup to call the setEditing:animated: method for you. There's no setup required.
I assume this means you have added your own table view to a UIViewController. If you are using a UITableViewController then you don't need the call to self.tableView setEditing... since it is already done for you.
If you really want to use your own button. Make sure you set the possibleTitles property of the UIBarButtonItem.

How to handle users pressing back button too quickly after pushing a viewController?

Usually after the viewController is pushed, I want to do certain things. In add phone feature, for example, I would open edit business and set the focus to the phone field.
If after viewController is pushed users press back button too quickly the app crash.
What's the standard way to do so?
This is the code:
+(BGBusinessEditViewController *) pushNewEditViewControllerWithBizandReturnValue: (Business *)biz withNavController :(UINavigationController *) nav andSelectPhone:(BOOL) selectPhoneAfterward
{
BGBusinessEditViewController * editBusiness = [[BGBusinessEditViewController alloc]init];
//[editBusiness view];//load the stuff first
[nav vPushViewController:editBusiness animated:YES andPerformBlock:^{
if (biz) {
editBusiness.biz=biz; //viewDidload must be called first before setting bizs
}
if (selectPhoneAfterward)
{
[editBusiness selectPhone];
}
}];
return editBusiness;
}
-(void) selectPhone
{
NSIndexPath * ipth =[NSIndexPath indexPathForItem:BGBusinessEditTextPhoneNumber inSection:0];
[self.tableView selectRowAtIndexPath: ipth animated:NO scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:ipth];
}
Basically I created a category in nav View Controller that will run code only when the navigation controller already reach - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
Well, Hide the back button until viewDidAppear, and then unhide it.

Need a really simple navigation controller with a table view inside a tab bar controller

I have an app with a tab bar controller (2 tabs). In one tab view controller, a button leads to an alert window. I want one button of the alert window to call a table view containing possible answers. I want that table view to have a done button and a title. I think that means a navigation controller has to be used. But most everything I can find on navigation controllers assumes a much more complicated situation. Here's part of the alert window logic:
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 2) {
AnswersViewController *aVC = [[AnswersViewController alloc] init];
[self presentViewController:aVC
animated:YES
completion:NULL];
}
}
And AnswersViewController looks like this:
#interface AnswersViewController : UITableViewController
#end
#implementation AnswersViewController
- (id) init
{
self = [super initWithStyle:UITableViewStylePlain];
return self;
}
- (id) initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[self view] setBackgroundColor:[UIColor redColor]];
}
#end
This code all works as expected (an empty red UITableView appears).
Two questions I guess: 1. Is there a simple modification to what I have that can give me a done button and title in my table view? 2. If I have to go to a navigation controller (probably), how can I make a bare-bones navigation controller with a done button and title and embed the table view within it? Oh, and I want to do this programatically. And I think I prefer the done button and title to be in the navigation bar, no tool bar desired. Thanks!
To get what you are looking for, you do need to use a UINavigationController. That will provide the UINavigationBar where you can display a title and also buttons.
To implement this with a UINavigationController, you want to do smoothing like this (assuming you are using ARC, so you don't need to worry about memory management):
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 2) {
AnswersViewController *aVC = [[AnswersViewController alloc] init];
//Make our done button
//Target is this same class, tapping the button will call dismissAnswersViewController:
aVC.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissAnswersViewController:)];
//Set the title of the view controller
aVC.title = #"Answers";
UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:aVC];
[self presentViewController:aNavigationController
animated:YES
completion:NULL];
}
}
Then you would also implement - (void)dismissAnswersViewController:(id)sender in the same class as the UIAlertView delegate method (based on the implementation I have here).
Hope this helps!

How to update DetailView using MasterDetail Application Template

I'm new to using the split view for creating iPad applications. When I first create the project just using the standard MasterDetail Application template (Xcode 4.2), it creates a MasterViewController and a DetailViewController. The template has the following method that is called when a row is selected from the popover table (master detail view controller):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
if (!self.detailViewController)
{
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
[self.navigationController pushViewController:self.detailViewController animated:YES];
Now I understand when you are using a regular navigation controller if you are programing for an iPhone you just do this type of thing to push on another view controller on to the stack. However, with this template, it just pushes the detail view onto the popover rather than updating what is already present. I'm confused as what I need to update to select something from the pop over (master detail view), and then have the detailView update.
Update:
To try and test out the "detailItem" that is already setup for you in the DetailViewController, I commented out the pushViewController and added the following:
//[self.navigationController pushViewController:self.detailViewController animated:YES];
self.detailViewController.detailItem = #"Test";
// setter in detailViewController
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
// detailDescriptionLabel.text is a IBOutlet to the label on the detailView
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
According to this code, the text of the label on the detailViewController should be updated. However, when I do click on the item in the master view controller table, nothing happens.
There are a couple different ways you could do it. First off, like you said, remove the pushViewController call (I don't know why Apple's template does this... maybe just to show you you can?).
Next, let your MasterViewController know about the DetailViewController that is already displayed. I usually set master.detailViewController = detailViewController in the appDelegate.
Remember, the DetailViewController is already being displayed, so you won't always need to realloc it (unless you are replacing it with some other view)
First Option
Use delegate calls to set the information. Declare a protocol to pass information to the detailView and have it display it appropriately. Here is a tutorial describing this in more detail.
Second Option
Pass DetailViewController some data & override the setter to refresh the detailView. Here is a tutorial describing this in more detail.
// in DetailViewController
- (void)setDetailItem:(id)newDetailItem {
if (detailItem != newDetailItem) {
[detailItem release];
detailItem = [newDetailItem retain];
// Update the view.
navigationBar.topItem.title = detailItem;
NSString * imageName = [NSString stringWithFormat:#"%#.png",detailItem];
[self.fruitImageView setImage:[UIImage imageNamed:imageName]];
}
}
Edit: Just looked at the template again, and setDetailItem type code is already in there, but the code is creating a completely new detailView so the detailView that is viewable on the splitViewController is not changed at all.

Change UITextfield on a detailview by clicking on different Cells

This is what I have so far:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row)
{
// row 0 -> DetailViewController1 anzeigen...
case 0:
{
TableViewController *fvController = [[TableViewController alloc] initWithNibName:#"TableViewController" bundle:[NSBundle mainBundle]];
fvController.selectedCellItem = selectedCellItem;
[self.navigationController pushViewController:fvController animated:YES];
[fvController release];
fvController = nil;
}
break;
default:
break;
}
So my question is: How can I change a UITextfield of the detailView by selecting a cell. Thank you for your help so far;)
Do you want to edit the text in a UITextField in a cell? If so, there are a few ways you can do this, I'll touch on two of them.
First, why don't u just edit the cell right from within the tableView? This entails you to keep track of each cell's contents but if you always have a custom cell with a UITextField in it, you're half way there.
If you want to make changes to the text in a regular cell, then the user selects it and you give them an edit screen, this is a lot simpler. You can have your tableView push a view controller with a textField that has the text from your cell. They can edit this textField, and then press save. When they save, pop the view off the stack, save the changes to the data model, and update the tableView.
I'm not sure exactly what you're trying to do, but having a textField in a cell and then making edits in a detail screen seems redundant.
If you provide us with a little more info, I'm sure we can help.
UPDATE based on your clarification
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row)
{
// row 0 -> DetailViewController1 anzeigen...
case 0:
{
ViewControllerName *vController = [[UIViewController alloc] initWithNibName:#"ViewControllerName" bundle:[NSBundle mainBundle]];
vController.textField.text = //set the text here from the data source. Assuming textField is an property of vController.
[self.navigationController pushViewController:vController animated:YES];
[vController release];
}
break;
default:
break;
}