Memory Management with UIPopoverController - iphone

I wanted to double check that I was doing correct memory management. Is this correct? Do I have the correct amount of releases.
In my .h file:
UITableView *_sortOrderTableView;
#property (nonatomic, retain) UITableView *SortOrderTableView;
In my .m file:
In dealloc
[_sortOrderTableView release];
My code that presents the popover is this:
- (IBAction)sortButtonOrderPressed:(id)sender {
UIViewController *sortOrderController = [[UIViewController alloc] init];
self.SortOrderTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 100)];
self.SortOrderTableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"App_Background.png"]];
self.SortOrderTableView.bounces = NO;
self.SortOrderTableView.scrollEnabled = NO;
sortOrderController.view = self.SortOrderTableView;
sortOrderController.contentSizeForViewInPopover = CGSizeMake(200, 100);
self.SortOrderTableView.delegate = self;
self.SortOrderTableView.dataSource = self;
self.SortPopover = [[UIPopoverController alloc] initWithContentViewController:sortOrderController];
[self.SortPopover presentPopoverFromRect:_sortButtonOrder.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[self.SortOrderTableView release];
[sortOrderController release];
}

Remove [self.SortOrderTableView release];, it should be [_sortOrderTableView release]; or self.SortOrderTableView = nilanyway, but you're already calling that in your dealloc method, so there is no need to release it here. If you want to release it though, use self.SortOrderTableView = nil.
Apart from that you will also have to release your SortPopover's instance variable in your dealloc method.

Related

When does searchDisplayController delegate methods get called?

I set up my searchDisplayController and searchBar like so:
UISearchBar *aSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 150, 44)];
self.reportSearchBar = aSearchBar;
_reportSearchBar.tintColor = DARKGRAY_COLOR;
_reportSearchBar.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
_reportSearchBar.delegate = self;
[aSearchBar release];
UISearchDisplayController *searchDisplayCtlr = [[UISearchDisplayController alloc] initWithSearchBar:self.reportSearchBar contentsController:self];
self.reportSearchDisplayController = searchDisplayCtlr;
self.reportSearchDisplayController.searchResultsDataSource = self;
self.reportSearchDisplayController.searchResultsDelegate = self;
[searchDisplayCtlr release];
UIBarButtonItem *searchBBI = [[UIBarButtonItem alloc] initWithCustomView:_reportSearchBar];
self.reportSearchBBI = searchBBI;
[searchBBI release];
[self.navigationItem setRightBarButtonItem:_reportSearchBBI animated:NO];
I checked if my ViewController conforms to the class just in case:
if ([self conformsToProtocol:#protocol(UISearchDisplayDelegate)]) {
NSLog(#"conform to search display");
}
My ViewController .h file has:
<UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchDisplayDelegate>
however, I set a break point at
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString];
return YES;
}
And it never reaches there. I implement one of the UISearBarDelegate methods and it does get to that method. When I run Apple's example code TableSearch, the searchDisplayController delegate method copied above does get run. So for me, I try to put in text into the search bar and my app crashes since the filtered list has no objects in it since the searchDisplayController delegate never gets called.
Thoughts? Thanks!
I just see in the apple reference:
searchController = [[UISearchDisplayController alloc]
initWithSearchBar:searchBar contentsController:self];
searchController.delegate = self;
searchController.searchResultsDataSource = self;
searchController.searchResultsDelegate = self;
I dont see the searchController.delegate = self in your code, isn't that nessesary?
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UISearchDisplayController_Class/Reference/Reference.html
Make sure you create an iVar for the UISearchDisplayController in your header file.
If you create an UISearchDisplayController using:
UISearchDisplayController* searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchField contentsController:self];
it will get released by ARC, it will not call any delegate methods and when you'll call self.searchDisplayController (the UIViewController's property) it will be nil.
So, the fix is:
In your header (.h) file:
#interface MenuViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate> {
UISearchDisplayController* searchDisplayController;
UISearchBar *searchField;
UITableView* tableView;
NSArray* searchResults;
}
and in the implementation (.m) file:
searchField = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 49)];
searchField.delegate = self;
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchField contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
tableView.tableHeaderView = searchField;
tableView.contentOffset = CGPointMake(0, searchField.frame.size.height);
When implemented like that, you can call both self.searchDisplayController and searchDisplayController in the rest of your code.

