UITableView not displaying data. - ios

I'm new to iOS and just trying to get data to display in UITableView. I basically have a project set up about authors. I want to display author names etc. So i have an Author model and AuthorsViewController which is a datasource and delegate for UITableView etc. I'm using storyboard (MainStoryboard) tableview and managed to connect it to AuthorsViewController in the "Identity Inspector".
Image of Storyboard if it helps, thanks:
Here, first, is the model: Author.h
#import <Foundation/Foundation.h>
#interface Author : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *book;
#property (nonatomic) int year;
#end
Author.m
#import "Author.h"
#implementation Author
#end
Here is the AuthorsViewController.h
#interface AuthorViewController : UITableViewController
<UITableViewDataSource, UITableViewDelegate>
#end
And AuthorsViewController.m
#import "AuthorViewController.h"
#interface AuthorViewController ()
#property (nonatomic, strong) NSMutableArray *authors;
#end
#implementation AuthorViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_authors = [[NSMutableArray alloc] init];
Author *auth = [[Author alloc] init];
[auth setName:#"David Powers"];
[auth setBook:#"PHP Solutions"];
[auth setYear:2010];
[_authors addObject:auth];
auth = [[Author alloc] init];
[auth setName:#"Lisa Snyder"];
[auth setBook:#"PHP security"];
[auth setYear:2011];
[_authors addObject:auth];
auth = [[Author alloc] init];
[auth setName:#"Rachel Andrew"];
[auth setBook:#"CSS3 Tips, Tricks and Hacks"];
[auth setYear:2012];
[_authors addObject: auth];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_authors count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"AuthorCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell != nil)
{
cell = [[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Author *currentAuthor = [_authors objectAtIndex:[indexPath row]];
[[cell textLabel] setText: [currentAuthor name]];
NSLog(#"%#", [currentAuthor name]);
return cell;
}
#end

Since you made the table view with its cell in the storyboard, you don't need the if (cell == nil) clause at all. You also need to call [self.tableView reloadData] as the last line in viewDidLoad.

Related

UITableView programatically added to View Controller won't populate

I've programmatically created a UITableView within my MatchCenterViewController, however it doesn't seem to populate with the JSON data being returned by my cloud code function. It simply shows a blank View Controller. MatchCenterViewController is a ViewController embedded within a Navigation View Controller.
MatchCenterViewController.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"
#interface MatchCenterViewController : UIViewController <UITableViewDataSource>
#property (nonatomic) IBOutlet NSString *itemSearch;
#property (nonatomic, strong) NSArray *imageURLs;
#property (strong, nonatomic) NSString *matchingCategoryCondition;
#property (strong, nonatomic) NSString *matchingCategoryLocation;
#property (strong, nonatomic) NSNumber *matchingCategoryMaxPrice;
#property (strong, nonatomic) NSNumber *matchingCategoryMinPrice;
#property (strong, nonatomic) NSArray *matchCenterArray;
#end
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [_matchCenter dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *matchCenterDictionary= [self.matchCenterArray objectAtIndex:indexPath.row];
cell.textLabel.text = [matchCenterDictionary objectForKey:#"Title"];// title of the first object
// if([matchCenterDictionary objectForKey:#"Price"] != NULL)
// {
// cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#",[matchCenterDictionary objectForKey:#"Price"]];
// }
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:#"MatchCenterTest"
withParameters:#{
#"test": #"Hi",
}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
self.matchCenterArray = [result objectForKey:#"Top 3"];
dispatch_async(dispatch_get_main_queue(), ^{
[_matchCenter reloadData];
});
NSLog(#"Test Result: '%#'", result);
}
}];
}
#end
How do you create this viewController? If you don't use [[MatchCenterViewController alloc] initWithNibName:... bundle:...] the table creation won't be called. This might happen because you have the viewController in a storyBoard, in this case initWithCoder: would be the method to overwrite.
I would recommend to move this code to viewDidLoad, which will be called regardless how the viewController was created . E.g.:
- (void)viewDidLoad {
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
self.matchCenterArray = [[NSArray alloc] init];
}

my method definition is not found but i'm not sure why

I have a storyboard with tabbed browsing. One of the tabs is a table view. The table is populated by a list of animal "titles". when the title is pressed, a detailed view is opened that displays the title in addition to a sound and the number of times that the animal has been clicked. I have a view controller set up. I also have item.h/m and itemstore.h/m. there is also a detailedviewcontroller. my current problem is that in the item store i have two arays set up but right off the bat xcode is telling me that method definitions aren't found. its also giving my undeclared identifier errors.
FSAnimalsViewController.h (this is my table view controller)
#import <AVFoundation/AVAudioPlayer.h>
#import <UIKit/UIKit.h>
#import "FSDetailViewController.h"
#interface FSAnimalsViewController : UITableViewController
{
}
#end
FSAnimalsViewController.m
#import "FSAnimalsViewController.h"
#import "FSItemStore.h"
#import "FSItem.h"
#implementation FSAnimalsViewController
- (id)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
UINavigationItem *n = [self navigationItem];
[n setTitle:#"FoxSays"];
// Create a new bar button item that will send
// addNewItem: to ItemsViewController
[[self navigationItem] setLeftBarButtonItem:[self editButtonItem]];
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
- (id)initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (void)tableView:(UITableView *)aTableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FSDetailViewController *detailViewController = [[FSDetailViewController alloc] init];
NSArray *items = [[FSItemStore defaultStore] allItems];
FSItem *selectedItem = [items objectAtIndex:[indexPath row]];
// Give detail view controller a pointer to the item object in row
[detailViewController setItem:selectedItem];
// Push it onto the top of the navigation controller's stack
[[self navigationController] pushViewController:detailViewController
animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[[FSItemStore defaultStore] allItems] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Set the cell identifier
static NSString *CellIdentifier = #"BasicCell";
// Reuse the cell from the identifier
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell if it doesn't exist
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Log the row for debugging
NSLog(#"%d", [indexPath row]);
// Get object from store
FSItem *item = [[[FSItemStore defaultStore] allItems] objectAtIndex:[indexPath row]];
// Set label to from property in object
[[cell textLabel] setText:[item title]];
return cell;
}
#end
FSItem.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface FSItem : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic) SystemSoundID *sound;
#property (nonatomic) int plays;
- (NSArray *)animals;
- (NSArray *)sounds;
#end
FSItem.m
#import <AudioToolbox/AudioToolbox.h>
#import "FSItem.h"
#implementation FSItem
NSString *title;
SystemSoundID *sound;
int plays;
- (NSArray *)animals
{
NSArray *animals = [NSArray arrayWithObjects:#"Dog",#"Cat",#"Bird",#"Mouse",#"Cow",#"Frog",#"Elephant",#"Duck",#"Fish",#"Seal",#"Fox", nil];
return animals;
}
- (NSArray *)sounds
{
NSArray *sounds = [NSArray arrayWithObjects:
#"Woof.mp3",
#"Meow.mp3",
#"tweet.mp3",
#"Squeak.mp3",
#"Moo.mp3",
#"Croak.mp3",
#"Toot.mp3",
#"Quack.mp3",
#"Blub.mp3",
#"OWOwOw.mp3",
#"Fox.mp3",
nil];
return sounds;
}
#end
FSItemStore.h
#import <AVFoundation/AVAudioPlayer.h>
#import <AudioToolbox/AudioToolbox.h>
#import <Foundation/Foundation.h>
#class FSItem;
#interface FSItemStore : NSObject
{
NSMutableArray *allItems;
}
#property (nonatomic) int i;
+ (FSItemStore *)defaultStore;
- (NSArray *)allItems;
- (NSArray *)animals;
- (NSArray *)sounds;
- (FSItem *)createItem;
#end
FSItemStore.m
#import <AudioToolbox/AudioToolbox.h>
#import "FSItem.h"
#import "FSItemStore.h"
#implementation FSItemStore
int i = 0;
- (NSArray *)allItems
{
return allItems;
}
+ (FSItemStore *)defaultStore;
{
static FSItemStore *defaultStore = nil;
if(!defaultStore)
defaultStore = [[super allocWithZone:nil] init];
return defaultStore;
}
- (FSItem *)createItem
{
FSItem *item = [[FSItem alloc] init];
if (i < [animals count])
{
[item setTitle: [animals objectAtIndex: i]];
[item setSound: [sounds objectAtIndex: i]];
[item setPlays: 0];
i++;
[allItems addObject: item];
}
return item;
}
#end
FSItemStore is where my problems seem to be. Its saying that method definition for sounds and animals isn't found and both sounds and animals are undeclared identifiers. Anyone got any ideas?
Your problem is that in your H file you are declaring that your class will implement a method called animals that will return an NSArray, and a method call sounds that will return another NSArray, but in your M file you are not implementing these methods.
In your FSItemStore.m you should implement these methods:
- (NSArray *)animals{
//Do whatever this method is supposed to do, return an NSArray.
}
- (NSArray *)sounds
{
//Do whatever this method is supposed to do, return an NSArray.
}
EDIT
If what you pretend is that FSItemStore inherits the methods from FSItem, you have to declare the interface that way:
#interface FSItemStore : FSItem //FSItem instead of NSObject
{
NSMutableArray *allItems;
}
If I understood your code correctly you want to set one of the animals and sounds initialized in FSItem::sounds and FSItem::animals to the new item that you create in FSItemStore::createItem. So the animals and sounds methods should be executed ont eh correct object - the FSItem object. Change your code in FSItemStore::createItem to this -
- (FSItem *)createItem
{
FSItem *item = [[FSItem alloc] init];
if (i < [animals count])
{
[item setTitle: [[item animals] objectAtIndex: i]];
[item setSound: [[item sounds] objectAtIndex: i]];
[item setPlays: 0];
i++;
[allItems addObject: item];
}
return item;
}
This is still a bad way of doing what you want, as the NSArray will be initialized everytime you create an item. If the number of sounds and animals is fixed, better define them so that they just get initialized once e.g. static objects in FSItem or property on FSItemStore
You haven't defined any properties or variables that are called animals or items. You have only defined the getter methods.
e.g.
#property(nonatomic,strong) NSArray *animals;
#property(nonatomic,strong) NSArray *items;
Then the implementation of your getters, would return these properties.

Memory keep increasing when the UITableView scrolling

there is a strange problem I have not met ever
there is an array() including some custom object named MyClass parsed by JSONKit;
when I keep scrolling the tableview the memory will keeping increasing too.
but when replace
cell.textLabel.text = myclass.name;
with
cell.textLabel.text = #"cool";
or
cell.textLabel.text = [NSString stringWithFormate:#"a-%d", indexPath.row];
it's ok the memory with keep stable
but if I use
cell.textLabel.text = [NSString stringWithFormate:#"a-%#-i",myclass.name, indexPath.row];
it also keep increasing;
It will drive my crazy!!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Singers";
OMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
MyClass *myclass = [self.data objectAtIndex:indexPath.row];
if (cell == nil){
cell = [[[OMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
cell.textLabel.text = myclass.name;
return cell;
}
MyClass
there is two class one Base another inherit
Base:
#interface OMBase : NSObject {
NSMutableDictionary *data;
NSString *name;
NSArray *keys;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, copy) NSMutableDictionary *data;
#implementation OMBase
#synthesize data, name;
- (void)setData:(NSMutableDictionary *)adata{
if (data){
[data release];
data = nil;
}
data = [adata mutableCopy];
}
- (void)dealloc{
if (keys){
[keys release];
}
[data release];
[super dealloc];
}
- (id)init{
if (self = [super init]){
self.data = [[[NSMutableDictionary alloc] initWithCapacity:20] autorelease];
}
return self;
}
inherit:
#import "OMBase.h"
#interface OMLyric : OMBase
- (NSString *)songid;
- (NSString *)content;
#import "OMLyric.h"
#implementation OMLyric
- (NSString *)songid{
return [data objectForKey:#"songid"];
}
- (NSString *)content{
return [data objectForKey:#"content"];
}
Seems like your myclass.name getter returns a new allocated object. We can't say more without seeing myclass.

Xcode Data Controller Issue

I have an application that has the following parts:
StoreDataController.h
StoreDataController.m
StoreTableViewController.h
StoreTableViewController.m
I created a property & method in StoreDataController that retrieves data from a URL and converts it to JSON. I then store it in an Array. I'm trying to get the table controller to display the array in the table but it isn't displaying. What do I need to do to have the Table display the contents of the array? Here is the code I have:
StoreDataController.h
#interface StoreDataController : NSObject
#property (nonatomic, retain) NSArray *storeNames;
-(void)addStoreNamesObject:(NSArray *)storeNames;
#end
StoreDataController.m
#import "StoreDataController.h"
#import "SBJson.h"
#implementation StoreDataController
-(void)addStoreNamesObject:(NSArray *)storeNames
{
NSString *strURL = [NSString stringWithFormat:#"http://10.247.245.87/stores/dodge.php"];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
storeNames = [strResult JSONValue];
}
#end
StoreTableViewController.h
#import <UIKit/UIKit.h>
#class StoreDataController;
#interface StoreTableViewController : UITableViewController
#property (nonatomic, retain) StoreDataController *storeNameController;
#end
StoreTableViewController.m
#import "StoreTableViewController.h"
#import "StoreDataController.h"
#interface StoreTableViewController ()
#end
#implementation StoreTableViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _storeNameController.storeNames.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [_storeNameController.storeNames objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
You at least need something to set the storeNameController property inside your StoreTableViewController so that it references the StoreDataController object that is doing the work of building the array.
How you do that depends on what creates the StoreDataController object and how that's related to your view controller.
(Aside: In general, you should use self.propertyName instead of _propertyName.)

UITableView doesn't display Address Book

I think I'm not getting the handle on address book and UITableView, or maybe I'm just making it simpler than it is.
here is my .h file:
#interface Contacts : UITableViewController <ABPeoplePickerNavigationControllerDelegate> {
NSMutableArray *menuArray;
NSString *firstName;
NSString *lastName;
UIButton *addcontact;
}
#property (nonatomic, retain) NSMutableArray *menuArray;
#property (nonatomic, strong) UIButton *addcontact;
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
-(void)showPeoplePickerController;
#end
And my .m file:
-(IBAction)addcontact:(id)sender {
ABPeoplePickerNavigationController *peoplePicker=[[ABPeoplePickerNavigationController alloc] init];
[peoplePicker setPeoplePickerDelegate:self];
[self presentModalViewController:peoplePicker animated:YES]; }
- (void)viewDidLoad
{
menuArray = [[NSMutableArray alloc] init];
[super viewDidLoad];
}
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
firstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
[menuArray addObject:firstName];
lastName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
[menuArray addObject:lastName];
[self dismissModalViewControllerAnimated:YES];
return NO;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [menuArray 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];
}
NSString *cellValue = [menuArray objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
I hope someone could help me with it, I'm fairley new to UITableViews and Addressbooks :)
For performance purposes (not to mention animation purposes), UITableView does not automatically update itself whenever the data source changes.
Try adding [myTableView reloadData]; after you add the first and last name to the arrays (or in viewWillAppear:

Resources