NSUserDefaults not appearing first appearence - objective-c

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

Add [super viewWillAppear:animated] to the top of your viewWillAppear: override. According to Apple's documentation for viewWillAppear:,
"If you override this method, you must call super at some point in your implementation."
While your application generally won't crash or anything if you omit it, important initialization performed by the base class will not occur unless you call [super viewWillAppear:animated], which may result in unexpected behaviour, such as label values not appearing in your table view cells.
As a best practice, you should always call the super method whenever you override one of Apple's methods, unless you explicitly do not want the default behaviour to occur (eg. overriding touchesBegan:withEvent:). Though there are exceptions, generally overridden initialization methods like viewDidLoad and viewWillAppear: should call their super method at the beginning of the method, while overridden teardown methods like viewWillDisappear: should call their super method at the end.

Related

NSTableViewCell selectedRow number for IBAction click

I'm running into a simple problem but have yet to find an optimal solution. I have a view based NSTableView that is loading it's cell views from different xibs. My table view is dynamic and based on user input I will dynamically add and remove rows ultimately adjusting the table data source. Each one of my NSTableCellViews have a button in it and I link the IBAction click handler to the NSView that holds the table view. What I need to do is get the row number for the button that was clicked in the table view so I can process the logic. I am able to do this successfully in : tableViewSelectionDidChange:(NSNotification *)notification
Here is how I do it:
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
NSTableView *tableView = [notification object];
NSInteger selectedRow = [tableView selectedRow];
}
This works perfectly for a user actually clicking the row. Now when I move the NSButton IBAction and link it in the NSView as follows:
- (IBAction)buttonClickHandler:(NSButton *)sender {
NSInteger selectedRow = [self.tblView rowForView:sender];
NSLog(#"%ld", (long)selectedRow);
}
I based this approach from this selected answer.
I also tried this:
- (IBAction)buttonClickHandler:(NSButton *)sender {
id representedObject = [(NSTableCellView *)[sender superview] objectValue];
NSLog(#"%#", representedObject);
}
//My configuration
- (void)configureView {
[self.view setFrame:[self bounds]];
[self addSubview:self.view];
[self.view setWantsLayer:YES];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
self.tblView.delegate = self;
self.tblView.dataSource = self;
[self.tblView setIntercellSpacing:NSMakeSize(0, 0)];
[self.tblView registerNib: [[NSNib alloc] initWithNibNamed:#"ParentCellXib" bundle:nil] forIdentifier:#"ParentCell"];
[self.tblView registerNib: [[NSNib alloc] initWithNibNamed:#"ChildCellXib" bundle:nil] forIdentifier:#"ChildCell"];
[self.tblView registerNib: [[NSNib alloc] initWithNibNamed:#"HeaderCellXib" bundle:nil] forIdentifier:#"HeaderCell"];
}
But the represented object returns null. If it's worth mentioning, I've set my File's Owner as the View that holds the tableView so I can link the IBAction and I've subclassed the TableCellView to a different class. However, I don't think this is part of the problem as far as I can see. Is there a simple solution to reliably give me the selectedRow number based on a button click in that cell? Both approaches I tried above return -1 and null respectively.
I would set the row in NSButton's tag property:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
SomeTableCellView *cell = [tableView makeViewWithIdentifier:#"cell" owner:self];
if (cell == nil) {
cell = // init some table cell view
cell.identifier = #"cell";
}
cell.button.tag = row;
[cell.button setTarget:self];
[cell.button setAction:#selector(buttonAction:)];
}
- (IBAction)buttonAction:(id)sender {
NSLog(#"row: %d", sender.tag);
}
Try This
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
yourCustomeCell *aCell;
NSString *aStrIdentifier = #"yourIdentiFier";
aCell = (yourCustomeCell *)[tableView dequeueReusableCellWithIdentifier:aStrIdentifier];
//you have to set your indexpath
objc_setAssociatedObject(aCell.btnUpload_or_Add, #"objBtn", indexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[aCell.YourButton addTarget:self action:#selector(yourButtonActiontapped:) forControlEvents:UIControlEventTouchUpInside];
return aCell;
}
-(IBAction)yourButtonActiontapped:(UIButton *)sender{
NSIndexPath *aIndPath = objc_getAssociatedObject(sender, #"objBtn");
NSLog(#"row:%#",aIndPath.row);
}
also you have to import #import <objc/runtime.h>
another way to get row in IBAction is TAG but objc is better option insted of TAG.
Create a subclass of UIButton and add a property for NSIndexPath for the button. Use this button in cellForRowAtIndexPath method. assign the index path of the cell to that of index path of the button.
On Tap, get the index path from its sender. In your case index path of that button.

Edit Item in Bottom Toolbar Xcode and Objective C

I have a Navigation Controller. I want to put the edit button on the bottom in the toolbar instead of in the top navigation bar.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
The problem I have is that when I add the edit button to the Bottom Toolbar. like this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.christmasGifts removeGiftAtIndexPath:indexPath];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:YES];
//Do not let the user add if the app is in edit mode.
if(editing)
self.navigationItem.rightBarButtonItem.enabled = YES;
else
self.navigationItem.rightBarButtonItem.enabled = YES;
}
And then link the edit button setEditing: in the toolbar it does not show a done button like the Edit button in the top navigation. it just stays the same.
But you can delete an item, but you cannot reset the state to normal again with the bottom button.
I need to be able to go back to the previous controller from this Navigation Controller. but the edit button hides the back button.
Edit.
I know I can by code add the toolbar.
UIBarButtonItem *editButton = [[UIBarButtonItem alloc]
initWithTitle:#"Edit"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(setEditing:)];
[[UIBarButtonItem appearance] setTintColor:[UIColor colorWithRed:70/255.0f green:155/255.0f blue:19/255.0f alpha:1.0]];
NSArray *arrBtns = [[NSArray alloc]initWithObjects:editButton,anotherButton, nil];
self.toolbarItems = arrBtns;
and
[self.navigationController setToolbarHidden:NO];
or even
UIToolbar *toolBar=[[UIToolbar alloc]initWithFrame:CGRectMake(0, 500, 400, 40)];
[self.tableView addSubview:toolBar];
In your ViewController.h, declare (and connect them in XIB)
#property (strong, nonatomic) IBOutlet UIToolbar *toolbar;
#property (strong, nonatomic) IBOutlet UIBarButtonItem *toolbarbutton;
- (IBAction)toolbarbuttonTouched:(id)sender; // Connect with UIBarButtonItem in XIB
In your ViewController.m, paste down the following function.
- (IBAction)toolbarbuttonTouched:(id)sender
{
if ([self.toolbarbutton.title isEqualToString:#"Edit"])
{
[self.tableView setEditing:YES animated:YES];
self.toolbarbutton.title = #"Done";
}
else
{
[self.tableView setEditing:NO animated:YES];
self.toolbarbutton.title = #"Edit";
}
}
And you are all set to go.
Points
Your UIBarButtonItem's initial value for property title must be
set to "Edit"
Code for editingStyle == UITableViewCellEditingStyleDelete should
be working perfectly
EDIT
You don't need the following code:
self.navigationItem.leftBarButtonItem = self.editButtonItem;
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:YES];
//Do not let the user add if the app is in edit mode.
if(editing)
self.navigationItem.rightBarButtonItem.enabled = YES;
else
self.navigationItem.rightBarButtonItem.enabled = YES;
}
Let me know, If it works for you or not.
I was able to do this more simply by using UIViewController's editButtonItem method:
- (void)viewDidLoad {
[super viewDidLoad];
// Place table view Edit button in toolbar, after existing buttons.
NSMutableArray *items = [self.toolbarItems mutableCopy];
[items addObject:self.editButtonItem];
[self setToolbarItems:items animated:YES];
}
This gets the existing array of toolbar buttons (if any) and makes a mutable copy of the array so it can be changed. It then adds UIViewController's built-in Edit button to the toolbar.
The result is a functioning Edit/Done toolbar button that toggles Edit mode on and off, without having to write your own action method to handle that.

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)

Show or dismiss a specific ViewController after performing an action

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

Error: unrecognized selector sent to instance

I have a custom object, Spaces:
#import "Spaces.h"
#implementation Spaces
#synthesize spaceName;
#synthesize spaceUsers;
#synthesize spaceIcon;
#synthesize spaceID;
#synthesize imageURLString;
- (void)dealloc
{
[spaceName release];
[spaceUsers release];
[spaceIcon release];
[imageURLString release];
[super dealloc];
}
#end
My root view controller implements a cellForRowAtIndexPath: and grabs from an NSArray of Spaces:
[[cell spaceName] setText:aSpace.spaceName];
[[cell spaceChatType] setText:#"People"];
[[cell spaceActiveUsers] setText:aSpace.spaceUsers];
This works fine and I can click to go into the detail view and back to the list, but after maybe 5-6 clicks back and forth between the table view and detail view, I get an error at [[cell spaceName] setText:aSpace.spaceName]; which is
'-[__NSCFSet spaceName]: unrecognized selector sent to instance 0x6047b90'"
Please help! Any insight will be very appreciated!
UPDATE:
I'm still getting the same error but I've narrowed it down to the this:
-I'm creating a detail view controller on didSelectRowAtIndexPath...
-The detail view is being pushed to the viewcontroller and displays fine, I have a back button added as well.
-The detail view loads information and refreshes on a timer
-Pressing the back button goes back to the table list view
This is the problem my detail view is not being released from memory so the more I go back and forth between the views the more timers were going off simultaneously. I added a check to viewWillDisappear that stops the timer by setting a bool value.
I noticed that the detail view is not unloading...
From the RootViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//no longer on initial view
isinit = NO;
//hide keyboard
[spacesSearch resignFirstResponder];
if (spaces != nil && spaces.count > 0)
{
//set back button reference
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Spaces" style:UIBarButtonItemStylePlain target:self action:#selector(returnSpacesList:)];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
DetailViewController *details = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//Grab Data from selected Space object and pass to DetailViewController
Spaces *aSpace = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if ([self.filteredListContent count] == 0)
{
//self.lastSearchText
NSLog(#"Create new space code!");
}
else
{
aSpace = [self.filteredListContent objectAtIndex:indexPath.row];
}
}
else
{
aSpace = [spaces objectAtIndex:[indexPath row]];
}
//set title and display
self.navigationController.title = [NSString stringWithFormat:#"/%#/",aSpace.spaceName];
//pass data
[details passedValue:aSpace.spaceID :aSpace.spaceName];
[self.navigationController pushViewController:details animated:YES];
[aSpace release];
[details release];
}
}
How can I force the detail view to be released from memory?
Thank you
It sounds like [cell spaceName] has been autoReleased. I cannot see how you have defined that, but take a look at that part of your code.
If you need more help, you need to provide more code.
Perhaps your aSpace = [spaces objectAtIndex:[indexPath row]];
is not returning a Space object. Perhaps before you try and use it you test to make sure with something like if ([aSpace class] == [Spaces class])