Memory management of UITableViewController, UITableView & UIPopoverController

I trying to figure out the best way to perform memory management on the following implementation:
I've a UIPopoverController which will be created upon viewDidLoad of the view and only be gone when viewDidUnload.
And Inside the UIPopoverController, I'm displaying a UITableView.
Here is my current implementation in .h:
UIPopoverController *aPopoverController;
#property (nonatomic, retain) UIPopoverController *aPopoverController;
In .m:
#synthesize *aPopoverController;
Inside a method in .m which is called when viewDidLoad:
UITableViewController *aTableViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
UITableView *aTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 800)];
aTableViewController.tableView = aTableView;
aTableView.delegate = self;
aTableView.dataSource = self;
aPopoverController = [[UIPopoverController alloc] initWithContentViewController:aTableViewController];
How should I release these objects when viewDidUnload?
Feel free to release both aTableView and aTableViewController right after this code.
To be more specific, UITableViewController retains the table view, so you don't need to keep it anymore, and UIPopoverController retains the content view controller, so you can release aTableViewController once you passed it to the popover controller.
In -viewDidUnload your popover controller is released, and it releases table view controller, which then releases the table view. Simple as that.
I'd put it like this:
UITableViewController *aTableViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
UITableView *aTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 800)];
aTableView.delegate = self;
aTableView.dataSource = self;
aTableViewController.tableView = aTableView;
[aTableView release];
aPopoverController = [[UIPopoverController alloc] initWithContentViewController:aTableViewController];
[aTableViewController release];

Memory leak with array

