Deleted row in tableview is reappearing when navigating back - ios

Have friendsviewcontroller in which have uibarbuttonItem to edit friends list and other uibarbuttonitem to create groups for group chatrooms.
Have multiple segue for switching view controllers.
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Groups";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"New" style:UIBarButtonItemStylePlain target:self
action:#selector(actionNew)];
self.tableView.separatorInset = UIEdgeInsetsZero;
chatrooms = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([PFUser currentUser] != nil)
{
[self refreshTable];
}
else LoginUser(self);
}
#pragma mark - User actions
- (void)actionNew
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Create New Group" message:nil delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex=
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *textField = [alertView textFieldAtIndex:0];
if ([textField.text isEqualToString:#""] == NO)
{
PFObject *object = [PFObject objectWithClassName:PF_CHATROOMS_CLASS_NAME];
object[PF_CHATROOMS_NAME] = textField.text;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (error == nil)
{
[self refreshTable];
}
else [ProgressHUD showError:#"Network error."];
}];
}
}
}
- (void)refreshTable
{
[ProgressHUD show:nil];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
[chatrooms removeAllObjects];
for (PFObject *object in objects)
{
[chatrooms addObject:object];
}
[ProgressHUD dismiss];
[self.tableView reloadData];
}
else [ProgressHUD showError:#"Network error."];
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [chatrooms count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
PFObject *chatroom = chatrooms[indexPath.row];
cell.textLabel.text = chatroom[PF_CHATROOMS_NAME];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
//[chatrooms removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PFObject *chatroom = chatrooms[indexPath.row];
NSString *roomId = chatroom.objectId;
CreateMessageItem([PFUser currentUser], roomId, chatroom[PF_CHATROOMS_NAME]);
ChatView *chatView = [[ChatView alloc] initWith:roomId];
chatView.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:chatView animated:YES];
}
Deleted row in table view reappears when navigate back to the TableView
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
Im unable to locate what piece of code i m missing or what exactly i m doing wrong.
If anyone can please point out to that.
Will appreciate so much.
Thanks.

When committing deletion, your code removes objects from chatrooms which is data source of the table view in your case, but this happens in your app's memory, the source from which chatrooms is populated does not change. Thus, speaking in MVC, the app's model state is not updated after the view's state is changed.
Every time the table view is showed up, your code populates chatrooms in refreshTable, if the model's state hasn't been changed, the code gets same list as before, thus the table view doesn't change.
EDIT: Instead of using another approach to refresh the table view, you need to think about what does your app do in this table view. If user can delete stuff in the table view, should your app update model (This model can be a local or remote database, a property list file, etc.) too? If yes, then update model when user inserts or deletes rows in the table view; well, if not, then you are asking a question that is not a problem, or maybe the table view should turn off editing.
EDIT1:
If you do need to update data, based on your code, you may need to do something like this:
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query deleteChatroom:chatroom];
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
That is, you may need to implement method deleteChatroom: of class PFQuery.

Related

Whenever I try to save a NSUserDefualts to a NSMutableArray it crashes

I've been using NSUserDefualts. Whenever I try to save to a NSMutableArray it crashes the app. How would I fix this?
I tried to figure it out online, but it's been bringing up either swift or guides that don't support any of what I searched.
#import "scoutViewViewController.h"
#interface scoutViewViewController ()
#property (weak, nonatomic) IBOutlet UITableView *scoutView;
#end
BOOL check = YES;
#implementation scoutViewViewController
*tableData; // u need this for a standalone/ static one
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
tableData =[[NSUserDefaults standardUserDefaults] objectForKey:#"data_0"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
//segue select
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"show" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"show"]) {
}
}
//ediatable tableView
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableData removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self scoutView];
}
}
- (IBAction)addCell:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Team Name Or Number" message: #"" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
-(void) alertView:(UIAlertView *) alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
//only accept if the user hit ok
// need to implement "UIAlertController" becuase UIAlert is no longer used.
if(buttonIndex == 1){
NSString *temptxtfield = [alertView textFieldAtIndex:0].text;
if(!tableData){
tableData = [[NSMutableArray alloc]init];
}
if([temptxtfield isEqual: #""] || [temptxtfield isEqual: #" "]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Team Name Or Number" message: #"" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
check = NO; //check, nothing to do wiht the implemtaiont
}else{
check = YES;//check, nothing to do wiht the implemtaiont
}
if(check == YES){//check, nothing to do wiht the implemtaiont
[tableData insertObject:temptxtfield atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.scoutView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
check= NO;//check, nothing to do wiht the implemtaiont
}//check, nothing to do wiht the implemtaiont
//check is to prevent nothing to be placed into the tabel, nothing to do with how the data is inserted into the table
}
}
- (IBAction)saveTable:(id)sender {
[[NSUserDefaults standardUserDefaults] setObject: tableData forKey:#"data_0"];
}
-(void)save2{
}
#end
It gives me a SIGBART error when it crashes, I tried figuring out with break points but it's being a pain.
ended up figuring it out, pretty simple now that I think of it and I feel pretty dumb not knowing it beofore lol...
tableData = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"tabelSave"]];

