I have 2 Controllers, 1 is to load data from JSON, the other is a simple UITableViewController. My problem is that the view is loaded before the data. How can I make the data load before my table? I'm new to Objective-C OOP :/
the code
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "DealsDataController.h"
#import "Deals.h"
#implementation MasterViewController
- (void)awakeFromNib
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
self.dataController = [[DealsDataController alloc] init];
NSLog(#"this is the awake from nib count %i",[self.dataController countOfList]);
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"did this count the list %i",[self.dataController countOfList]);
return [self.dataController countOfList];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"DealCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Deals *dealAtIndex = [self.dataController objectInListAtIndex:indexPath.row];
[[cell textLabel] setText:dealAtIndex.name];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
/*
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSDate *object = _objects[indexPath.row];
self.detailViewController.detailItem = object;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
}
*/
#end
and the Data Controller
#import "DealsDataController.h"
#import "Deals.h"
#implementation DealsDataController
#synthesize masterDealsList = _masterDealsList;
-(id)init {
if (self = [super init]) {
[self initializeDataList];
return self;
}
return nil;
}
-(NSMutableArray *)masterDealsList {
if (!_masterDealsList) {
_masterDealsList = [[NSMutableArray alloc] init];
}
return _masterDealsList;
}
-(void)setMasterDealsList:(NSMutableArray *)newList {
if (_masterDealsList != newList) {
_masterDealsList = newList;
}
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
_deals = [json objectForKey:#"deals"]; //2
NSLog(#"deals: %#", _deals);
NSArray *dealName = [_deals valueForKey:#"deal_name"];
NSLog(#"deals Name: %#", dealName);
for (int i = 1;i <= [_deals count]; i++) {
NSDictionary* dict = [_deals objectAtIndex:i-1];
Deals *deal =[[Deals alloc] initWithProdID:1 name:[dict valueForKey:#"deal_name"] description:[dict objectForKey:#"deal_description"] price:10.00 specs:#"specs" terms:#"terms"];
[self addDealWithDeal:deal];
NSLog (#"masterListCount %i ", [self countOfList]);
}
}
-(void)initializeDataList {
//NSDate *today = [NSDate date];
dispatch_async(sweetDealsQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:sweetDealsURL];
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
-(NSUInteger)countOfList {
return [self.masterDealsList count];
}
-(Deals *)objectInListAtIndex:(NSUInteger)theIndex {
return [self.masterDealsList objectAtIndex:theIndex];
}
-(void)addDealWithDeal:(Deals *)deal {
[self.masterDealsList addObject:deal];
}
#end
In MVC, you'd typically have one view controller per view. So a single view controller would be responsible for everything display on one view. Of course, you can have helper classes, or use sub view controllers (e.g. widgets), or if you're developing for iPad, you might have two view controllers (one for the side menu, one for the main view).
I'd suggest you do the following
Make your DataController a subclass of NSObject instead of UIViewController. From what I understand, it is a data access class, not responsible for UI.
In the viewDidLoad method of your MasterViewController, allocate and initialise a DataController object and trigger its data load method.
Either set a callback so when data is fetched, a method on the MasterViewController is called with the data. Or set your MasterViewController as a delegate for your DataController and when it's done, assign the data to a property of the MasterViewController.
i guess you need to perform Data loading before initialising your TableViewController and as you get response Data load the TableViewController. for that refer this post how to wait until some method complete execution, perform data loading in that method.
Its okay to display a blank tableview with an activity indicator overlay while the data is loading. When the data has finished loading, you can just reload the tableview with the data and remove the activity indicator. [tableview reloaddata] would call all of the datasource delegate methods which would then have your data in it.
Related
I followed this tutorial from AppCoda and I noticed that when I create another calendar, choose it (indicated by the checkmark beside it), then hit the Back button, the events in the main UIViewController view are not refreshed. I already added this code in my ViewController.m but nothing new happened:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.tblEvents == nil) {
NSLog(#"Your TableView becomes nil");
return;
}
[self.tblEvents reloadData];
}
Any ideas? Let me know if you need more information.
Edit:
.m
#import "MainViewController.h"
#import "AppDelegate.h"
#interface MainViewController ()
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) NSArray *arrEvents;
- (void)requestAccessToEvents;
- (void)loadEvents;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
[self performSelector:#selector(requestAccessToEvents) withObject:nil afterDelay:0.4];
[self performSelector:#selector(loadEvents) withObject:nil afterDelay:0.5];
[self.tblEvents reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tblEvents reloadData];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"idSegueEvent"]) {
EventViewController *eventViewController = [segue destinationViewController];
eventViewController.delegate = self;
}
}
#pragma mark - UITableView Delegate and Datasource method implementation
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%lu", (unsigned long)self.arrEvents.count);
return self.arrEvents.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"idCellEvent"];
// Get each single event.
EKEvent *event = [self.arrEvents objectAtIndex:indexPath.row];
// Set its title to the cell's text label.
cell.textLabel.text = event.title;
// Get the event start date as a string value.
NSString *startDateString = [self.appDelegate.eventManager getStringFromDate:event.startDate];
// Get the event end date as a string value.
NSString *endDateString = [self.appDelegate.eventManager getStringFromDate:event.endDate];
// Add the start and end date strings to the detail text label.
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", startDateString, endDateString];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
// Keep the identifier of the event that's about to be edited.
self.appDelegate.eventManager.selectedEventIdentifier = [[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier];
// Perform the segue.
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the selected event.
[self.appDelegate.eventManager deleteEventWithIdentifier:[[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier]];
// Reload all events and the table view.
[self loadEvents];
}
}
#pragma mark - EEventViewControllerDelegate method implementation
- (void)eventWasSuccessfullySaved
{
// Reload all events.
[self loadEvents];
}
#pragma mark - IBAction method implementation
- (IBAction)showCalendars:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueCalendars" sender:self];
}
}
- (IBAction)createEvent:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
}
#pragma mark - Private method implementation
- (void)requestAccessToEvents
{
[self.appDelegate.eventManager.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (error == nil) {
// Store the returned granted value.
self.appDelegate.eventManager.eventsAccessGranted = granted;
} else {
// In case of error, just log its description to the debugger.
NSLog(#"%#", [error localizedDescription]);
}
}];
}
- (void)loadEvents
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
self.arrEvents = [self.appDelegate.eventManager getEventsOfSelectedCalendar];
[self.tblEvents reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
To make UITableView work you need to set the delegate and datasource object like this..
in you ViewController.m file try to add Delegate and DataSource like this.
#interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
#end
now add these two lines in your view did load.
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
And check the implimentation of you Data Source methods like this
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//This method should return the number of rows you want to create in your tableView
return yourArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"yourCellIdentifier"];
//Now show what you want to show in your each cell? For Example you just want to show a simple text which is stored in you array.
cell.textLabel.text = [yourArray objectAtIndex:indexPath.row];
//indexPath.row is the numeric index number of each cell. This method will automatically execute exact the same number of time you return in above method.
return cell;
}
Now When your class/View Controller is open you might have zero data in your array and after some manipulation you got some data in your array Either by Call Web-Services/Loading from local Database/ by Passing Reference of array to next ViewController and on coming back to screen you want to refresh your TableView so now calling [tblEvents reloadData] will restart the process from numberOfRowsInSection method to cellForRowAtIndexPath method
I have a viewcontroller set up on my storyboard, and I have inserted a tableView inside this view controller. I want to do a [self.tableView reloadData].
This is what my viewController.m looks like. My tableView is an IBOutlet called sharedView, hence the names in the methods, but I am doing something wrong as on viewDidLoad when I call configureView, and subsequently [self.sharedView reloadData]; the data doesn't show up inside the table.
#import "DetailViewController.h"
#import "sharedUsersTable.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [[self.detailItem objectForKey:#"lock_name"] description];
activeUsers = [self.detailItem objectForKey:#"active_shared_users"];
[self.sharedView reloadData];
//NSLog(#"Info: %#", activeUsers);
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSString *)sharedView:(UITableView *)sharedView titleForHeaderInSection:(NSInteger)section {
return #"Shared with";
}
- (NSInteger)sharedView:(UITableView *)sharedView numberOfRowsInSection:(NSInteger)section
{
return activeUsers.count;
}
- (sharedUsersTable *)sharedView:(UITableView *)sharedView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"sharedUser";
sharedUsersTable *cell = [sharedView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[sharedUsersTable alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *key;
NSString *name;
NSString *email;
// NSString *permission;
key = [activeUsers objectAtIndex:indexPath.row];
name = [key objectForKey:#"shared_user_name"];
email = [key objectForKey:#"email"];
NSLog(#"Info: %#", name);
cell.textLabel.text = [NSString stringWithFormat:#"%#", name];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", email];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
#end
You should add info about protocols that Your VC is implementing:
#interface DetailViewController () <UITableViewDataSource, UITableViewDelegate>
- (void)configureView;
#end
and then:
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [[self.detailItem objectForKey:#"lock_name"] description];
activeUsers = [self.detailItem objectForKey:#"active_shared_users"];
/* I assume that Your table view is self.sharedView though You should change the name and I assume that it is connected to VC */
self.sharedView.dataSource = self;
self.sharedView.delegate = self;
[self.sharedView reloadData];
//NSLog(#"Info: %#", activeUsers);
}
}
You can also set data source and delegate directly in storyboard - I think that You have to ctrl+drag from table view to vc. Sorry if this is not correct - I do not use IB for quite some time no - only code.
And one more thing - read this:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UITableViewDataSource
And change method names to be exactly the same as in the protocol - If You do not It won't work.
For better undesstanding data sources and delegates try:
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/CreateConfigureTableView/CreateConfigureTableView.html
You mentioned that you are using a UIViewController and not UITableViewController. If you are using UIViewController then you will need to implement UITableViewDelegate and UITableViewDataSourceDelegate. You will also need to connect those delegates either through code or using the interface builder or Storyboard.
I'm new to programming. I am building a program that scans barcodes and puts the UPC number in the search box in my table view. Now all i want to do is create a search for the UPC scanned. the viewTable is displaying an inventory from a sqlite database.
The search bar is built all i need to do is program it to search, and I have not found any good tutorials on how to do this. How can I implement this?
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "ScanViewController.h"
#import <sqlite3.h>
#interface MasterViewController ()
{
NSMutableArray *_objects;
}
#end
#implementation MasterViewController
{
}
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Get the DBAccess object;
DBAccess *dbAccess = [[DBAccess alloc] init];
// Get the products array from the database
self.products = [dbAccess getAllProducts];
// Close the database because we are finished with it
[dbAccess closeDatabase];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [self.products count];
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
cell.accessoryType = UITableViewCellAccessoryNone;
Product* product = [self.products objectAtIndex:[indexPath row]];
cell.textLabel.text = product.serial;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Product *theProduct = _products[indexPath.row];
[[segue destinationViewController] setDetailItem:theProduct];
NSLog(#"this is prepare for segue");
}
}
- (void)scanditSDKOverlayController: (ScanditSDKOverlayController *)scanditSDKOverlayController
didScanBarcode:(NSDictionary *)barcodeResult
{
// add your own code to handle the barcode result e.g.
scanResult = [barcodeResult valueForKey:#"barcode"];
//barcodelabel.text = [NSString stringWithFormat:#"The barcode is: %#", scanResult];
searchLabel.text = [NSString stringWithFormat:#"%#", scanResult];
[self dismissViewControllerAnimated:YES completion:nil];
self.tableView.contentOffset = CGPointMake(0, 0 - self.tableView.contentInset.top);
[searchLabel becomeFirstResponder];
[super viewDidAppear:YES];
}
- (void)scanditSDKOverlayController: (ScanditSDKOverlayController *)scanditSDKOverlayController
didCancelWithStatus:(NSDictionary *)status
{
// add your own code to handle the user canceling the barcode scan process
}
- (void)scanditSDKOverlayController: (ScanditSDKOverlayController *)scanditSDKOverlayController
didManualSearch:(NSString *)input
{
// add your own code to handle user input in the search bar
// (only required if you use the search bar provided by the Scandit SDK
}
-(IBAction)scanClick:(id)sender;
{
ScanditSDKBarcodePicker *picker = [[ScanditSDKBarcodePicker alloc] initWithAppKey:#"oK1ckH/7EeOPhaseNDXmvNVu+pCX2y6UHZWZ/VYw0hE"];
picker.overlayController.delegate = self;
[picker startScanning];
[self presentViewController:picker animated:YES completion:nil];
//[[self navigationController]pushViewController:picker animated:YES];
[searchLabel becomeFirstResponder];
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
-(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
searchBar.text = nil;
[searchBar resignFirstResponder];
}
#end
I figured out my own question. for anyone who stumbles across this question, i used NSPredicate. i assumed that if there is a sqlite database then you cannot use NSPredicate, but i made it work. As long as the data is in an array..
I'm creating an iphone app using storyboard. I'm basically new on objective c and Xcode.
I have a list of categories, every time I click on a category it should open a tableView, so I can add an item in that category. But instead of getting a different tableView for each category, its the same table for all the categories and the added items are copied.
How can I create a new table for each label?
Thanks in advance!
Here's what I have for adding a category
#interface ListViewController ()
#end
#implementation ListViewController{
NSMutableArray *items;
}
#synthesize lists;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
items = [NSMutableArray arrayWithCapacity:20];
List *item = [[List alloc] init];
item.title = #"Grocery List";
[items addObject:item];
item = [[List alloc]init];
item.title = #"Project List";
[items addObject:item];
item = [[List alloc] init];
item.title = #"Events List";
[items addObject:item];
self.lists = items;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [self.lists count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell...
/*UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ListsCell"];
List *list = [self.lists objectAtIndex:indexPath.row];
cell.textLabel.text = list.title;*/
ListCell *cell = (ListCell *)[tableView dequeueReusableCellWithIdentifier:#"ListsCell"];
List *list = [self.lists objectAtIndex:indexPath.row];
cell.titleLabel.text = list.title;
return cell;
}
//Add new list, new row will be added on the bottom and its data source must always be sync
-(void)addViewControllerSave:(AddViewController *)controller addList:(List *)list{
[self.lists addObject:list];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.lists count] - 1 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
/*
// 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
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
if(editingStyle == UITableViewCellEditingStyleDelete){
[self.lists removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/* else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}*/
}
/*
// 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 story board-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.
if([segue.identifier isEqualToString:#"AddList"]){
UINavigationController *navigationController = segue.destinationViewController;
AddViewController *addViewController = [[navigationController viewControllers] objectAtIndex:0];
addViewController.delegate = self;
}
else if([segue.identifier isEqualToString:#"ViewItem"]){
UINavigationController *nav = segue.destinationViewController;
ItemViewController *itemViewController = [[nav viewControllers] objectAtIndex:0];
itemViewController.delegate = self;
}
}
#pragma mark - AddViewControllerDelegate
-(void)addViewControllerCancel:(AddViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)addViewControllerSave:(AddViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)itemViewControllerBack:(ItemViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Here's what I have for adding an item:
#interface ItemViewController ()
#end
#implementation ItemViewController{
NSMutableArray *newItems;
}
#synthesize items;
#synthesize delegate;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
newItems = [NSMutableArray arrayWithCapacity:20];
Item *i = [[Item alloc]init];
i.listItem = #"a";
[newItems addObject:i];
self.items = newItems;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Configure the cell...
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ItemsCell"];
Item *item = [self.items objectAtIndex:indexPath.row];
cell.textLabel.text = item.listItem;
return cell;
}
-(void)addIteViewControllerSave:(AddItemViewController *)controller addItem:(Item *)item{
[self.items addObject:item];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.items count] -1 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - Navigation
// In a story board-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.
if([segue.identifier isEqualToString:#"AddItem"]){
UINavigationController *navigationController = segue.destinationViewController;
AddItemViewController *addItemViewController = [[navigationController viewControllers]objectAtIndex:0];
addItemViewController.itemDelegate = self;
}
}
#pragma mark - AddItemViewControllerDelegate
-(void)addItemviewControllerCancel:(AddItemViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)addIteViewControllerSave:(AddItemViewController *)controller{
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - ItemViewControllerDelegate
-(IBAction)back:(id)sender{
[self.delegate itemViewControllerBack:self];
}
#end
AddItemViewController
#import "AddItemViewController.h"
#import "Item.h"
#interface AddItemViewController ()
#end
#implementation AddItemViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)cancel:(id)sender{
[self.itemDelegate addItemviewControllerCancel:self];
}
-(IBAction)save:(id)sender{
Item *item = [[Item alloc] init];
item.listItem = self.listItemTextField.text;
[self.itemDelegate addIteViewControllerSave:self addItem:item];
}
#end
Don't create a new table view for each label, instead populate it with different data for each label, you will need to change the object you are storing your data in and call
[tableView reloadData];
If all the added items you may need to clear out your array you are using to store the objects before adding the additional content.
[self.items removeAllObjects];
I have this problem that when my code executes and then I click on item on table, it takes me to detail view. Things display properly but in the console there is this message:
2013-03-27 13:09:30.616 LinkTest[3605:c07] Unbalanced calls to
begin/end appearance transitions for
.
I know that this is reported here often and looked through the answers, but nothing seems to work. Maybe I got something wrong. Here is the code for tableviewcontroller:
#import "EventListingTableViewController.h"
#import "EventListingDetailViewController.h"
#interface EventListingTableViewController ()
#end
#implementation EventListingTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)fetchEventDetails
{
NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://xsysdevelopment.com/ios/read.php"]];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
self.eventsTitles = [[NSMutableArray alloc] init];
self.eventsCity = [[NSMutableArray alloc] init];
for(id object in dict){
[self.eventsTitles addObject:object[#"title"]];
[self.eventsCity addObject:object[#"city"]];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self fetchEventDetails];
// 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)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.eventsTitles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
int row = [indexPath row];
cell.textLabel.text = self.eventsTitles[row];
cell.detailTextLabel.text = self.eventsCity[row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
EventListingDetailViewController *detailViewController = [[EventListingDetailViewController alloc] initWithNibName:#"EventListingDetailViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"eventDetailSeague"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
EventListingDetailViewController *detailViewController = [segue destinationViewController];
int row = [indexPath row];
detailViewController.eventDetails = #[self.eventsTitles[row], self.eventsCity[row]];
}
}
I will really appreciate it if someone tells me where I am going wrong. I am new to iOS so only helpful criticism would be useful.
regards
If you are using segues via storyboards for the UITableView then you don't need the code in didSelectRowAtIndexPath:. I believe you a firing a push twice due to this.