Can someone point me in the right direction. When I load this file in as a nib, and unload it, and reload it instruments says I'm getting a memory leak. Specifically, it's says that where I set the compareOptions NSMutableArray, and where I call [vc release].
CompareOptions is a synthesize property that is also released in the dealloc.
Many thanks in advance.
- (void)viewDidLoad{
[super viewDidLoad];
//NSLog(#"Comparison.viewDidLoad");
self.compareOptions = [[NSMutableArray alloc] init];
self.tabs = [[ComparisonTabs alloc] initWithFrame:CGRectMake(450, 85, 650, 50)];
//NSDictionary * currComparison = (NSDictionary*)[data objectAtIndex:0];
//NSArray * correctOptions = [currComparison objectForKey:#"correct"];
for(int i = 0; i < 3; i++)
{
UIViewController * vc = [[UIViewController alloc] initWithNibName:#"ComparisonOptions" bundle:nil];
ComparisonOptions * options = (ComparisonOptions *)vc.view;
[options setup];
options.index = i;
//options.frame = CGRectMake(355 + (306 * i), 475, options.frame.size.width, options.frame.size.height);
//[options setCorrect:[correctOptions objectAtIndex:i]];
[vc release];
[self.view addSubview:options];
[self.compareOptions addObject:options];
}
[self.view addSubview:self.tabs];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tabSelectedHandler:) name:#"tabSelected" object:nil ];
[self update:0];}
how does the property of compareOptions and tabs look like? Does it retain your objects?
If it does retain, then you'll get a double retain if you use the setter and alloc.
self.compareOptions = [[NSMutableArray alloc] init];
^ retains ^^^^^ retains
self.tabs = [[ComparisonTabs alloc] initWithFrame:CGRectMake(450, 85, 650, 50)];
^ retains ^^^^^ retains
you could use this instead
self.compareOptions = [NSMutableArray array];
self.tabs = [[[ComparisonTabs alloc] initWithFrame:CGRectMake(450, 85, 650, 50)] autorelease];
UIViewController * vc = [[UIViewController alloc] initWithNibName:#"ComparisonOptions" bundle:nil];
ComparisonOptions * options = (ComparisonOptions *)vc.view;
[vc release];
[self.view addSubview:options];
vc.view (ie options) will be deallocated at the same time vc will be deallocated. And this happens when you call [vc release]. You can't use options after this.
You should release vc after you've added the view to the subview.
And you should think about better class names. I would never assume that ComparisonOptions is a View. It sounds more like NSCaseInsensitiveSearch etc. You know, like it would be an option.

UITabBarContrtoller achieve from a different class in iPhone

I have the following problem:
There is a class that includes five tabs in the following way:
mainMenuClient.h
#import <UIKit/UIKit.h>
#interface MainMenuClient : UIViewController {
UITabBarController *tabBarController;
}
#property (nonatomic, retain) UITabBarController *tabBarController;
#end
mainMenuClient.m
-(void)viewDidLoad {
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor blackColor];
self.view = contentView;
[contentView release];
ContactListTab *contactTab = [[ContactListTab alloc] init];
ChatTab *chat = [[ChatTab alloc]init];
DialerTab *dialer = [[DialerTab alloc]init];
MenuTab *menu = [[MenuTab alloc]init];
TesztingFile *teszting = [[TesztingFile alloc]init];
contactTab.title = #"Contact List";
chat.title = #"Chat";
dialer.title = #"Dialer";
menu.title = #"Menu";
teszting.title = #"TesztTab";
contactTab.tabBarItem.image = [UIImage imageNamed:#"Contacts_icon.png"];
chat.tabBarItem.image = [UIImage imageNamed:#"Chat_icon.png"];
dialer.tabBarItem.image = [UIImage imageNamed:#"Dialer_icon.png"];
menu.tabBarItem.image = [UIImage imageNamed:#"Menu_icon.png"];
teszting.tabBarItem.image = [UIImage imageNamed:#"Contacts_icon.png"];
chat.tabBarItem.badgeValue = #"99";
tabBarController = [[UITabBarController alloc]init];
tabBarController.view.frame = CGRectMake(0, 0, 320, 460);
[tabBarController setViewControllers:[NSArray arrayWithObjects:contactTab, chat, dialer, menu, teszting, nil]];
[contactTab release];
[chat release];
[dialer release];
[menu release];
[teszting release];
[self.view addSubview:tabBarController.view];
[super viewDidLoad];
}
In the contactTab class there are a UITableViewController.
contactTab.h
- (void)updateCellData;
- (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath;
There is a third class, which I would like to achieve is a method of UITableViewController's (from ContactTab).
So far I tried this:
When I tried to achieve the UItabbarController:
MainMenuClient *menu;
UITabBarController *tabBarControllerchange = [[UITabBarController alloc] init];
tabBarControllerchange = menu.tabBarController;
[tabBarControllerchange setSelectedIndex:0];
When I tried to achieve the UITableViewController:
ContactListTab *contactListTab;
[contactListTab updateCellData];
Does anybody have an idea for this problem? Thanks. Balazs.
You need to get the instance of your MainMenuClient:
define method in your MainMenuClient.h as:
+(MainMenuClient*)getMainMenuInstance;
Implement the following method in MainMenuClient.m as :
+(MainMenuClient*)getMainMenuInstance
{
return self;
}
Now you can get same instance of UITabBarContrtoller in any class as :
MainMenuClient *menuClient = [MainMenuClient getMainMenuInstance];
UITabBarContrtoller *newTabBarController = menuClient.tabBarController;
You can do what ever you want to do with this new UITabBarController object.
Hope this helps.
Jim.

Problem: Can´t pass a NSUInteger from one ViewController to the other anymore

I want pass a number from my ViewController to the the TweetViewController. Everything worked okay, I did it with NSUInteger as property (randomNumber and tweetNumber):
TweetViewController *Second = [[TweetViewController alloc] initWithNibName:nil bundle:nil];
Second.tweetNumber = randomNumber;
Second.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:Second animated:YES];
[Second release];
I have now changed my code because I did not want that only my TweetViewVontroller is loaded. I wanted a homescreenlike swipe between the Tweet- and InfoViewController. I use a SwitchViewController, which will be load instead of the TweetViewController. The SwitchViewController looks like this (window1/2 are UIViewController):
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,460)];
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0,0,640,460)];
self.window1 = [TweetViewController alloc];
self.window2 = [InfoViewController alloc];
[contentView addSubview:self.window1.view];
CGRect f = self.window2.view.frame;
f.origin.x = 320;
self.window2.view.frame = f;
[contentView addSubview:self.window2.view];
[scrollView addSubview:contentView];
scrollView.contentSize = contentView.frame.size;
scrollView.pagingEnabled = YES;
self.view = scrollView;
[contentView release];
[scrollView release];
Now I can´t pass the number from the FirstViewController to the TweetViewController. Any Idea, how to solve the problem?
window1.tweetNumber = randomNumber;
If you want to update this every time the scrollview is scrolled, you might want to look into the UIScrollViewDelegate protocol. Specifically scrollViewWillBeginDragging: