I am making a simple navigation based application that drills down one level and show a new xib file each time. When I drill down one level my screen shows up blank. I still have the navigation controller at the top with a back button but my view dosent load.
Here is my code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
circle_area *subViewOneController = [[circle_area alloc] init];
UIViewController *tvc = subViewOneController;
if (indexPath.row == 0 && indexPath.section == 0) {
[[self navigationController] pushViewController:tvc animated:YES];
}
}
like I said this returns a blank screen.
My updated Code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
circle_area *subViewOneController = [[circle_area alloc] init];
UIViewController *tvc = subViewOneController;
switch (indexPath.section) {
case 0:
switch (indexPath.row) {
case 0:
NSLog(#"section %i special button!", indexPath.section);
NSLog(#"row %i special button!", indexPath.row);
break;
default:
break;
}
break;
default:
break;
}
NSLog(#"section %i!", indexPath.section);
NSLog(#"row %i!", indexPath.row);
NSLog(tvc.view.recursiveDescription);
if (indexPath.row == 0 && indexPath.section == 0) {
[[self navigationController] pushViewController:subViewOneController animated:YES];
}
[tvc release];
}
Last time i left out the switches in the middle, it dosent look like they would effect anything , but i included them this time.
circle_area *subViewOneController = [[circle_area alloc] init];
In this line, you are creating an instance of the circle_area class and assigning it to the pointer called subViewOneController.
UIViewController *tvc = subViewOneController;
In this line, you are assigning that same instance to a pointer called tvc. This pointer is defined to point to an instance of the UIViewController class.
It's not clear what you are trying to do here. What is circle_area? Why the redundant assignment? Is circle_area a subclass of UIViewController? If it isn't, then that's the problem and you should have been warned about it by the compiler.
In addition, you have a memory leak. You allocate memory for this circle_area instance, but you don't release it.
Related
I noticed one of my custom UITableViewCell is leaking. It is not getting released on performing edit, remove bottom cell and tap on Save. This is my top cell in the table (I call it add cell). Once my table view is in edit mode, Add cell is shown up with all the other cells shown underneath with delete mode on. Now, after performing the delete operation and saving the data, Add Cell still hang around even if dealloc on my table view gets called.
I am attaching my code and instrument screenshot (I've removed first line (Malloc call) from the screenshot. To me, it appears to be something wrong in iOS internal handling. Please advise.
- (UITableViewCell *)tableView:(UITableView *)iTableView cellForRowAtIndexPath:(NSIndexPath *)iIndexPath {
MyTableViewCell *aCell = nil;
NSString *aCellType;
if (iIndexPath.row == 0 && self.inEditMode) {
aCellType = kMyAddCell;
aCell = (MyAddCell *)[iTableView dequeueReusableCellWithIdentifier:aCellType];
if (!aCell) {
aCell = [[MyAddCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:aCellType];
}
aCell.isGroupedView = YES;
aCell.delegate = self;
aCell.textLabel.text = #“Add More";
self.tableView.allowsSelectionDuringEditing = YES;
} else {
aCellType = kMyDefaultCell;
aCell = (MyTableViewCell *)[iTableView dequeueReusableCellWithIdentifier:aCellType];
if (!aCell) {
aCell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:aCellType];
}
NSInteger anIndex = iIndexPath.row;
if (self.inEditMode) {
anIndex = anIndex - 1;
}
aCell.textLabel.text = #“Name";
aCell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return aCell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)iIndexPath {
return (iIndexPath.row == 0 && self.inEditMode) ? UITableViewCellEditingStyleNone : UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)iTableView canEditRowAtIndexPath:(NSIndexPath *)iIndexPath {
return YES;
}
- (void)tableView:(UITableView *)iTableView commitEditingStyle:(UITableViewCellEditingStyle)iEditingStyle forRowAtIndexPath:(NSIndexPath *)iIndexPath {
if (iEditingStyle == UITableViewCellEditingStyleDelete) {
[self setSaveModeNavigationBar];
[self.tableView beginUpdates];
[self.enabledUsers removeObjectAtIndex:(self.inEditMode) ? iIndexPath.row - 1 : iIndexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[iIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
}
- (void)setEditing:(BOOL)iEditing animated:(BOOL)iAnimated {
[super setEditing:iEditing animated:iAnimated];
[self.navigationItem setHidesBackButton:YES animated:NO];
self.headerViewLabel.text = #“Edit Me";
UIBarButtonItem *aDoneButton = [[UIBarButtonItem alloc] initWithTitle:#“Done"
style:UIBarButtonItemStylePlain
target:self
action:#selector(cancelEditing)];
[self.navigationItem setRightBarButtonItem:aDoneButton];
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.inEditMode = YES;
[self.tableView reloadData];
}
Code that gets called once I tap on Save button:
self.requestHandler = [[MyRequestHandler alloc] initWithEndPoint:myEndPoint body:aPostBody successHandler:^(NSDictionary *iResponse) {
[aBlockSelf addNoDataOverlay];
} andErrorHandler:^(NSString *iMessage, NSString *iKey, NSInteger iErrorCode, BOOL iIsNetworkError) {
[aBlockSelf addNoDataOverlay];
}];
[self.requestHandler executeRequest];
Instrument Allocation Stack:
Apparently it turned out to be a known issue being tracked in this thread. Tried the same steps in iPhone 5S (iOS 8) and issue has been resolved there.
I have a custom UIView with a UITableView in it. I connect the delegate and dataSource via interface builder, it looks like this: http://postimg.org/image/nj9elaj4h/ (may not upload images yet :( )
When I load the view, the data is displayed as it should be. But when I try to call reloadData, nothing happens. I checked if the uitableview is set, but it is NULL. But as soon as I drag the tableView and it reloads it views, the new data is presented. Anyone got an idea why reloadData does not work?
.h looks like this:
#interface NextTitleView : UIView<UITableViewDataSource,UITableViewDelegate,SociusClientDelegate,UIActionSheetDelegate,Ne xtTitleCustomCellDelegate>
{
NexTitleCustomCell* _cellInFocus;
}
#property(nonatomic,retain)IBOutlet UITableView* _tableViewNextTitle;
#end
thanks for your help :D
EDIT: Added .m file
#implementation NextTitleView
#synthesize _tableViewNextTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(id)init
{
if(self)
{
[SharedSingeltons sharedInstance]._client.delegateCustomClient = self;
_tableViewNextTitle = [[UITableView alloc]init];
}
return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if(section == 0)
return #"Now playing";
if(section == 1)
return #"Comming Next";
else
return #"";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section == 0)
return 1;
if (section == 1)
return [[SharedSingeltons sharedInstance]._client._musicList count];
else
return 0;
}
-(NexTitleCustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NexTitleCustomCell* cell = [[NexTitleCustomCell alloc]init];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NextTitleCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
MusicItem* item = [[SharedSingeltons sharedInstance]._client._musicList
objectAtIndex:indexPath.row];
cell.delegate = self;
cell._labelSongTitle.text = item._songTitle;
cell._labelSongTitle.textColor = [UIColor blackColor];
cell._labelSubtitle.text = item._artist;
cell._identifier = item._songIdentifier;
cell._labelRating.text = item._rating.stringValue;
return cell;
}
-(void)clientDidReceiveMusicList:(SociusClient *)sender list:(NSMutableArray *)array
{
for(MusicItem* item in [SharedSingeltons sharedInstance]._client._musicList)
{
NSLog(#"rating:%#",item._rating);
}
NSLog(#"TAbleVIEW:%#",_tableViewNextTitle);
[self._tableViewNextTitle reloadData];
}
-(void)didPressActionButton:(NexTitleCustomCell *)sender
{
NSLog(#"Show alert view");
_cellInFocus = sender;
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Vote Up", #"Like",#"Remember", nil];
[popupQuery showInView:self];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
NSLog(#"Vote up");
[self sendUpdateVoteForSong];
}
}
-(void)sendUpdateVoteForSong
{
NSMutableDictionary* dict = [[NSMutableDictionary alloc]init];
[dict setObject:_cellInFocus._identifier forKey:#"Vote"];
NSLog(#"Identifier:%#",_cellInFocus._identifier);
[[SharedSingeltons sharedInstance]._client sendObject:dict error:nil];
}
#end
I would say you are calling reload data too soon, probably in initWithNibName, you should be calling it in viewDidLoad.
I just set up a uiviewcontroller to handle the view. Now it works fine.
I think that UIActionSheet led to the problem,you can try to reloadData twice.
I noticed you are New-ing your Table view, but it's an Outlet... You don't need to alloc init your table view, if it's an IBOutlet. So either get rid of the IBOutlet, and just declare it as a property (but then you need to make sure you lay out your Table view programmatically), or keep the IBOutlet, and get rid of the code to alloc init it. Currently also your datasource and delegate are set from IB, so if you alloc init your table view, those won't be set anymore...
The tableview outlet should NOT be nil.
Can you put a breakpoint in awakeFromNib, and see if the TableView outlet is NIL there?
Are you loading the View Class that contains the table view by using its NIB file properly?
If you just embed the View class in the storyboard, it will not load the NIB automatically. I usually use a View container in that case, then load the NIB programmatically, and embed the loaded view in the view container programmatically.
NSArray *arrayXibObjects = [[NSBundle bundleWithIdentifier:#"net.mycompany.myappid"] loadNibNamed:#"myNibName" owner:nil options:nil];
for (id object in arrayXibObjects) {
if ([object isKindOfClass:myNibsClass]) {
return object; // this is your class loaded from NIB
}
}
This code can be placed in a utility method, to make it accessible with 1 line of code.
The returned Class is going to have the IBOutlets connected from the NIB to it's respective Class.
Now check in the debugger:
po [loadedClassFromNib tableView] // should not be NIL
Then embed the loaded NIB in the container like this: (or use constraints)
[self.viewContainer addSubview: classLoadedFromNib];
classLoadedFromNib.frame = self.viewContainer.frame;
I have a Navigation controller on which a table view is there. I wanted two button on that navigation bar i.e. "Add to Favourite" and the other is "Edit".
Both the button should fire the event that makes the table view go in editing mode. From the "Add to favorite button i want the table view to go in insertion mode i.e. a +green sign in front of every cell and with the Edit button i want it to go in deletion mode i.e. - negative sign in front of every cell.
I have sorted out the Edit button , but i am not able to do the Add to favorite button.
Sticking my code here for reference
The viewDidLoad method:
- (void)viewDidLoad
{
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem=[[[UIBarButtonItem alloc]initWithTitle:#"Add to Favourite" style:UIBarButtonItemStylePlain target:self action:#selector(saveAction:)]autorelease];
[super viewDidLoad];
- (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.leftBarButtonItem.enabled = NO;
else
self.navigationItem.leftBarButtonItem.enabled = YES;
NSLog(#"i came till here"); }
In this method i am just retrieving values from database and deleting it from the DB as well as the table view.
- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
NSDictionary *rowVals = (NSDictionary *) [appdelegate.tablearr objectAtIndex:indexPath.row];
NSString *keyValue = (NSString *) [rowVals objectForKey:#"id"];
// [tableView beginUpdates];
sqlite3 *db;
int dbrc; //Codice di ritorno del database (database return code)
AppDelegate *appDelegate = (AppDelegate*) [UIApplication sharedApplication].delegate;
const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc = sqlite3_open(dbFilePathUTF8, &db);
if (dbrc) {
NSLog(#"Impossibile aprire il Database!");
return;
}
sqlite3_stmt *dbps; //Istruzione di preparazione del database
NSString *deleteStatementsNS = [NSString stringWithFormat: #"DELETE FROM \"Hell\" WHERE id='%#'", keyValue];
const char *deleteStatement = [deleteStatementsNS UTF8String];
dbrc = sqlite3_prepare_v2(db, deleteStatement, -1, &dbps, NULL);
dbrc = sqlite3_step(dbps);
sqlite3_finalize(dbps);
sqlite3_close(db);
[appdelegate.tablearr removeObjectAtIndex:indexPath.row];
//Delete the object from the table.
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
And this is the one method thats get fired when i press the add to favorite button
-(void)saveAction:(UIBarButtonItem *)sender{
NSLog(#"here");
}
Now what should i write in this method so that the table view goes into the editing and with an + green insertion thing in front of every cell ??
To put the table into editing mode, you need to use:
[self.tableView setEditing:YES animated:YES];
To switch between insertion and deletion modes, you need to implement tableView:editingStyleForRowAtIndexPath:. I.e.:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (some condition)
return UITableViewCellEditingStyleInsert;
else
return UITableViewCellEditingStyleDelete;
}
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])
I'm having this "tableView:cellForRowAtIndexPath:]: unrecognized selector sent to instance" error, I'm almost sure is some kind of memory management issue but right now I'm pretty much tired of having to find the bug.
The TableView displays the cells well as long as you don't scroll down, if you do..
app crashes.
The only property I use is called "places", I've already checked if I didn't miss a "self.".
so.. here's my code:
#import "PlacesViewController.h"
#import "FlickrFetcher.h"
#import "SinglePlaceViewController.h"
#implementation PlacesViewController
#synthesize places;
- (NSArray *)places
{
if (!places) {
NSSortDescriptor *content = [[NSSortDescriptor alloc] initWithKey:#"_content" ascending:YES];
NSArray *unsortedPlaces = [FlickrFetcher topPlaces];
places = [unsortedPlaces sortedArrayUsingDescriptors:[NSArray arrayWithObjects: content, nil]];
}
return places;
}
#pragma mark -
#pragma mark Initialization
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Top Places";
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return YES;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return self.places.count;
}
- (NSDictionary *)placeAtIndexPath:(NSIndexPath *)indexPath
{
return [self.places objectAtIndex:indexPath.row];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"PlacesTableViewCell";
NSLog(#"%#", [FlickrFetcher topPlaces]);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSString *location = [[self placeAtIndexPath:indexPath] objectForKey:#"_content"];
NSArray *splitLocation = [location componentsSeparatedByString:#", "];
cell.textLabel.text = [splitLocation objectAtIndex:0];
if (splitLocation.count == 2)
cell.detailTextLabel.text = [splitLocation objectAtIndex:1];
if (splitLocation.count == 3)
cell.detailTextLabel.text = [[[splitLocation objectAtIndex:1] stringByAppendingString:#","] stringByAppendingString:[splitLocation objectAtIndex:2]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
SinglePlaceViewController *spvc = [[SinglePlaceViewController alloc] init];
// Pass the selected object to the new view controller.
spvc.placeId = [[self placeAtIndexPath:indexPath] objectForKey:#"place_id"];
[self.navigationController pushViewController:spvc animated:YES];
[spvc release];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[places release];
[super dealloc];
}
#end
Thank You very much for your help and I'm really sorry for making you all guys do a bit of work for me.
You didn't provide much info about the error so i can only guess:
The error indicates that the object that get the message cellForRowAtIndexPath: don't actually have this method implemented.
But since you DID implemented it, the only reason i can think of is that you are messing with your tableView's "dataSource" property and changing it to something you shouldn't.
Make sure that the dataSource is your PlacecViewController.
From what it looks like to me, the getter method for your places property is not retaining the value it returns. You are setting it to an autoreleased instance of NSArray you're getting from the sortedArray method. I'm willing to bet it's being released after it displays your initial tableview cells.