Edit Item in Bottom Toolbar Xcode and Objective C - objective-c

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.

Related

how to segue to a detail view from created tableview cell in Expandable/Collapsable UITableView

I am kinda new in Xcode and now I am working on a Expandable/Collapsable UITableView. The basic idea is to create new sub dropdown cells when the first master cell is clicked and subcells can segue to a detail view. But I hope to segue to a detail view from those new sub cells. I found there are two options:
Create a segue
Create a pushviewcontroller.
I dragged a new view controller and defined its storyboard ID, and tried to programmatically create a segue to push the new detail view. but it is not working. Could anyone help me? Thanks.
//didSelectRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//to change the button image when selecting a row.
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIButton *arrowBtn = (UIButton*)[cell viewWithTag:10];
NSDictionary *dic=[self.itemsinTable objectAtIndex:indexPath.row];
if([dic valueForKey:#"list"])
{
NSArray *listarray=[dic valueForKey:#"list"];
BOOL isTableExpanded=NO;
for(NSDictionary *subitems in listarray )
{
NSInteger index=[self.itemsinTable indexOfObjectIdenticalTo:subitems];
isTableExpanded=(index>0 && index!=NSIntegerMax);
if(isTableExpanded) break;
}
if(isTableExpanded)
{
[self CollapseRows:listarray];
[arrowBtn setImage:[UIImage imageNamed:#"down_arrow.png"] forState:UIControlStateNormal];
}
else
{
NSUInteger count=indexPath.row+1;
NSMutableArray *arrCells=[NSMutableArray array];
for(NSDictionary *dInner in listarray )
{
[arrCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.itemsinTable insertObject:dInner atIndex:count++];
}
[self.expandingtableView insertRowsAtIndexPaths:arrCells withRowAnimation:UITableViewRowAnimationTop];
[arrowBtn setImage:[UIImage imageNamed:#"up_arrow.png"] forState:UIControlStateNormal];
//This segue is not working...
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"detailvcontroller"];
[self.navigationController pushViewController:controller animated:YES];}}}
detailvcontroller *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"detailvcontroller"];
[self.navigationController pushViewController:controller animated:YES];
You need to check couple of things here:
Storyboard identifier for DetailViewController is set correctly.
self.storyboard is initialized correctly.
Root view have navigation Controller.
I just added below storyboard intialization code. Please ensure your self.storyboard is being set this way:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
DetailViewController *viewController = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"detailvcontroller"];
[self.navigationController pushViewController:controller animated:YES];

NSUserDefaults not appearing first appearence

So I've been learning iOS for the past couple months and have recently ran into this problem. I have a settings screen inside my app after a log in process that should save some basic information pertaining to the user. The issue is when the view first appears from a tab bar controller, the static grouped table view is blank with none of the information available for the cell.detailLabel.text. I used NSLog to discover that at first when retrieving the objects from keys, they are null. However, when I select a cell to change it's information and push on another view controller, I can then go back and all the values will appear from previous inputs saved to NSUser defaults. I was curious why this happens and for a solution. Thanks
#import "SettingsController.h"
#import <Parse/Parse.h>
#import "LogInViewController.h"
#import "AddSettings.h"
#import "AddUrination.h"
#import "ChooseAlarmController.h"
#interface SettingsController ()
#end
#implementation SettingsController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem *addUrination=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addUrinationView:)];
self.navigationItem.rightBarButtonItem=addUrination;
/*Rename the back button which every pushed on controller will have*/
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
NSLog(#"view loaded");
}
-(void)viewWillAppear:(BOOL)animated
{
/*Everytime view appears, we want to repopulate the table with updated content*/
NSLog(#"Settings View appeared,Load the keys");
/*Load every cell with appropiate details*/
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSIndexPath *path=[NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"FirstNameKey"];
NSLog(#"%#",cell.detailTextLabel.text);
path=[NSIndexPath indexPathForRow:1 inSection:0];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"LastNameKey"];
path=[NSIndexPath indexPathForRow:2 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"NumberOfUrinationsKey"];
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
path=[NSIndexPath indexPathForRow:0 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"StartingAlarmKey"];
path=[NSIndexPath indexPathForRow:1 inSection:1];
cell=[self.tableView cellForRowAtIndexPath:path];
cell.detailTextLabel.text=[defaults objectForKey:#"FinalAlarmKey"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)addUrinationView:(id)sender
{
[self performSegueWithIdentifier:#"AddUrinationSegue" sender:self];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// If Log Out Button is selected
if(indexPath.row==0 && indexPath.section==2){
NSLog(#"Log Out selected");
[PFUser logOut];
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Are You Sure?" message:#"If you would like to change your mind, press cancel. Otherwise choose log out" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Log Out", nil];
[alert show];
}
NSLog(#"Selected row is %ld %ld", (long)indexPath.section,(long)indexPath.row);
/*Segue depends on which cell is selected. First section segues to text input (AddSettings.h)*/
if((indexPath.section==0 && indexPath.row<2) || (indexPath.section==1 && indexPath.row==2)){
[self performSegueWithIdentifier:#"AddSettingSegue" sender:self];
}
/*Choose alarm controller is selected*/
if(indexPath.section==1 && indexPath.row<2){
[self performSegueWithIdentifier:#"AddAlarmSegue" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if([segue.identifier isEqualToString:#"AddSettingSegue"]){
AddSettings *settingsController=[segue destinationViewController];
/*index path contains both the section and row of the selected cell*/
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"Section:%ld Row:%ld",(long)indexPath.section,(long)indexPath.row);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
settingsController.titleOfController=cell.textLabel.text;
}
if([segue.identifier isEqualToString:#"AddUrinationSegue"])
{
AddUrination *addUrinationView=[segue destinationViewController];
}
if([segue.identifier isEqualToString:#"AddAlarmSegue"]){
ChooseAlarmController *alarm=[segue destinationViewController];
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
alarm.titleOfController=cell.textLabel.text;
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex==1){
[self performSegueWithIdentifier:#"UnwindToLogIn" sender:self];
}
}
#end
Add [super viewWillAppear:animated] to the top of your viewWillAppear: override. According to Apple's documentation for viewWillAppear:,
"If you override this method, you must call super at some point in your implementation."
While your application generally won't crash or anything if you omit it, important initialization performed by the base class will not occur unless you call [super viewWillAppear:animated], which may result in unexpected behaviour, such as label values not appearing in your table view cells.
As a best practice, you should always call the super method whenever you override one of Apple's methods, unless you explicitly do not want the default behaviour to occur (eg. overriding touchesBegan:withEvent:). Though there are exceptions, generally overridden initialization methods like viewDidLoad and viewWillAppear: should call their super method at the beginning of the method, while overridden teardown methods like viewWillDisappear: should call their super method at the end.

How to use UIPopoverController to edit a UIlabel

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.

Show or dismiss a specific ViewController after performing an action

I want to show a specific ViewController (or dismiss) a View after performing an IBAction in my iPhone App. I've tried
[self.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
However this does not appear to do anything once the action has been performed.
A bit more information:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if (selectedCell.tag == 1)
{
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"Are you sure you want to delete this project?"
delegate:self cancelButtonTitle:#"No" destructiveButtonTitle:#"Yes, I’m Sure" otherButtonTitles:nil];
[actionSheet showInView:self.view];
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [actionSheet cancelButtonIndex])
{
[self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException
// Delete the project object that was swiped
Project *projectToDelete = self.project;
NSLog(#"Deleting (%#)", projectToDelete.name);
[self.managedObjectContext deleteObject:projectToDelete];
[self.managedObjectContext save:nil];
}
}
I want the current view to disappear when a user presses the Yes button on the actionsheet.
// Assume we are inside a UIViewController (or a subclass)
DestinationController *destinationController = [[DestinationController alloc] init];
[self presentModalViewController:destinationController animated:YES];
...
// Assume we are now in destination controller
// Dismiss
[self dismissModalViewControllerAnimated:YES];
I needed to go all the way back to the first (or, root) view in my navigation stack.
All I need to do was use this method:
[controller.navigationController popToRootViewControllerAnimated:YES];
Another way to show and dismiss a view controller is with pushViewController and popViewController.
To show a viewController:
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
// Uses a horizontal slide transition. Has no effect if the view controller is already in the stack.
And to dismiss:
-(UIViewController *)popViewControllerAnimated:(BOOL)animated; // Returns the popped controller.

PopOver and Tableviews

Quick question on popovers, i seem not grasp a way of closing a popview when i select something from it (tableview)
so i have a list items on a tableview which popup using a UIPopoverController so when i select an item i'd like to the popove to fade away.
MainViewController
- (IBAction)popoverFontName:(id)sender
CGRect popoverRect = [self.view convertRect:[popoverFontName frame]
fromView:[popoverFontName superview]];
TitleController *titleC=[[TitleController alloc]init];
popup =[[UIPopoverController alloc]initWithContentViewController:titleC];
[popup presentPopoverFromRect:popoverRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[popup setPopoverContentSize:CGSizeMake(50.0, 300.0)];
[titleC release];
}
TitleController
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedLang = [titleList objectAtIndex:indexPath.row];
//Initialize the detail view controller and display it.
MyDetViewCont *myDetViewCont = [[MyDetViewCont alloc] initWithNibName:#"myDetViewCont" bundle:[NSBundle mainBundle]]; // view controller instance
}
On the title contoller i dont know how to dismiss the popover
You can call dismissPopoverAnimated: on the popoverController. You should keep an instance of your popover as an instance variable in order to dismiss from the UITableViewDelegate methods.