UIWebView Delegate Code Doesn't Seem Right - xcode

I've implemented sample code using the UIWebView that I found, but it doesn't look right to me, though it works. Specifically because it sets the UIWevView delegate twice (in viewDidLoad and viewWillAppear). Also, myWebView is set as an autorelease object, but then it's released in dealoc. I'm hoping someone can tell me how to clean this up.
// *** WebViewController.h ***
#interface WebViewController : UIViewController
<UIWebViewDelegate>
{
UIWebView *myWebView;
UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) UIWebView *myWebView;
#property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
#end
// *** WebViewController.m ***
#synthesize myWebView;
- (void) viewDidLoad {
[super viewDidLoad];
// - - - - -> Create the UIWebView
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.origin.y += 42.0;
webFrame.size.height -= 106.0;
self.myWebView = [[[UIWebView alloc] initWithFrame:webFrame] autorelease];
self.myWebView.backgroundColor = [UIColor whiteColor];
self.myWebView.scalesPageToFit = YES;
self.myWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.myWebView.delegate = self;
[self.view addSubview: self.myWebView];
// - - - - -> Create the UIActivityIndicatorView
self.activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
[self.view addSubview: self.activityIndicator];
self.activityIndicator.center = CGPointMake(135,438);
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.someURL.com/"]]];
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.myWebView.delegate = self;
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.myWebView stopLoading];
self.myWebView.delegate = nil;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void) dealloc {
myWebView.delegate = nil;
[myWebView release];
[activityIndicator release];
[super dealloc];
}

It's pretty much fine to do that. The idea is pretty basic. You do not want the delegate to receive any delegation messages when off screen. So the idea of setting the delegate -viewWillAppear: and -viewWillDisappear: is correct. But I don't see any delegate methods being implemented in the code.

Related

Cocoa: NSToolBar with Custom Views. Animation issues

So I got a Window:
Window.xib
I got a WindowController too:
WindowController.h reads:
#import <Cocoa/Cocoa.h>
#interface MainWindowController : NSWindowController
{
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
IBOutlet NSView *thirdView;
int currentViewTag;
}
-(IBAction)switchView:(id)sender;
#end
And the WindowController.m reads:
#import "MainWindowController.h"
#interface MainWindowController ()
#end
#implementation MainWindowController
-(id)init
{
self = [super initWithWindowNibName:#"MainWindow"];
if (self){
// Initialization code here
}
return self;
}
//- (void)windowDidLoad {
// [super windowDidLoad];
//
// // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
//}
#pragma mark - Custom view drawing
-(NSRect)newFrameForNewContentView:(NSView *)view
{
NSWindow *window = [self window];
NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
NSRect oldFrameRect = [window frame];
NSSize newSize = newFrameRect.size;
NSSize oldSize = oldFrameRect.size;
NSRect frame = [window frame];
frame.size = newSize;
frame.origin.y -= (newSize.height - oldSize.height);
return frame;
}
-(NSView *)viewForTag:(int)tag{
NSView *view = nil;
if (tag == 0) {
view = firstView;
} else if (tag == 1) {
view = secondView;
} else {
view = thirdView;
}
return view;
}
-(BOOL) validateToolbarItem:(NSToolbarItem *)item
{
if ([item tag] == currentViewTag) return NO;
else return YES;
}
-(void)awakeFromNib
{
[[self window] setContentSize:[firstView frame].size];
[[[self window] contentView]addSubview:firstView];
[[[self window] contentView]setWantsLayer:YES];
}
-(IBAction)switchView:(id)sender
{
int tag = [sender tag];
NSView *view = [self viewForTag:tag];
NSView *previousView = [self viewForTag:currentViewTag];
currentViewTag = tag;
NSRect newFrame = [self newFrameForNewContentView:view];
[NSAnimationContext beginGrouping];
if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
[[NSAnimationContext currentContext] setDuration:1.0];
[[[[self window]contentView]animator]replaceSubview:previousView with:view];
[[[self window]animator]setFrame:newFrame display:YES];
[NSAnimationContext endGrouping];
}
#end
The problem I have is that when i switch tabs in my app, the custom view (and there are three of different sizes) draw differently each time. Look at the screenshots, all of the numbers should be centre aligned but they are sometimes and others not. Can anyone see what my error is please?
I will also add that all of the actions have been correctly configured + the code works perfectly if the custom view size is the same all the time.
The view that works
The view that almost works
Again pointing out that in my .xib all of the numbers are aligned to 0x and 0y axis.
Appdelegate.h
#import <Cocoa/Cocoa.h>
#class MainWindowController;
#interface AppDelegate : NSObject <NSApplicationDelegate> {
MainWindowController *mainWindowController;
}
#end
Appdelegate.m
#interface AppDelegate ()
#property (nonatomic) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
-(void)awakeFromNib
{
if(!mainWindowController){
mainWindowController = [[MainWindowController alloc]init];
}
[mainWindowController showWindow:nil];
}
#end
In Interface Builder, make sure to disable the "autoresizes subviews" checkbox of the default view of your window

