My second level detail controller is not showing the initWithObjects in my array in the viewDidLoad method - objective-c

I am creating a Two Level table view. And the second view is supposed to have the list of the movies I have listed below in my viewDidLoad method, but it is not showing.(You can see my screen shots attached)Does anyone know which file where I can look to see why it is not showing? The code below is from my DisclosureButtonController.m file which is to display this information after I hit the Disclosure Buttons instance on the First Level screen.
Regards,
#import "LWWDisclosureButtonController.h"
#import "LWWAppDelegate.h"
#import "LWWDisclosureDetailController.h"
#interface LWWDisclosureButtonController ()
#property (strong, nonatomic) LWWDisclosureDetailController *childController;
#end
#implementation LWWDisclosureButtonController
#synthesize list;
#synthesize childController;
//- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
//{
// self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
//if (self) {
// Custom initialization
//}
//return self;
//}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *array = [[NSArray alloc] initWithObjects:#"Toy Story", #"A Bug's Life", #"Toy Story 2", #"Monsters, Inc.", #"Finding Nemo", #"The Incredibles", #"Cars", #"Ratatouille", #"WALL-E", #"Up", #"Toy Story 3", #"Cars 2", #"Brave", nil];
self.list = array;
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.list = nil;
self.childController = nil;
// Release any retained subviews of the main view.
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [list count];//
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString * DisclosureButtonCellIdentifier = #"DisclosureButtonCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:DisclosureButtonCellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:DisclosureButtonCellIdentifier];
}
NSUInteger row = [indexPath row];
NSString *rowString = [list objectAtIndex:row];
cell.textLabel.text = rowString;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
#pragma mark -
#pragma mark Table Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Hey, boss do you see the disclosure button?" message:#"If you're trying to drill down, touch that instead mate!" delegate:nil cancelButtonTitle:#"Won't happen again" otherButtonTitles:nil];
[alert show];
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *)indexPath
{
if (childController == nil)
{
childController = [[LWWDisclosureDetailController alloc]initWithNibName:#"LWWDisclosureDetail" bundle:nil];
}
childController.title = #"Disclosure Button Pressed";
NSUInteger row = [indexPath row];
NSString *selectedMovie = [list objectAtIndex:row];
NSString *detailMessage = [[NSString alloc]initWithFormat:#"You pressed the disclosure button for %#.", selectedMovie];
childController.message = detailMessage;
childController.title = selectedMovie;
[self.navigationController pushViewController:childController animated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

Why not start the array with the VC instead of after the VC loads? Try overriding the init method.
- (id) init {
if((self == [super init])) {
//load your array here and set
}
return self;
}
That way, on older devices, you don't have to wait after the view loads to see the array. But, however, this is my preference. I love to override init methods and create my own.
Also, for some weird reason on my SDK, I have to use NSMutableArray instead of NSArray or it won't work. Maybe you have the same issue?
Also, I've noticed NSString *selectedMovie. Instead of using just "row", use the getter indexPath.row.
Hope these suggestions helped!

Call:
[self.tableView reloadData]; (put in place of self.tableView the var or property connected to the tableView)
after the:
self.list = array;
code line in the viewDidLoad method
and put a
NSLog(#"number of rows: %d", [self.list count]);
in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [list count];//
}
to check if it is not zero.

Related

ViewController load methods called when view disappears?

I've got the following code in a viewController. I've got a NavigationController on the view (which is the child view - the code for the parent is working fine)
What happens is when I select an option on the parent, this viewController loads. The user can select an option from the child viewController to open a PDF file with a DocumentInteractionController (which works fine).
The problem is when I try going back to the parent viewController, messages are being sent to the child viewController as if it's still allocated. I saw something similar when I set it up since there were multiple calls to the methods in the child viewController.
Any thoughts on what I'm doing wrong?
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize node;
#synthesize replies;
#synthesize docController;
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
[self.tableView setContentOffset:CGPointZero animated:NO];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.docController init];
// Do any additional setup after loading the view from its nib.
}
- (void) dealloc
{
[self.docController release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.replies == nil)
{
self.replies = [[NSArray alloc] init];
self.actions = [[NSArray alloc] init];
}
if(self.replies.count == 0)
{
self.replies = [self.node nodesForXPath:#"./question/reply/text" error:nil];
self.actions = [self.node nodesForXPath:#"./question/reply/response/action" error:nil];
}
return self.replies.count;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"QuestionCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Get the object to display and set the value in the cell
NSString *cellText = [[replies objectAtIndex:indexPath.row] stringValue];
cell.textLabel.text = cellText;
return cell;
}
- (void) showOptionsMenu:(NSString *) fileName
{
NSString *fileToOpen = [[NSBundle mainBundle] pathForResource:fileName ofType:#"pdf"];
NSURL *fileURL = [NSURL fileURLWithPath:fileToOpen];
self.docController = [self setupControllerWithURL:fileURL usingDelegate:self];
bool didShow = [self.docController presentOptionsMenuFromRect:CGRectMake(0, 0, 150, 150) inView: self.view animated:YES];
if(!didShow)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"Sorry, app not found" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *action = [[self.actions objectAtIndex:indexPath.row] stringValue];
[self showOptionsMenu:action];
}
- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL *) fileURL usingDelegate:(id <UIDocumentInteractionControllerDelegate>) interactionDelegate
{
UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
interactionController.delegate = interactionDelegate;
return interactionController;
}
#end
EDIT
Adding the code for the parent view controller...maybe there's something I'm doing wrong in there? I'm using GDataXML to load a Q&A app based on the contents of an XML file...
#implementation ViewController
#synthesize currentReply;
#synthesize questions;
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUpQuestions];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[super dealloc];
}
- (void) setUpQuestions
{
// create and init NSXMLParser object
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"query" ofType:#"xml"];
NSData *xml_data = [[NSData alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *xmlDoc = [[GDataXMLDocument alloc] initWithData:xml_data options:0 error:&error];
NSArray *rootDataArray = [xmlDoc.rootElement nodesForXPath:#"//query" error:nil];
for (GDataXMLElement *rootDataElement in rootDataArray)
{
// Allocate the query object
self->query = [[[Query alloc] init] autorelease];
// Name
NSArray *query_title = [rootDataElement elementsForName:#"text"];
if (query_title.count > 0)
{
GDataXMLElement *queryTitle = (GDataXMLElement *) [query_title objectAtIndex:0];
self->query.queryTitle = [[[NSString alloc] initWithString:queryTitle.stringValue] autorelease];
}
NSArray *query_first_question = [rootDataElement elementsForName:#"question"];
NSArray *replies = [NSArray alloc];
questions = [[NSMutableArray alloc] init];
if(query_first_question.count == 1)
{
GDataXMLElement *fq = (GDataXMLElement *) [query_first_question objectAtIndex:0];
replies = [fq elementsForName:#"reply"];
for (GDataXMLElement *replyElement in replies)
{
[questions addObject:replyElement];
}
}
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Only one section.
return 1;
}
- (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection:(NSInteger)section
{
switch(section)
{
case 0:
return questions.count;
break;
case 1:
return 1;
break;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"QuestionCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
// Get the object to display and set the value in the cell.
GDataXMLElement *questionAtIndex = questions[indexPath.row];
NSString *cellText = [[[questionAtIndex elementsForName:#"text"] objectAtIndex:0] stringValue];
cell.textLabel.text = cellText;
//cell.textLabel.text = [[questionAtIndex elementsForName:#"text"] objectAtIndex:0];
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSMutableString *msg = [NSMutableString new];
//[msg appendString:#"You selected row: "];
//[msg appendString:[NSString stringWithFormat:#"%i",indexPath.row]];
//UIAlertView *alertMsg = [[UIAlertView alloc] initWithTitle:#"Row Selected" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
//[alertMsg show];
if (questions != nil)
{
GDataXMLElement *selectedReply = (GDataXMLElement *) [questions objectAtIndex:indexPath.row];
DetailViewController *dvc = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
dvc.node = selectedReply;
[self.navigationController pushViewController:dvc animated:YES];
[dvc release];
}
}
EDIT
I've tried profiling and looking for zombies, but when the crash occurs there are no zombie objects flagged. It throws the following error in the console:
[UIView _forgetDependentConstraint:]: message sent to deallocated instance 0x1e8ab810
I have seen this Issue before also !!!
Answer : Turn Off "AutoLayout".
I am guessing the error occurred due to new feature in ios called AutoLayout. It looks like Compiler has created some NSLayoutConstraint objects and due to some reason the objects were released more than they should. Deletion and Re-Creation, forces Xcode to Re-Build the Constraints. But,I am not 100% sure.
Try to Un-Check "AutoLayout", if it can solve your Problem.
Your DetailViewController code is fine - not actually fine, as you're leaking self.replies and self.actions, and the [self.docController init] is very odd and probably wrong (always alloc and init together) - but the lifecycle code on this end looks fine. The problem is almost certainly in the parent view controller (or possibly the document controller if you're creating a retain cycle there). If the parent view controller is holding onto a pointer to the detail view controller, it won't actually be deallocated and accessing the view or any property thereof will cause -viewDidLoad to be called again.
From what I understood, your parent view controller is setting the node here:
dvc.node = selectedReply;
and it's never being released from your DetailViewController.
I'm assuming that your GDataXMLElement in the DetailViewController header is set as "retain".
And there's some leaking problems as icodestuff pointed out.

Push the values to new ViewController when a cell is tapped

I have table view that populated with plist called "Htgg".
I am trying to push the value to a new view called "DetailViewController".
This is the code:
#import "Glist.h"
#import "DetailViewController.h"
#implementation Glist
#synthesize htgg,detailViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"ofek", #"ofek");
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = #"איך להוציא גימלים?";
NSString *htggFile = [[NSBundle mainBundle]pathForResource:#"Htgg" ofType:#"plist"];
htgg = [[NSDictionary alloc] initWithContentsOfFile: htggFile];
}
- (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 [htgg 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.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
id keys = [htgg allKeys];
//Get all the keys in the first dictionary (the keys are: "good", "funny", "New - Item 3")
//This is an array, so you can do this: array[0] (in C#)
//Here we tell the tableview cell. to put in the text - [keys objectsAtIndex:indexPath.row]; if the row is 0, we will get: "good", if 1, we will get "funny"
cell.textLabel.text = [keys objectAtIndex:indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *showPickedSolution = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:showPickedSolution animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
The code works perfect but it doesn't push the value of the row( all the rows of plist are string type and above the there is 'Root').
I need your help to push the value to another view(DetailViewController).
make a property in your DetailViewController of the same type as of your data you want to push then use
DetailViewController *showPickedSolution = [[DetailViewController alloc]
initWithNibName:#"DetailViewController" bundle:[NSBundle mainBundle]];
showPickedSolution.yourPropertName = [htgg objectAt:indexPath.Row];
[self.navigationController pushViewController:showPickedSolution animated:YES];
you can now access the passed dat in your DetailViewController in your property.
Please check the syntax.
I have done this in two different way depending on the scenario:
1) Delegate, when I fill some values on a form that I want to pass back to the original screen.
2) Storyboard Segue, when I want to send some value(s) to a second screen.
I usually put all the values I want in an array to send the object and then at arrival I extract what I need.
Instead of explaining each way, I can refer you to Getting Started section of the iOS Dev Site.
I hope it help!
To achieve this you can made an NSString property in class DetailViewController and set that property in didSelectRowAtIndexPath. Here is the code for your reference:
showPickedSolution.valueToBeSent = [htgg valueForKey:[[htgg allKeys] objectAtIndex:indexPath.row]];
You can use this valueToBeSent in your DetailViewController class.

What are some reasons why custom UITableViewCells might work in iOS 6 but not iOS 5?

I am having a ton of trouble trying to get a table view to work on my iPhone. The weird thing is that it seems to work completely fine on my iOS simulator (i.e., I can add an entry to an array, and that entry shows up in my table view). However, when I try to add an entry when using my iOS device, the codes breaks on the line dequeueReusableCellWithIdentifier:. I've checked for capitalization inconsistencies, name inconsistencies, have reimplemented prepareForReuse in the custom UITableViewCell subclass, have tried defining fields in my UITableViewCell subclass using IBOutlets v. tags, and perhaps a few more things but none have worked.
This questions is tangentially related to my previous question: Debugging strategies when UITableView's cells don't load?
The tough part about programming is always knowing which question to ask, so I apologize if it turns out I am asking the wrong questions.
UPDATE 6: Problem Is Custom Layout For UITableViewCell On iOS 5
I tested using a subclass of UITableViewCell and UITableViewCell with a custom layout. Using a subclass of UITableViewCell with style UITableViewCellStyleDefault does work on both iOS 5 and iOS 6 iPhone simulator. However, using a generic UITableViewCell with a custom style crashes on iOS 5 but not iOS 6. Interestingly, I don't see a declaration for a custom UITableViewCellStyle in the documentation for UITableViewCell...
UPDATE 5: iOS 5 v. 6 + Custom UITableViewCell Subclass?
Hello: Continued testing today and it appears that it is an issue between how iOS 5 and 6 treat custom UITableViewCell subclasses. No solution yet :(
UPDATE 4: iOS 5 v. iOS 6?
So all I've been able to notice is that this seems to be an issue with iOS 5 versus iOS 6. When testing on iOS 6 using line GlassboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier] the code below works. However, neither that line nor GlassboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath] work in iOS 5. Any ideas? I somehow got it to work exactly once by changing the identifier to protocell.
UPDATE 3: I now use GitHub!
Here is the relevant repo: https://github.com/kenmhaggerty/Glassbox
UPDATE 2: More Observations
So I had added in #synthesize tableView = _tableView because I read in a response somewhere that it might help, but I now realize that it stopped my data from loading in my table view even when running on the iOS simulator. Commenting out that line of code returns the code back to how I describe it above: it works just fine on the iOS simulator but breaks on line dequeueReusableCellWithIdentifier: with no specified error, just Thread 1: breakpoint 1.1.
UPDATE 1: Relevant Code
GlassboxTableViewController.h
//
// GlassboxTableViewController.h
// Glassbox
//
// Created by Ken M. Haggerty on 10/22/12.
// Copyright (c) 2012 Ken M. Haggerty. All rights reserved.
//
#pragma mark - // NOTES (Public) //
#pragma mark - // IMPORTS (Public) //
#import <UIKit/UIKit.h>
#pragma mark - // PROTOCOLS //
//#protocol GlassboxTableViewDatasource <NSObject>
//#property (nonatomic, weak) NSMutableArray *arrayOfPlayers;
//#end
#pragma mark - // DEFINITIONS (Public) //
#interface GlassboxTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *arrayOfPlayers;
- (IBAction)addPlayer:(UIBarButtonItem *)sender;
//#property (nonatomic, strong) id <GlassboxTableViewDatasource> datasource;
#end
GlassboxTableViewController.m
//
// GlassboxTableViewController.m
// Glassbox
//
// Created by Ken M. Haggerty on 10/22/12.
// Copyright (c) 2012 Ken M. Haggerty. All rights reserved.
//
#pragma mark - // NOTES (Private) //
#pragma mark - // IMPORTS (Private) //
#import "GlassboxTableViewController.h"
#import "GlassboxCell.h"
#import "Player.h"
#import <MobileCoreServices/MobileCoreServices.h>
#pragma mark - // DEFINITIONS (Private) //
#define SIDEBAR_WIDTH_PERCENT 0.75
#interface GlassboxTableViewController () <UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
//#property (nonatomic, weak) IBOutlet UITableView *tableView;
- (void)setup;
#end
#implementation GlassboxTableViewController
#pragma mark - // SETTERS AND GETTERS //
#synthesize arrayOfPlayers = _arrayOfPlayers;
#synthesize tableView = _tableView;
//#synthesize datasource = _datasource;
- (void)setArrayOfPlayers:(NSMutableArray *)arrayOfPlayers
{
_arrayOfPlayers = arrayOfPlayers;
}
- (NSMutableArray *)arrayOfPlayers
{
if (!_arrayOfPlayers) _arrayOfPlayers = [[NSMutableArray alloc] init];
// [_arrayOfPlayers addObject:[[Player alloc] initWithUsername:#"Ken H.:"]];
return _arrayOfPlayers;
}
#pragma mark - // INITS AND LOADS //
- (void)setup
{
self.tableView.dataSource = self;
self.tableView.delegate = self;
}
- (id)initWithStyle:(UITableViewStyle)style
{
NSLog(#"[initWithStyle]");
self = [super initWithStyle:style];
if (self) {
[self setup];
}
return self;
}
- (void)viewDidLoad
{
NSLog(#"[viewDidLoad]");
[super viewDidLoad];
[self setup];
// 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)viewDidAppear:(BOOL)animated
//{
// [super viewDidAppear:animated];
// [self.view setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width*SIDEBAR_WIDTH_PERCENT, self.view.frame.size.height)];
//}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - // PUBLIC FUNCTIONS //
- (IBAction)addPlayer:(UIBarButtonItem *)sender
{
[self alertAddPlayer];
}
#pragma mark - // PRIVATE FUNCTIONS //
- (void)alertAddPlayer
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Add New Player" message:#"Please type player name:" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
alert.tag = 1;
[alert show];
}
- (void)alertInvalidPlayer
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Invalid Name" message:#"Please type another name:" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK",nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
alert.tag = 1;
[alert show];
}
- (void)alertAddPhoto
{
NSLog(#"[TEST] alertAddPhoto");
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
NSArray *mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
if ([mediaTypes containsObject:(NSString *)kUTTypeImage])
{
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.allowsEditing = YES;
// imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
// imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
imagePickerController.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
// [self presentViewController:imagePickerController animated:YES completion:nil];
imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
[self presentModalViewController:imagePickerController animated:YES];
return;
}
}
NSLog(#"[TEST] No camera available");
[self.tableView reloadData];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if (!image) image = [info objectForKey:UIImagePickerControllerOriginalImage];
if (image)
{
[[self.arrayOfPlayers lastObject] setPhoto:[[UIImageView alloc] initWithImage:image]];
}
[self dismissImagePicker];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissImagePicker];
}
- (void)dismissImagePicker
{
// [self dismissViewControllerAnimated:YES completion:^{
// [self.tableView reloadData];
// }];
[self dismissModalViewControllerAnimated:YES];
[self.tableView reloadData];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) NSLog(#"Cancel tapped");
else
{
if (alertView.tag == 1)
{
if (buttonIndex == 1)
{
if ([[[alertView textFieldAtIndex:0] text] length] != 0)
{
[self.arrayOfPlayers addObject:[[Player alloc] initWithUsername:[[alertView textFieldAtIndex:0] text]]];
[self alertAddPhoto];
}
else [self alertInvalidPlayer];
}
}
}
}
#pragma mark - // PRIVATE FUNCTIONS (Miscellaneous) //
// TableView data source //
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//{
//#warning Potentially incomplete method implementation.
// // Return the number of sections.
// return 0;
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return self.datasource.arrayOfPlayers.count;
return self.arrayOfPlayers.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"New Cell";
// GlassboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
GlassboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.name.text = [[self.arrayOfPlayers objectAtIndex:indexPath.row] username];
cell.action.text = #"LOADED SUCCESSFULLY";
cell.time.text = #"Just now";
cell.photo = [[self.arrayOfPlayers objectAtIndex:indexPath.row] photo];
// [((UILabel *)[cell viewWithTag:1]) setText:[[self.arrayOfPlayers objectAtIndex:indexPath.row] username]];
// [((UILabel *)[cell viewWithTag:2]) setText:#"has been added."];
// [((UILabel *)[cell viewWithTag:3]) setText:#"Just now"];
// [((UIImageView *)[cell viewWithTag:4]) setImage:[[[self.arrayOfPlayers objectAtIndex:indexPath.row] photo] image]];
[cell.contentView setFrame:CGRectMake(cell.contentView.frame.origin.x, cell.contentView.frame.origin.y, cell.contentView.frame.size.width, 120)];
return cell;
}
/*
// 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) {
// Delete the row from the data source
[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
}
}
*/
/*
// 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;
}
*/
// TableView delegate //
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
Let me know if I should post more.
(Your github project does not compile (Player.h/Player.m missing), so it is difficult to reproduce the issue.)
But I noticed that "Use Autolayout" is on in the MainStoryboard file. Autolayout works only on iOS 6 and later, not on iOS 5!
Please post your code. I can advice you to leave the xib files for uitableviewcell and try again. Do you use one kind of cell? or you use few different style?
===== ANSWER =====
When you create cell GlassboxCell *cell and use dequeueReusableCellWIthIdentifier you need check if cell is allocated.
// use dequeueReusableCellWithIdentifier for init cell
if (cell == nil){
cell = [[[GlassboxCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:yourIdentifier]] autorelease];
}
//rest your code for init properties for cell
ok man try to use this function instead of yours.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NewCell";
GlassboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[GlassboxCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.name.text = [[self.arrayOfPlayers objectAtIndex:indexPath.row] username];
cell.action.text = #"LOADED SUCCESSFULLY";
cell.time.text = #"Just now";
cell.photo = [[self.arrayOfPlayers objectAtIndex:indexPath.row] photo];
[cell.contentView setFrame:CGRectMake(cell.contentView.frame.origin.x, cell.contentView.frame.origin.y, cell.contentView.frame.size.width, 120)];
return cell;
}
I think I found the problem...at least it works on my project.
When you make a UITableViewController class with an older version of Xcode (say 4), the generated code for cellForRowAtIndexPath is this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
But when you make a UITableViewController with Xcode 4.5.2 (mine), the generated code for cellForRowAtIndexPath is this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
So in my case all I did was remove the "forIndexPath:indexPath" portion and it works!
(This is my first answer ever so please be gentle if I screwed up something)

TableView is delegated, populates but wont group

I am having a weird problem and i couldn`t find a solution (or something similar).
The thing is, my UITableView Populates with initial info (for testing), but no matter what i do i can't seem to put it to grouped style (i can select it on the UI but it wont show)
I initially started a TabBar project and added a third navigationController view in the tabs.
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *tableData;
}
#property (nonatomic, retain) NSMutableArray *tableData;
-(void)initTableData;
#end
This is the header, and as you can see it has nothing out of the ordinary. The following code is inside the .m file of the header i just posted(ill only be posting uncommented code:
#synthesize tableData;
-(void)initTableData
{
tableData = [[NSMutableArray alloc] init];
[tableData addObject:#"Cidade"];
[tableData addObject:#"Veículo"];
[tableData addObject:#"Ano"];
[tableData addObject:#"Valor"];
[tableData addObject:#"Cor"];
[tableData addObject:#"Combustível"];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Busca";
UIBarButtonItem *_backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:nil action:nil];
self.navigationItem.backBarButtonItem = _backButton;
[self initTableData];
}
- (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 6;
}
// 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] autorelease];
}
// Configure the cell...
cell.textLabel.text = [tableData objectAtIndex:[indexPath row]];
return cell;
}
- (void)dealloc {
[tableData release];
[super dealloc];
}
Nothing out of the ordinary again as you can see...
Any idea of what may be causing this? I tried
- (id)initWithStyle:(UITableViewStyle)style {
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
// Custom initialization.
}
return self;
}
because i don't know what else to do. (also didn't worked)
Again, i got the delegate and datasource set to File`s Owner.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Set the tab bar controller as the window's root view controller and display.
self.window.rootViewController = self.tabBarController;
RootViewController *rvc = [[RootViewController alloc] initWithStyle: UITableViewStyleGrouped];
[self.window makeKeyAndVisible];
return YES;
}
As you have modified the - (id)initWithStyle:(UITableViewStyle)style initializer to return a UITableView with a grouped style, do you call this initializer when you initialize the RootViewController?
RootViewController *rvc = [[RootViewController] alloc] initWithStyle: UITableViewStyleGrouped];
Grouped tables respond to the sections. You only have 1 section listed so you will only see the 1 group. Try and add a 2nd tableData for the 2nd group and return 2 sections. You will also have to split the data in your -cellForRowAtIndexPath by section as well to make sure the data goes to the right section.
if (indexpath.section == 0) {
// first section and first tableData
}
if (indexpath.section == 1) {
// second section and second tableData
}

cellForRowAtIndexPath returns null but really need similar method

I have a UITableView in my UITableViewController (lol, obviously) but I need to get a cell at a given index inside the - (void)viewWillAppear:(BOOL)animated method.
Now, my cells are static and I create them in the interface builder. If I call
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:previously_selected_cell.integerValue inSection:0]];
it returns null for the cell. I only have 3 static cells in 1 sections. I tried both sections 0 and 1 and both return null.
Currently I have removed the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method because if I add it, it will clear the UITableView of all my static cells.
Is there a method I can call in - (void)viewWillAppear:(BOOL)animated that will return a cell at a given index?
Thanks in advance!
EDIT: I checked out this stackoverflow question but I'm using static cells without cellForRowAtIndexPath so that question didn't help. :(
EDIT2: I'm trying to set the accessory type of the cell when the view loads. But only on a certain cell, that cell being the one the user selected before he quit the app.
#import "AutoSyncSettings.h"
#import "CDFetchController.h"
#implementation AutoSyncSettings
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSArray *objects = [results fetchedObjects];
NSNumber *sync_setting;
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
sync_setting = [object valueForKey:#"wifi_setting"];
NSLog(#"(Settings)sync_setting: %#",sync_setting);
NSLog(#"(Settings)sync_setting int value: %i",sync_setting.integerValue);
NSLog(#"(Settings)TableView: %#",self.tableView);
//cell is null, even after this.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:wifi_settings.integerValue inSection:0]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//cell is still null. WHY OH WHY? :(
objects = nil;
}
cdfc = nil;
results = nil;
objects = nil;
sync_setting = nil;
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (int i = 0; i < [tableView numberOfRowsInSection:indexPath.section]; i++)
{
if([[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]] accessoryType] == UITableViewCellAccessoryCheckmark)
{
[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]].accessoryType = UITableViewCellAccessoryNone;
}
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSManagedObjectContext *context = [results managedObjectContext];
NSArray *objects = [results fetchedObjects];
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
else
{
//INSERT NEW OBJECT
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"SETTINGS" inManagedObjectContext:context];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
}
#end
I have a project doing exactly this and it works perfectly. However, it doesn't work unless you call [super viewWillAppear:animated] before trying to access the cells in this manner.
The base implementation presumably loads in the cells from the storyboard.
I want to add a checkmark accessory to the previously selected cell,
the previously_selected_cell variable gets stored even if the app
quits/crashes
The way to go will be to control the indexPath in your cellForRowAtIndexPath implementation and act if it's equal to previously_selected_cell.integerValue:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// usual cache lookup, allocation of the cell, etc
if (indexPath.row == previously_selected_cell.integerValue) {
// add checkbox here
} else {
// remove checkbox
}
}