I'm getting this error when I try to delete a row

I'm getting this error when I try to delete a row. Please who can help me!!!!
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 3. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
//
// InboxTableViewController.m
// Ribbit
//
// Created by OnMac on 24/11/14.
// Copyright (c) 2014 OnMac. All rights reserved.
//
#import "InboxTableViewController.h"
#import "ImageViewController.h"
#interface InboxTableViewController ()
#end
#implementation InboxTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.recipient = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:#"recipientIds"]];
NSLog(#"Delete: %#", self.selectedMessage);
self.moviePlayer = [[MPMoviePlayerController alloc] init];
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
NSLog(#"Currrent user: %#", currentUser.username);
}
else {
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
PFQuery *query = [PFQuery queryWithClassName:#"Message"];
[query whereKey:#"recipiendID" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else{
// We found messages!!!
self.messages = objects;
[self.tableView reloadData];
// NSLog(#"messages: %#", self.messages);
}
}];
}
else {
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
PFObject *message = [self.messages objectAtIndex:indexPath.row];
cell.textLabel.text = [message objectForKey:#"Username"];
// NSLog(#"ALT: %#", message);
NSString *fileType = [message objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
PFFile *im = [message objectForKey:#"file"];
NSData *resumeData = [im getData];
cell.imageView.image = [UIImage imageWithData:resumeData];
}
else{
cell.imageView.image = nil;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedMessage = [self.messages objectAtIndex:indexPath.row];
NSString *fileType = [self.selectedMessage objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
[self performSegueWithIdentifier:#"showImage" sender:self];
}
else{
// File type is video
PFFile *videoFile = [self.selectedMessage objectForKey:#"file"];
NSURL *fileUrl = [NSURL URLWithString:videoFile.url];
self.moviePlayer.contentURL = fileUrl;
[self.moviePlayer prepareToPlay];
// Add it to the view controller so we can see it
[self.view addSubview:self.moviePlayer.view];
[self.moviePlayer setFullscreen:YES animated:YES];
}
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[message1 deleteInBackground];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView reloadData];
}
- (IBAction)logout:(id)sender {
[PFUser logOut];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showLogin"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
else if ([segue.identifier isEqualToString:#"showImage"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
ImageViewController *imageViewController = (ImageViewController *)segue.destinationViewController;
imageViewController.message = self.selectedMessage;
}
}
#end
First, please edit your code more. You have more white space than actual code, and pasting that much white space just makes the process longer.
Second, try reading the error message. It's saying that you are deleting a row from the datasource when you aren't removing it from the table. What I suspect is happening is inside your commitEditingStyle method:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[message1 deleteInBackground];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView reloadData];
}
Look at what you're doing. There's a lot of issues here. First, you're deleting a message 100% of the time this method is called. That means you're always modifying your datasource. But look at your if statement - this means that you are not always deleting a row. Now you sometimes delete a message without deleting the row from the table. This WILL cause the crash.
Second - from what it sounds like, it sounds like you're deleting the message in the background. This is potentially a very bad thing. Why? Because if you're waiting on a delegate callback in an asynchronous fashion, then this will lead to very bad race conditions.
Your code should look like this:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[self.messages removeObject:message1];
[message1 deleteInBackground];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}
Note that I added [self.messages removeObject:message1] to make your dataSource consistent with the table immediately. I don't know what you were doing in [PFObject deleteInBackground], but if you weren't immediately removing the message object from your dataSource, then you can run into bad issues.

UITableViewCell doesn't display

I have a problem with my TableViewController. There is a custom cell, with a class, and various infos dynamically loaded. My TableViewController appears, but my cell doesn't display, but i can touch this, and my transition with infos are good.
Thanks for your answers.
TableViewController.m
#interface Chat() {
NSMutableArray *messages;
UIRefreshControl *refreshControl;
}
#property (strong, nonatomic) IBOutlet UITableView *tableMessages;
#end
#implementation Chat
NSString *cellIdentifier = #"ChatCell";
- (void)viewDidLoad {
[super viewDidLoad];
[_tableMessages registerClass:[ChatCell class] forCellReuseIdentifier:cellIdentifier];
refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(loadMessages) forControlEvents:UIControlEventValueChanged];
[_tableMessages addSubview:refreshControl];
messages = [[NSMutableArray alloc] init];
[self loadMessages];
}
- (void)loadMessages {
if ([PFUser currentUser] != nil)
{
PFQuery *query = [PFQuery queryWithClassName:PF_MESSAGES_CLASS_NAME];
[query whereKey:PF_MESSAGES_USER equalTo:[PFUser currentUser]];
[query includeKey:PF_MESSAGES_LASTUSER];
[query orderByDescending:PF_MESSAGES_UPDATEDACTION];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error == nil) {
[messages removeAllObjects];
[messages addObjectsFromArray:objects];
[_tableMessages reloadData];
} else [ProgressHUD showError:#"Network error."];
[refreshControl endRefreshing];
}];
}
}
- (void)actionCleanup {
[messages removeAllObjects];
[_tableMessages reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell bindData:messages[indexPath.row]];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
DeleteMessageItem(messages[indexPath.row]);
[messages removeObjectAtIndex:indexPath.row];
[_tableMessages deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PFObject *message = messages[indexPath.row];
ChatView *chatView = [[ChatView alloc] initWith:message[PF_MESSAGES_ROOMID]];
[self.navigationController pushViewController:chatView animated:YES];
}
#end
TableViewCell.m
#interface ChatCell() {
PFObject *message;
}
#end
#implementation ChatCell
- (void)bindData:(PFObject *)message_ {
message = message_;
_chatImg.layer.cornerRadius = _chatImg.frame.size.width/2;
_chatImg.layer.masksToBounds = YES;
PFUser *lastUser = message[PF_MESSAGES_LASTUSER];
[_chatImg setFile:lastUser[PF_USER_PICTURE]];
[_chatImg loadInBackground];
_chatUsername.text = message[PF_MESSAGES_DESCRIPTION];
_chatMessage.text = message[PF_MESSAGES_LASTMESSAGE];
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:message.updatedAt];
_chatDate.text = TimeElapsed(seconds);
}
#end
It's because you register the cell using - registerClass:forCellReuseIdentifier:.
If you register it this way you have to construct the view programmatically or load the nib file in ChatCell code.
To solve the problem, do either of these:
Create a nib file containing the view for your table view cell and set the class to ChatCell. Then use - registerNib:forCellReuseIdentifier: to register the nib.
Construct the view programmatically eg. create a UILabel and add it as a subview of ChatCell.
Make the prototype cell in the storyboard and set the cell identifier to ChatCell. Then remove the - registerClass:forCellReuseIdentifier:
Check You are given correct cell Identifier in storyboard. (case sensitive) " ChatCell"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"ChatCell";
ChatCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[cell bindData:messages[indexPath.row]];
return cell;
}
You are updating the UI on background thread. Try this, in your "loadMessages" method.
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
//update UI here
if (error == nil) {
[messages removeAllObjects];
[messages addObjectsFromArray:objects];
[_tableMessages reloadData];
} else [ProgressHUD showError:#"Network error."];
[refreshControl endRefreshing];
});
}];