Custom Checkbox Not Working As Expected

I'm attempting to create this checkbutton and then call that check button where ever I'd like in my project and have it work by adding an image like it's supposed to but I can't even get it to NSLog...for testing purposes...
Below are the button .h and .m files. and the view that I'm calling the button into and trying to use...
CheckButton.h
#import
#interface CheckButton : UIButton {
BOOL _checked;
}
#property (nonatomic, setter=setChecked:) BOOL checked;
-(void) setChecked:(BOOL)check;
#end
CheckButton.m
#import "CheckButton.h"
#implementation CheckButton
#synthesize checked = _checked;
-(id) init {
if (self=[super init]) {
self.checked = NO;
[self addTarget:self action:#selector(setChecked:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(void) awakeFromNib {
self.checked = NO;
[self addTarget:self action:#selector(OnCheck:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) setChecked:(BOOL)check{
_checked = check;
if(_checked) {
UIImage *img = [UIImage imageNamed:#"check.png"];
[self setImage:img forState:UIControlStateNormal];
NSLog(#"Checked");
} else {
UIImage *img = [UIImage imageNamed:#"uncheck.png"];
[self setImage:img forState:UIControlStateNormal];
NSLog(#"UnChecked");
}
}
-(void) OnCheck:(id) sender {
self.checked = _checked;
}
#end
GoToBedPopUp.h
#import "CheckButton.h"
#interface GoToBedPopup : PopupContainer{
IBOutlet CheckButton *checkboxButton;
}
// Checkboxes - (CheckButton)
#property (nonatomic, strong) CheckButton *checkHR;
#end
GoToBedPopUp.m
#import "GoToBedPopup.h"
#implementation GoToBedPopup
#synthesize checkHR, checkO2, checkMovement, checkNoise, checkSkinTemp;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
// Checkbox Button
checkHR = [[CheckButton alloc] initWithFrame:CGRectMake(17, 31, 23, 23)];
return self;
}
hi i tested your code every thing okay u just change only one thing....
- (void) setChecked:(BOOL)check{
_checked = !check; //** this is the only one change needed
if(_checked) {
UIImage *img = [UIImage imageNamed:#"Check.png"];
[self setImage:img forState:UIControlStateNormal];
NSLog(#"Checked");
} else {
UIImage *img = [UIImage imageNamed:#"Uncheck.png"];
[self setImage:img forState:UIControlStateNormal];
NSLog(#"UnChecked");
}
}
Sample project here

Page View Controller - from images to another view controller

I'm a bit perplexed about what I'm trying to accomplish. I have a page view controller that has a data source containing an array list of images. It's actually a tutorial that a user can flip through. What I'm trying to do is make the last page a log in screen so the user can enter info and hit a login button. I thought this would be as simple as adding a login view controller to the array but oooh how wrong I was D: When I tried that I got this error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController _isResizable]: unrecognized selector sent to instance 0xa160660'
I do apologise for being such a noob I'm new to all of this just trying to get my head around it. Here's my code (accomplished by using this site actually):
My data source (ModelController.h)
#import <Foundation/Foundation.h>
#class DataViewController;
#interface ModelController : NSObject <UIPageViewControllerDataSource>
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard;
- (NSUInteger)indexOfViewController:(DataViewController *)viewController;`
#end
ModelController.m
#import "ModelController.h"
#import "DataViewController.h"
#import "LoginViewController.h"
#interface ModelController()
#property (readonly, strong, nonatomic) NSArray *pageData;
#end
#implementation ModelController
- (id)init
{
self = [super init];
if (self)
{
// Create the data model
_pageData = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"tutorial1.png"],
[UIImage imageNamed:#"tutorial2.png"],
[UIImage imageNamed:#"lastWishes.png"],
[UIImage imageNamed:#"todo.png"],
[UIImage imageNamed:#"web.png"],
(LoginViewController*)[[UIViewController alloc] init],
nil];
}
return self;
}
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard
{
// Return the data view controller for the given index.
if (([self.pageData count] == 0) || (index >= [self.pageData count]))
{
return nil;
}
// Create a new view controller and pass suitable data.
DataViewController *dataViewController = [storyboard instantiateViewControllerWithIdentifier:#"DataViewController"];
dataViewController.dataObject = self.pageData[index];
return dataViewController;
}
- (NSUInteger)indexOfViewController:(DataViewController *)viewController
{
// Return the index of the given data view controller.
// For simplicity, this implementation uses a static array of model objects and the view controller stores the model object; you can therefore use the model object to identify the index.
return [self.pageData indexOfObject:viewController.dataObject];
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger index = [self indexOfViewController:(DataViewController *)viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = [self indexOfViewController:(DataViewController *)viewController];
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.pageData count]) {
return nil;
}
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
#end
The Parent (RootViewController.h)
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController <UIPageViewControllerDelegate>
#property (strong, nonatomic) UIPageViewController *pageViewController;
#end
RootViewController.m
#import "RootViewController.h"
#import "ModelController.h"
#import "DataViewController.h"
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#end
#implementation RootViewController
#synthesize modelController = _modelController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationVertical options:nil];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (ModelController *)modelController
{
// Return the model controller object, creating it if necessary.
// In more complex implementations, the model controller may be passed to the view controller.
if (!_modelController) {
_modelController = [[ModelController alloc] init];
}
return _modelController;
}
#pragma mark - UIPageViewController delegate methods
/*
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating: (BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted: (BOOL)completed
{
}
*/
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
// Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here.
UIViewController *currentViewController = self.pageViewController.viewControllers[0];
NSArray *viewControllers = #[currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMin;
}
#end
The Child (DataViewController.h)
#import <UIKit/UIKit.h>
#interface DataViewController : UIViewController
#property (strong, nonatomic) id dataObject;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
DataViewController.m
#import "DataViewController.h"
#interface DataViewController ()
#end
#implementation DataViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.imageView.image = _dataObject;
}
#end
Once again, the code in question is here where I'm trying to add a view controller to the data source as the last page:
_pageData = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"tutorial1.png"],
[UIImage imageNamed:#"tutorial2.png"],
[UIImage imageNamed:#"lastWishes.png"],
[UIImage imageNamed:#"todo.png"],
[UIImage imageNamed:#"web.png"],
(LoginViewController*)[[UIViewController alloc] init],
nil];
and getting unrecognized selector error when at runtime. I've also tried this as well:
- (id)init
{
self = [super init];
if (self)
{
LoginViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
// Create the data model
_pageData = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"tutorial1.png"],
[UIImage imageNamed:#"tutorial2.png"],
[UIImage imageNamed:#"lastWishes.png"],
[UIImage imageNamed:#"todo.png"],
[UIImage imageNamed:#"web.png"],
viewController,
nil];
}
return self;
}
Any suggestions would be great. THanks!!
Your idea is 100% correct, your implementation is not.
This line:
dataViewController.dataObject = self.pageData[index];
is very suspicious because that will return a UIViewController in the case of your login screen. I would suggest you type-check your page data, if it is already a UIViewController subclass, just return it, if it is (in your case) a UIImage add it as the data object.

Need help debugging switchChanged method

Am getting error ("switchChanged" undeclared) in the implementation file, but can't find the problem. Can you help me?
TIA
ViewController.m
#import "Control_FunViewController.h"
#implementation Control_FunViewController
#synthesize nameField;
#synthesize numberField;
#synthesize sliderLabel;
#synthesize leftSwitch;
#synthesize rightSwitch;
#synthesize doSomethingButton;
-(IBAction)sliderChanged:(id)sender
{
UISlider *slider = (UISlider *)sender;
int progressAsInt = (int)(slider.value + 0.5f);
NSString *newText = [[NSString alloc] initWithFormat:#"%d",progressAsInt];
sliderLabel.text = newText;
[newText release];
}
-(IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
-(IBAction)backgroundTap:(id)sender
{
[nameField resignFirstResponder];
[numberField resignFirstResponder];
}
-(IBAction)toggleControls:(id)sender
{
if ([sender selectedSegmentIndex] == kSwitchesSegmentIndex)
{
leftSwitch.hidden = NO;
rightSwitch.hidden = NO;
doSomethingButton.hidden = YES;
}
else {
leftSwitch.hidden =YES;
rightSwitch.hidden =YES;
doSomethingButton.hidden = NO;
}
-(IBAction)switchChanged:(id)sender
{
UISwitch *whichSwitch = (UISwitch *)sender;
BOOL setting = whichSwitch.isOn;
[leftSwitch setOn:setting animated:YES];
[rightSwitch setOn:setting animated:YES];
}
-(IBAction)buttonPressed
{
//TODO: Implement Action Sheet and Alert
}
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[nameField release];
[numberField release];
[sliderLabel release];
[leftSwitch release];
[rightSwitch release];
[doSomethingButton release];
[super dealloc];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#define kSwitchesSegmentIndex 0
#interface Control_FunViewController : UIViewController {
UITextField *nameField;
UITextField *numberField;
UILabel *sliderLabel;
UISwitch *leftSwitch;
UISwitch *rightSwitch;
UIButton *doSomethingButton;
}
#property(nonatomic,retain)IBOutlet UITextField *nameField;
#property(nonatomic,retain)IBOutlet UITextField *numberField;
#property(nonatomic,retain)IBOutlet UILabel *sliderLabel;
#property(nonatomic,retain)IBOutlet UISwitch *leftSwitch;
#property(nonatomic,retain)IBOutlet UISwitch *rightSwitch;
#property(nonatomic,retain)IBOutlet UIButton *doSomethingButton;
-(IBAction)textFieldDoneEditing:(id)sender;
-(IBAction)backgroundTap:(id)sender;
-(IBAction)sliderChanged:(id)sender;
-(IBAction)toggleControls:(id)sender;
-(IBAction)switchChanged:(id)sender;
-(IBAction)buttonPressed;
#end
The colon (:) is part of the name of the method, but you haven't included it in the error message. It may be that you just forgot, but if you're calling -switchChanged (no colon) from somewhere, or if you connected a control using the action -switchChanged (no colon), that's the problem. Perhaps you added the colon and sender parameter later on?

objectAtIndex - Message sent to deallocated instance

I am having a real problem finding where my problem is in my search controller. This is a table view with search bar and search display controller. It used to work fine, but all the sudden it stopped working. I turned on NSZombieEnabled and it shows that my NSArray called searchDataSource is the zombie.
When you type a search term the "shouldReloadTableForSearchTerm" executes the handleSearchForTerm function. The handleSearchForTerm" function accesses my ProductInfo class that query a SQLite database and returns the query results. Those results are then placed in my searchDataSource Array. Everything appears to work fine there. However, once I get to the "cellForRowAtIndexPath" function and I try to load the cells from the searchDataSource, that is when I run in to the problem of the Array having been deallocated.
Here is my code for the search controller:
//
// SearchViewController.h
// Priority Wire
//
// Created by Keith Yohn on 2/2/11.
// Copyright 2011 Priority Wire & Cable. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface FourthViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate> {
UITableView *mainTableView;
NSArray *searchDataSource;
NSMutableArray *contentsList;
NSMutableArray *searchResults;
NSString *savedSearchTerm;
NSString *webURL;
}
#property (nonatomic, retain) IBOutlet UITableView *mainTableView;
#property (nonatomic, retain) IBOutlet NSArray *searchDataSource;
#property (nonatomic, retain) NSMutableArray *contentsList;
#property (nonatomic, retain) NSMutableArray *searchResults;
#property (nonatomic, copy) NSString *savedSearchTerm;
#property (nonatomic, retain) NSString *webURL;
- (void)handleSearchForTerm:(NSString *)searchTerm;
#end
SearchViewController.m
//
// SearchViewController.m
// Priority Wire
//
// Created by Keith Yohn on 2/2/11.
// Copyright 2011 Priority Wire & Cable. All rights reserved.
//
#import "FourthViewController.h"
#import "ProductsDatabase.h"
#import "ProductInfo.h"
#import "WebViewController.h"
#implementation FourthViewController
#synthesize mainTableView;
#synthesize searchDataSource;
#synthesize contentsList;
#synthesize searchResults;
#synthesize savedSearchTerm;
#synthesize webURL;
- (void)viewDidLoad {
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.searchDataSource count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Set up the cell...
ProductInfo *info = [searchDataSource objectAtIndex:indexPath.row]; //This is where I get the 'message sent to deallocated instance' message.
[cell.textLabel setText:info.sName];
[cell.detailTextLabel setText:info.sType];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ProductInfo *info = [searchDataSource objectAtIndex:indexPath.row];
webURL = [NSString stringWithFormat:#"http://www.prioritywire.com/specs/%#", info.sFile];
WebViewController *wvController = [[WebViewController alloc] initWithNibName:#"WebViewController" bundle:[NSBundle mainBundle]];
wvController.URL = webURL;
wvController.navTitle = #"Spec Sheet";
[self.navigationController pushViewController:wvController animated:YES];
[wvController release];
}
- (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 {
[super viewDidUnload];
// Save the state of the search UI so that it can be restored if the view is re-created.
[self setSavedSearchTerm:[[[self searchDisplayController] searchBar] text]];
[self setSearchResults:nil];
}
- (void)dealloc {
[searchDataSource release], searchDataSource = nil;
[mainTableView release];
[contentsList release];
[searchResults release];
[savedSearchTerm release];
[super dealloc];
}
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
[array release], array = nil;
} else {
NSArray *productInfo = [[ProductsDatabase database] searchListing:searchTerm];
self.searchDataSource = productInfo;
[self.mainTableView reloadData];
[productInfo release];
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self contentsList])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentString];
}
}
}
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self handleSearchForTerm:searchString];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
{
[self setSavedSearchTerm:nil];
self.searchDataSource = nil;
[self.mainTableView reloadData];
}
#end
I am quite new to objective-C and can't understand what I did wrong. I have spent days trying to figure this out and have had no luck. I would appreciate any help anyone can offer.
Keith
This bit of code seems to be the only place searchDataSource gets set:
NSArray *productInfo = [[ProductsDatabase database] searchListing:searchTerm];
self.searchDataSource = productInfo;
[self.mainTableView reloadData];
[productInfo release];
If ProductsDatabase follows the rules, you don't own the returned array (i.e. it is already autoreleased) so the release on the fourth line is incorrect.
Don't you mean to use your searchResults-array instead of your searchDataSource, because in handleSearchForTerm: you are adding the results to it. Why do you even have the searchResult ivar? It's only used in handleSearchForTerm:, maybe some mixup there?

Resources