ftwhere
ftwhere

Reputation: 103

Add to favorites function?

I have this problem understanding how to save data in order to have an "add to favorites" function to my app. The app has an UITableView and the data is stored in a Plist. From there it goes into a DetailView containing an UIImageView and an UITextView. I want to be able to bookmark the items i like and display them in a separate view.

Here is a piece of the code to make it easier to see:

//BooksLibraryDao.h

#import <Foundation/Foundation.h>


@interface BooksLibraryDao : NSObject {
    NSString *libraryPlist;
    NSArray *libraryContent;
}

@property (nonatomic, readonly) NSString *libraryPlist;
@property (nonatomic, readonly) NSArray *libraryContent;

- (id)initWithLibraryName:(NSString *)libraryName;
- (NSDictionary *)libraryItemAtIndex:(int)index;
- (int)libraryCount;

@end


//BooksLibraryDao.m

#import "BooksLibraryDao.h"


@implementation BooksLibraryDao

@synthesize libraryContent, libraryPlist;

 - (id)initWithLibraryName:(NSString *)libraryName {
    if (self = [super init]) {
        libraryPlist = libraryName;
        libraryContent = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] 
                                                                  pathForResource:libraryPlist ofType:@"plist"]];
    }
    return self;
}

- (NSDictionary *)libraryItemAtIndex:(int)index {
    return (libraryContent != nil && [libraryContent count] > 0 && index < [libraryContent count]) 
        ? [libraryContent objectAtIndex:index]
        : nil;
}

- (int)libraryCount {
    return (libraryContent != nil) ? [libraryContent count] : 0;
}

- (void) dealloc {
    if (libraryContent) [libraryContent release];
    [super dealloc];
}


@end


//BooksTableViewController.h

#import <UIKit/UIKit.h>
#import "BooksLibraryDao.h"
#import "BooksListingViewCell.h"
#import "BooksAppDelegate.h"


@interface BooksTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
    IBOutlet UITableView *booksTableView;
    BooksLibraryDao *dao;

    IBOutlet BooksListingViewCell *_cell;
}


@end



//BooksTableViewController.m

#import "BooksTableViewController.h"
#import "DetailViewController.h"
#import "BooksListingViewCell.h"
#import "BooksNavController.h"

@implementation BooksTableViewController
#define CELL_HEIGHT 70.0

#pragma mark -
#pragma mark Initialization

/*
- (id)initWithStyle:(UITableViewStyle)style {
    // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization.
    }
    return self;
}
*/


#pragma mark -
#pragma mark View lifecycle


- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.backgroundColor = [UIColor clearColor];
}


- (void)viewWillAppear:(BOOL)animated {
    dao = [[BooksLibraryDao alloc] initWithLibraryName:@"TestData"];
    self.title = @"Books";
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated: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 [dao libraryCount];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"LibraryListingCell";

    BooksListingViewCell *cell = (BooksListingViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"BooksListingView" owner:self options:nil];
        cell = [_cell autorelease];
        _cell = nil;
    }

    cell.titleLabel.text = [[dao libraryItemAtIndex:indexPath.row] valueForKey:@"title"];     
    cell.smallImageView.image = [UIImage imageNamed:[[dao libraryItemAtIndex:indexPath.row] valueForKey:@"smallImage"]];    
    cell.backgroundColor = [UIColor colorWithRed:9 green:9 blue:9 alpha:.7];
    cell.textLabel.backgroundColor = [UIColor clearColor];
    cell.textLabel.textColor = [UIColor colorWithRed:.1 green:.1 blue:.1 alpha:1];
    cell.selectedBackgroundView = [[[UIImageView alloc] init] autorelease];
    UIImage *selectionBackground;
    selectionBackground = [UIImage imageNamed:@"cell.png"];
    ((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
    return cell;

}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    DetailViewController *controller = [[DetailViewController alloc] 
                                        initWithBookData:[dao libraryItemAtIndex:indexPath.row]
                                        nibName:@"DetailViewController" bundle:[NSBundle mainBundle]];
    controller.title = [[dao libraryItemAtIndex:indexPath.row] valueForKey:@"title"];
    [self.navigationController pushViewController:controller animated:YES];
    [controller release];  

}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return CELL_HEIGHT;
}


#pragma mark -
#pragma mark Table view delegate


#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 {
    [super dealloc];
}


@end


//DetailViewController.h


#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#import <QuartzCore/QuartzCore.h>


@interface DetailViewController : UIViewController <MFMailComposeViewControllerDelegate>{
    IBOutlet UIImageView *bookImageView;
    IBOutlet UILabel *titleLabel;

    IBOutlet UITextView *authorTextView;
    IBOutlet UITextView *descriptionTextView;
    IBOutlet UILabel *message;

    NSDictionary *bookData;
}

@property (nonatomic, retain) UIImageView *bookImageView;
@property (nonatomic, retain) UILabel *titleLabel;

@property (nonatomic, retain) UITextView *descriptionTextView;
@property (nonatomic, retain) UITextView *authorTextView;
@property (nonatomic, retain) IBOutlet UILabel *message;


-(IBAction)showPicker:(id)sender;
-(void)displayComposerSheet;
-(void)launchMailAppOnDevice;
-(IBAction)showAuthor;
-(IBAction)showDesc;
-(IBAction)showImage;

- (id)initWithBookData:(NSDictionary *)data nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;

@end



//DetailViewController.m

#import "DetailViewController.h"



@implementation DetailViewController

@synthesize bookImageView, titleLabel, descriptionTextView, authorTextView;
@synthesize message;

- (id)initWithBookData:(NSDictionary *)data nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        bookData = data;
    }
    return self;
}

- (void)viewDidLoad {
    bookImageView.image = [UIImage imageNamed:[bookData valueForKey:@"bookImage"]];
    titleLabel.text = [bookData valueForKey:@"title"];
    descriptionTextView.text = [bookData valueForKey:@"description"];
    authorTextView.text = [bookData valueForKey:@"author"];
    [super viewDidLoad];
}

Upvotes: 0

Views: 528

Answers (1)

Simon
Simon

Reputation: 9021

You've got one of a few options for implementing favourites (really depends mostly on whether your data is persistent).

  • (A) You can add a marker for each item you display in your table, which marks it as a favourite - then just refer to the same data set but filter it for said marker. Or...

  • (B) You can create an additional list holding a copy of each item you want to mark as a favourite and then refer to that new list as your datasource.

If your data isn't persistent, you could still use method A and when data is refreshed only retain the marked records before you insert the new, fresh data.

Hope that makes sense!

Upvotes: 1

Related Questions