UITableView not being updated after adding new items (using Core Data)

I use Core Data to keep track of entries in a simple to do list. I use a simple UIAlertView with UITextField for the user to add new entries. The entries are saved using NSManagedObject, but the latest entry isn't added to the tableview, even after I run [self.tableView reloadData];
This GIF show how it works now:
Header file:
#import <UIKit/UIKit.h>
#interface PakkelisteViewController : UITableViewController <UIAlertViewDelegate>
#end
Implementation file:
#import "PakkelisteViewController.h"
#import "AUFToDoItem.h"
#interface PakkelisteViewController ()
#property NSMutableArray *toDoItems;
-(IBAction)addNewToDoItem;
#end
#implementation PakkelisteViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// defaultTodos = [[NSMutableArray alloc] initWithObjects:#"Badetøy", #"Skrivesaker", #"Lommepenger", #"Godt humør", nil];
self.toDoItems = [[NSMutableArray alloc] init];
[self loadInitialData];
// 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;
}
-(void)viewWillAppear:(BOOL)animated
{
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"AUFToDoItem"];
self.toDoItems = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
}
-(void)loadInitialData
{
}
-(IBAction)addNewToDoItem
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Legg til ny" message:nil delegate:self cancelButtonTitle:#"Avbryt" otherButtonTitles:#"Legg til", nil];
[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[alertView textFieldAtIndex:0] setPlaceholder:#"Rent undertøy"];
[[alertView textFieldAtIndex:0] setAutocapitalizationType:UITextAutocapitalizationTypeSentences];
[alertView show];
}
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if ([inputText length] > 0)
{
return YES;
}
else
{
return NO;
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
NSManagedObjectContext *context = [self managedObjectContext];
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:#"itemName"];
[toDoItem setValue:[NSDate date] forKey:#"creationDate"];
[toDoItem setValue:NO forKey:#"completed"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
// [self.tableView reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.toDoItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
NSManagedObject *toDoItem = [self.toDoItems objectAtIndex:indexPath.row];
cell.textLabel.text = [toDoItem valueForKey:#"itemName"];
if ((BOOL)[toDoItem valueForKey:#"completed"] == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*
[tableView deselectRowAtIndexPath:indexPath animated:NO];
AUFToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
*/
}
-(NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[context deleteObject:[self.toDoItems objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Can't delete! %# %#", error, [error localizedDescription]);
return;
}
[self.toDoItems removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
You need to add the new toDoItem to your array as well. Try this :
// Create a new managed object
NSManagedObject *toDoItem = [NSEntityDescription insertNewObjectForEntityForName:#"AUFToDoItem" inManagedObjectContext:context];
[toDoItem setValue:[alertView textFieldAtIndex:0].text forKey:#"itemName"];
[toDoItem setValue:[NSDate date] forKey:#"creationDate"];
[toDoItem setValue:NO forKey:#"completed"];
[self.toDoItems addObject:toDoItem];
[self.tableView reloadData];
You should update your dataSource self.toDoItems as it still stays the same as off in viewDidLoad method. You're only saving it in CoreData, but not refreshing your dataSourse and [tableView reloadData] wont do anything

Saving Method for a button

this is my code in my .m file
#interface HomeWorkViewController ()
#end
#implementation HomeWorkViewController
#synthesize adView;
#synthesize myTableView, numbers;
-(void) viewDidLoad
{
adView.delegate=self;
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
// check here if key exists in the defaults or not, if yes the retrieve results in array
if([[NSUserDefaults standardUserDefaults] objectForKey:#"numberArray"] != nil) {
self.numbers = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"numberArray"]];
}
//Register for the notification when user go to background or minimize the app, just save the array objects in the defaults
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(appWillGoToBackground:)
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
//Add the Add button
UIBarButtonItem * addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target: self action: #selector(insertNewObject)];
self.navigationItem.rightBarButtonItem = addButton;
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.myTableView setEditing:editing animated:animated];
}
-(void)appWillGoToBackground:(NSNotification *)note {
NSLog(#"terminate");
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:self.numbers forKey:#"numberArray"];
[defaults synchronize];
}
-(void)insertNewObject{
//Display a UIAlertView
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Enter HomeWork" message: #"" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//Only perform the following actions if the user hits the ok button
if (buttonIndex == 1)
{
NSString * tmpTextField = [alertView textFieldAtIndex:0].text;
if(!self. numbers){
self.numbers = [[NSMutableArray alloc]init];
}
[self.numbers insertObject:tmpTextField atIndex:0];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.myTableView insertRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.numbers.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [ tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: cellIdentifier];
}
cell.textLabel.text = [self.numbers objectAtIndex:indexPath.row];
return cell;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
//remove our NSMutableArray
[self.numbers removeObjectAtIndex:indexPath.row];
//remove from our tableView
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
{
}
-(void)bannerViewDidLoadAd:(ADBannerView *)banner
{
adView.hidden=FALSE;
NSLog(#"Has ad, showing");
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
adView.hidden=TRUE;
NSLog(#"Has no ads, hiding");
}
-(void)dealloc
{
[adView release];
[super dealloc];
}
#end
I have a saving method there but I want to save everything that I changed in the table by clicking a button. How do i do that?
I want to put a toolbar with a button that says back to go to the home screen, and link this button to save everything that was done to the table like delete, switch order and add.
You're almost there :)
You are using the numbers array as the data model for the table.
Make sure that this array is always updated when the table is manipulated. (For example, you need to reorder the numbers array in moveRowAtIndexPath. Currently, you do nothing in that method)
To save the model using a button, just create a UIButton in the Interface Builder and connect it to the following action:
- (IBAction)saveButtonWasPressed:(id)sender {
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:self.numbers forKey:#"numberArray"];
[defaults synchronize];
}
Maybe you also want to pop the tableviewcontroller from the navigationcontroller stack if you also want to leave the controller.

Resources