UITableView returns null? - objective-c

I have spent many hours looking into this and I still can't find a solution. Here's a chart on what the user goes through:
The user takes a picture or takes one from their camera roll
As soon as they take (or select) one, the captionView closes
As soon as the captionView closes, startUploads from a different view starts
If the user decides to open the view that startUploads is in, they can see what has been uploaded
Now that you know a little bit about the process, I have a few issues. When uploads finish I want them to fade out. I know how to do that, but for some reason when I call to, the self.theTableView returns null. I have a #property (nonatomic, retain)... in my .h and I have a #sythesize theTableView; in my .m.
In a different question, I found out that when doing the startUploads, my NSMutableArray needed to be initiated in here (so I thought that it would do the same with my UItableView). Here's what I have:
- (id)initWithNibNamed:(NSString *)nibName bundle:(NSBundle *)bundle {
self = [super initWithNibNamed:nibName bundle:bundle];
if (self) {
processList = [[NSMutableArray alloc] init];
self.theTableView = [[UITableView alloc] init];
NSLog(#"thetableview: %#", theTableView);
}
return self;
}
Just in case you want to see how startUploads is called, here's the code:
processViewController *testtest = [[processViewController alloc] initWithNibName:#"processView.xib" bundle:nil];
//testtest.processList = [[NSMutableArray alloc] initWithNig];
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC BEFORE STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest startUploads];
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, processList = %#", testtest.processList);
NSLog(#"Different:displayProcessVC AFTER STARTING UPLOAD, theTableView = %#", testtest.theTableView);
[testtest release];
However it still shows (null) in the console.
Please help!Coulton
EDIT 1:
Here's where it's being nil:
- (void)deleteOneRow: (NSString *)theString {
int theInt = [processList indexOfObject:theString];
[processList removeObjectAtIndex:theInt];
NSArray *deleteIndexPaths = [[NSArray alloc] initWithObjects: [NSIndexPath indexPathForRow:theInt inSection:0], nil];
NSLog(#"theTableView: %#", self.theTableView);
[self.theTableView beginUpdates];
[self.theTableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.theTableView endUpdates];
}

The designated initializer for UITableView is -initWithFrame:style: and you're leaking. Try this in -viewDidLoad instead.
self.theTableView = [[[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain] autorelease];

Related

MASPreferences choose view

I am using MASPreferences in my app, I was able to set up everything correctly, with 3 different views (preferences, login and about).What I would like to do is to choose which panel gets shown when the window is opened. This is so that when the user clicks on about, the about panel is shown, etc. instead of the last panel shown being the one displayed. As of now I have tried modifying the entry in the plist file, but it does not seem to work. Is there any other way?
So after a bit of trying, and by using #Jasper's answer, I came up with the following:
-(void)openPreferencesWindowWithIdentifier:(NSString *)identifier {
[NSApp activateIgnoringOtherApps:YES];
[[NSUserDefaults standardUserDefaults] setValue:identifier forKey:#"MASPreferences Selected Identifier View"];
// Create the preferences window
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc]initWithNibName:#"GeneralPreferencesViewController" bundle:nil];
NSViewController *loginViewController = [[PushoverLoginViewController alloc]initWithNibName:#"PushoverLoginViewController" bundle:nil];
NSViewController *aboutViewController = [[AboutPreferencesViewController alloc]initWithNibName:#"AboutPreferencesViewController" bundle:nil];
NSArray *controllers = [[NSArray alloc]initWithObjects:generalViewController,loginViewController,[NSNull null],aboutViewController, nil];
NSString *windowTitle = NSLocalizedString(#"Preferences", #"Comon title for preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc]initWithViewControllers:controllers title:windowTitle];
[self.preferencesWindowController showWindow:nil];
}
Essentially this method writes the required "tab" on the plist file, and then initalizes a new instance everytime. By doing so, the correct view is loaded. The identifier parameter is the one you set up for each of the views. Thanks again to Jasper for his answer, really helped me understand how to figure this one out!
MASPreferences remembers the last opened 'tab'
Change in the order in your array when passing it to your MASPreferencesWindowController should work to change the order of your tabs.
-(NSWindowController *)preferencesWindowController
{
if (_preferencesWindowController == nil)
{
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc] init];
NSViewController *accountViewController = [[AccountPreferencesViewController alloc] init];
NSViewController *troubleshootingViewController = [[TroubleShootingPreferencesViewController alloc] init];
//Change the order here
NSArray *controllers = [[NSArray alloc] initWithObjects:accountViewController, generalViewController, troubleshootingViewController, nil];
NSString *title = NSLocalizedString(#"Preferences", #"Common title for Preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc] initWithViewControllers:controllers title:title];
}
return _preferencesWindowController;
}
Have a look inside MASPReferencesWindowController.m line 6. There is a static NSString key which handles the logic to show the last selected tab
static NSString *const kMASPreferencesSelectedViewKey = #"MASPreferences Selected Identifier View";
The key is used in:
- (void)windowDidLoad
{
if ([self.title length] > 0)
[[self window] setTitle:self.title];
if ([self.viewControllers count])
self.selectedViewController = [self viewControllerForIdentifier:[[NSUserDefaults standardUserDefaults] stringForKey:kMASPreferencesSelectedViewKey]] ?: [self firstViewController];
NSString *origin = [[NSUserDefaults standardUserDefaults] stringForKey:kMASPreferencesFrameTopLeftKey];
if (origin)
[self.window setFrameTopLeftPoint:NSPointFromString(origin)];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidMove:) name:NSWindowDidMoveNotification object:self.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(windowDidResize:) name:NSWindowDidResizeNotification object:self.window];
}
TL;DR
Look for the method - (void)setSelectedViewController:(NSViewController <MASPreferencesViewController> *)controller inside MASPreferencesWindowController.m
Comment this line:
// Record new selected controller in user defaults
[[NSUserDefaults standardUserDefaults] setObject:controller.identifier forKey:kMASPreferencesSelectedViewKey];
Now change the way you initialise your NSWindowController so you create a new instance every time, otherwise it will still remember the last selected tab:
-(NSWindowController *)preferencesWindowController
{
NSViewController *generalViewController = [[GeneralPreferencesViewController alloc] init];
NSViewController *accountViewController = [[AccountPreferencesViewController alloc] init];
NSViewController *troubleshootingViewController = [[TroubleShootingPreferencesViewController alloc] init];
//NSArray *controllers = [[NSArray alloc] initWithObjects:generalViewController, accountViewController, troubleshootingViewController, nil];
NSArray *controllers = [[NSArray alloc] initWithObjects:accountViewController, generalViewController, troubleshootingViewController, nil];
// To add a flexible space between General and Advanced preference panes insert [NSNull null]:
// NSArray *controllers = [[NSArray alloc] initWithObjects:generalViewController, [NSNull null], advancedViewController, nil];
NSString *title = NSLocalizedString(#"Preferences", #"Common title for Preferences window");
_preferencesWindowController = [[MASPreferencesWindowController alloc] initWithViewControllers:controllers title:title];
return _preferencesWindowController;
}

Why would a property essentially disappear? Obj-C, Cocoa

I am quite stumped. I have an app with a class for storing item details. Called LEItem. Those items are stored in a store with a class labeled LEItemStore. I have a view with a table of all items. This works fine. If you tap on a row, it sends this message to LogbookFirstViewController.
LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];
NSArray *items = [[LEItemStore sharedStore] allItems];
LEItem *selectedItem = [items objectAtIndex:[indexPath row]];
NSString *description = [selectedItem description];
NSLog(#"%#", description);
[logController setItem:selectedItem];
[self dismissViewControllerAnimated:YES completion:nil];
That is in a TableView class. In the LogbookFirstViewController.m I have
-(void)setItem:(LEItem *)i{
item = i;
NSString *t = [item description];
NSLog(#"In LogbookFirstViewController, returning %#", t);
}
This is where it gets odd. That works. It outputs the correct item, therefore I would think everything would be okay. But it's not. item is a class-level property, so it should stay, but it doesn't. In the same class, I have overrode this method.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//NSString *string = [item description];
//NSLog(#"Item = %#", string);
NSLog(#"View did Appear:animated");
int glucoseValue = [item glucose];
NSString *glucoseString = [NSString stringWithFormat:#"%d", glucoseValue];
[glucoseField setText:glucoseString];
int proteinValue = [item protein];
NSString *proteinString = [NSString stringWithFormat:#"%d", proteinValue];
[proteinField setText:proteinString];
int carbsValuue = [item carbs];
NSString *carbsString = [NSString stringWithFormat:#"%d", carbsValuue];
[carbsField setText:carbsString];
int insulinValue1 = [item insulin];
NSString *insulin1String = [NSString stringWithFormat:#"%d", insulinValue1];
[insulinField1 setText:insulin1String];
int insulinValue2 = [item insulin2];
NSString *insulinString2 = [NSString stringWithFormat:#"%d", insulinValue2];
[insulinField2 setText:insulinString2];
//NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
//[dateFormatter setDateStyle:NSDateFormatterShortStyle];
//[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
//NSLog(#" The item was created on %#", [dateFormatter stringFromDate:[item dateCreated]]);
//[dateButton setTitle:[dateFormatter stringFromDate:[item dateCreated]] forState:UIControlStateNormal];
NSString *t = [item description];
NSLog(#"Loading view... Returns: %#", t);
}
I know that it isn't the cleanest code, but the idea is the same. It uses exactly the same code as the setItem: method. However, this always returns (null). Why? The property appears to go missing at viewWillAppear.
Thanks.
EDIT
I solved the problem. As you can see, the checked answer below did give the right idea, here is what I did to solve it. The problem was that when I sent setItem: I used this code to get LogbookFirstViewController
LogbookFirstViewController *logController = [[LogbookFirstViewController alloc] initForNewItem:NO];
As I know see, that created a new instance of LogbookFirstViewController, so therefore, the existing one did not change it's Item property, as properties are assigned to one instance. Therefore, I was only changing the value of Item for this "invisible" property.
To solve this, one must get the existing instance of the viewController. To do this I did the following:
In LogbookFirstViewController.h I added this property
#property (assign) LogbookFirstViewController *instance;
Then, synthesize instance in your .m and in the same placed I added this to viewDidLoad
- (void)viewDidLoad
{
instance = self;
...
Then, in the other viewController, entriesViewController, I added this too the .h
#property (nonatomic, strong) LogbookFirstViewController *logController;
Synthesize it. Then, I just used my didSelectRowAtIndexPath the same way, just using the existing logController
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *items = [[LEItemStore sharedStore] allItems];
LEItem *selectedItem = [items objectAtIndex:[indexPath row]];
NSString *description = [selectedItem description];
NSLog(#"%#", description);
NSLog(#"Setting controller: %#", logController);
[logController setItem:selectedItem];
[self dismissViewControllerAnimated:YES completion:nil];
}
Then it works!
You have a line where you create the LogbookFirstViewController but you don't actually cause it to display anything (push or present). Since it's a local variable, it would appear that whatever instance of that controller is loading its view is not the same one that you initialize in the code you've shown.
You can verify this by adding a couple of NSLog lines, such as:
NSLog(#"Setting controller: %#", logController); // Insert before existing line
[logController setItem:selectedItem];
...and...
[super viewWillAppear:animated];
NSLog(#"Viewing controller: %#", self); // Insert after existing line
For things to work the way you want, those have to print the same address.
You should retain when assigning object to property without ARC:
-(void)setItem:(LEItem *)i{
_item = [i retain];
...
}
If you use property with ARC, then write _item = i;:
-(void)setItem:(LEItem *)i{
_item = i;
...
}

Accessing property without self.propertyname cause errors

I'm working on App with coreData and i get an error that i can't understand: In a custom init whether i define NSFetchedResultController with "self.controller = new_controller" all works correctly, if i define only "controller = new_controller" (without self), error "The NSManagedObject has been invalidated" occur after 2 loops for the situation described in this image:
Application parts interested in this error is here described:
A Table with a list of Months (Class MonthListVC, step 1 in the image). Where
sections describe Month (like April
2011) and the unique Row for any
section present data (that are sum
from transactions happened during the
month).
Selecting one of these Row a next
Table is pushed in navigation
controller (Class WeekTVC, step 2 in the image), this table presents
detail for every weeks for selected month. Here section title has format "week beginning - week end", and the unique row for the section is a sum of transactions for the week.
A NSManagedObjectContext is passed via a custom init method (check the code)
every data for these tables are managed with
NSFetchedResultController.
Here the code for selection on first Table (MonthListVC)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:indexPath.section];
// get the first object for this section and get its date.
NSDate *datepoint = [[[sectionInfo objects]objectAtIndex:0] date];
//Create next Controller and push it into Navigation
WeeksTVC *weeksTVC = (WeeksTVC*)[[WeeksTVC alloc] initWithContext:self.context datepoint:datepoint withTitle: [sectionInfo name] ];
[self.navigationController pushViewController:weeksTVC animated:YES];
[weeksTVC release];
}
And here the code for WeeksTVC custom init method, where i define "self.controller = ..." and where i get the problem whether i write only "controller = ...".
"controller" is a synthesized property.
-(WeeksTVC *)initWithContext:(NSManagedObjectContext *)n_context datepoint:(NSDate*)n_datePoint withTitle:(NSString*) stringTitle{
self = [self init];
if(self !=nil){
self.title = [NSString stringWithFormat:#"History (%#)",stringTitle];
//Back button setup
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init];
barButton.title = #"Back";
self.navigationItem.backBarButtonItem = barButton;
//datePoint = n_datePoint;
self.context = n_context;
//Get Begin and End week information for this datePoint
NSDate *startDay = [[CommonHelper weekInfoFromData:[CommonHelper firstDayOfMonthForDate:n_datePoint]] objectForKey:#"begin"];
NSDate *endDay = [[CommonHelper weekInfoFromData:[CommonHelper lastDayOfMonthForDate:n_datePoint]] objectForKey:#"end"];
//Manage Request
NSFetchRequest *request = [[NSFetchRequest alloc]init];
request.entity = [NSEntityDescription entityForName:#"Transactions" inManagedObjectContext:self.context];
request.predicate = [NSPredicate predicateWithFormat:#"(date >= %#) && (date <= %#)",startDay,endDay];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"date" ascending:NO];
NSArray *sortDescs = [NSArray arrayWithObjects:sort,nil];
request.sortDescriptors = sortDescs;
"HERE THE PROBLEM WITH SELF***********************************************"
//Manage NSResultFetchedController
self.controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.context sectionNameKeyPath:#"byWeek" cacheName:nil];
self.controller.delegate = self;
NSError *error = nil;
//Fetch
[self.controller performFetch:&error];
"END OF PROBLEM***********************************************************"
[request release];
[barButton release];
}
return self;
}
I report also dealloc method for WeeksTVC, i found that if i don't release context and controller in this method... no error occur also if i write in init method "controller = " and not "self.controller = "
- (void)dealloc {
//[self.datePoint release];
[self.controller release];
[self.context release];
[super dealloc];
}
Why self.controller and controller are so different in this case ???
In init method i ever write ivar without self -.-'
In custo init method for WeeksTVC i wrote
self = [self init];
and not
self = [super init];
This cause the problem... but i'm curious to understand what happen exactly...

Get & Edit NSMutableArray from different class file

I am trying to access and change a array from a different class file. When using a NSLog, I get a result of (null). Below is my code:
RootViewController.h
NSMutableArray *listOfItems;
#property (nonatomic, retain) NSMutableArray *listOfItems;
RootViewController.m
#synthesize listOfItems;
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
[listOfItems addObject:#"Two"];
[listOfItems addObject:#"Three"];
SecondViewController.m
RootViewController *test = [[RootViewController alloc] init];
NSLog(#"Results: %#", test.listOfItems);
I get the following results in my console: Results: (null)
Thanks in advance,
Coulton
P.S. Obviously I have left out a bunch of code. I just tried to make it easier to read. If you need to see anything else, I would be more than happy to post more. Just ask
EDIT #1:
I am getting hundreds of NSLog Messages that look something like this:
*** __NSAutoreleaseNoPool(): Object 0x4e39020 of class __NSArrayI autoreleased with no pool in place - just leaking
And here's my init code:
- (id) init {
//NSLog(#"%#", theUserID);
// Set up database connection
NSString *myDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.db"];
database = [[Sqlite alloc] init];
[database open:myDB];
//Initialize the array.
listOfItems = [[NSMutableArray alloc] init];
// Add to array to display in the tableView
NSArray *listOfItemsTwo = [database executeQuery:#"SELECT * FROM albums"];
for (NSDictionary *rowone in listOfItemsTwo) {
NSString *getName = [rowone valueForKey:#"name"];
if (getName != NULL) {
[listOfItems addObject:getName];
[getName release];
}
}
return self;
}
I guess you reversed RootViewController.m and RootViewController.h snippets right?
Are you sure that the
listOfItems = [[NSMutableArray alloc] init];
gets called? Maybe you can put a breakpoint there.
EDIT: Order of RootViewController.m and RootViewController.h has been fixed in the question. It's not clear from the question where the above line is in the code. That's a important piece of information.
EDIT2: Example of init method.
#implementation RootViewController
- (id) init
{
listOfItems = [[NSMutableArray alloc] init];
[listOfItems addObject:#"One"];
return self;
}
#end

Issue Displaying/Hiding Views (Obj-C iPhone Programming)

All right all,
So I've got a UITableView that is inited in applicationDidFinishLaunching like so:
[self showForumList];
Said method does this:
-(void)showForumList {
ForumList *fl = [ForumList alloc];
[fl initWithNibName:#"ForumList" bundle:[NSBundle mainBundle]];
self.ForumList = fl;
[window addSubview:[self.ForumList view]];
[fl release];
}where self.ForumList is previously defined in the interface as ForumList *ForumList;, etc.
Now, in ForumList (itself an extension of UITableViewController obviously), I've got didSelectRowAtIndexPath: -- within it I have the following code:
Forum *f = [Forum alloc];
NSArray *forums = [f getForumList];
NSDictionary *selectedForum = [forums objectAtIndex:[indexPath row]];
NSString *Url = [selectedForum objectForKey:#"url"];
NSString *Username = [selectedForum objectForKey:#"username"];
NSString *Password = [selectedForum objectForKey:#"password"];
NSLog(#"Identified press on forum %# (%#/%#)", Url, Username, Password);
[self.globalDelegate showForumListFromForumUsingUrl:Url username:Username password:Password];
[self.globalDelegate closeForumList];
NSLog(#"ForumListFromForum init");
Both of the NSLog calls in this function are executed and perform as they should. Now, here is where the issue starts.
self.globalDelegate is defined as AppDelegate *globalDelegate; in the Interface specification in my header file. However, [self.globalDelegate showForumListFromForumUsingUrl:username:password] and and [self.globalDelegate closeForumList] are never actually called. They look like so:
-(void)closeForumList {
NSLog(#"Hiding forum list");
[[self.ForumList view] removeFromSuperview];
}
-(void)showForumListFromForumUsingUrl:(NSString *)Url username:(NSString *)Username password:(NSString *)Password {
NSLog(#"Showing forum list from forum");
ForumListFromForum *fl = [ForumListFromForum alloc];
[fl initWithNibName:#"ForumListFromForum" bundle:[NSBundle mainBundle]];
[fl initFromForumWithUrl:Url username:Username password:Password];
self.ForumListFromForum = fl;
[window addSubview:[self.ForumListFromForum view]];
[fl release];
}
The app responds to my press, yet neither of these NSLog calls are made, presumably because the calls to the method in appDelegate do not work.
Any idea where I've gone wrong?
I don't see a line, where self.globalDelegate is allocated & initialized. Maybe, it's the reason.
Moreover, check (in debugger) that in these lines:
[self.globalDelegate showForumListFromForumUsingUrl:Url username:Username password:Password];
[self.globalDelegate closeForumList];
self.globalDelegate is not nil. As you should remember - messages to nil are perceived as correct, but nothing happens.