Wrox Programmer Forums
|
BOOK: Beginning iOS 4 Application Development
This is the forum to discuss the Wrox book Beginning iOS 4 Application Development by Wei-Meng Lee; ISBN: 978-0-470-91802-9
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Beginning iOS 4 Application Development section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old April 25th, 2011, 07:35 AM
Registered User
 
Join Date: Apr 2011
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default chapter 10

I'm trying to follow this book and so far its a nightmare.... couldn't get chapter 8 to work either......

anyway I've done the first part, stopped at 'copying bundled resources" as the app crashes on this line:
Code:
[mutableTitles addObject:@"New App title"];
I'm not getting any errors or warnings for the code in xcode

this is the error that comes up making the app crash:
Quote:
2011-04-25 12:33:42.707 FilesHandling[494:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary addObject:]: unrecognized selector sent to instance 0x4e00790'
any ideas what's wrong?

here's the whole file:
Code:
//
//  FilesHandlingViewController.m
//  FilesHandling
//
//  Created by Martin Chrobot on 25/04/2011.
//  Copyright 2011 home. All rights reserved.
//

#import "FilesHandlingViewController.h"

@implementation FilesHandlingViewController

//finds the path to the application's documents directory
-(NSString *)documentsPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    return documentsDir;
}

//write content into a specified file path
-(void)writeToFile:(NSString *)text withFileName:(NSString *)filePath {
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:text];
    [array writeToFile:filePath atomically:YES];
    [array release];
}

//read content from a specified file path
-(NSString *)readFromFile:(NSString *)filePath {
    //check if file exists
    if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
        NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
        NSString *data = [NSString stringWithFormat:@"%@", [array objectAtIndex:0]];
        
        [array release];
        return data;
    } else {
        return nil;
    }
}

- (void)dealloc
{
    [super dealloc];
}

- (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.
}

#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    //formulate filename
    NSString *fileName = [[self documentsPath] stringByAppendingPathComponent:@"data.txt"];
    
    //write something to the file
    [self writeToFile:@"a string of text" withFileName:fileName];
    
    //read it back
    NSString *fileContent = [self readFromFile:fileName];
    
    //display the content read in the debugger console window
    NSLog(@"%@", fileContent);
    
    //get the path to the property list file
    NSString *plistFileName = [[self documentsPath] stringByAppendingPathComponent:@"Apps.plist"];
    
    //if the property list can be found
    if([[NSFileManager defaultManager]fileExistsAtPath:plistFileName]){
        //load the content of the property list file into a NSDictionary object
        NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileName];
        
        //for each category
        for(NSString *category in dict){
            NSLog(@"%@", category);
            NSLog(@"========");
            
            //return all titles in an array
            NSArray *titles = [dict valueForKey:category];
            
            //print out all the titles in that category
            for(NSString *title in titles){
                NSLog(@"%@", title);
            }
        }
        [dict release];
    } else {
        //load the property list from the resource folder
        NSString *pListPath = [[NSBundle mainBundle] pathForResource:@"Apps" ofType:@"plist"];
        NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
        
        //make mutable copy of the dictionary object
        NSMutableDictionary *copyOfDict = [dict mutableCopy];
        
        //get all the different categories
        NSArray *categoriesArray = [[copyOfDict allKeys] sortedArrayUsingSelector:@selector(compare:)];
        
        //for each category
        for(NSString *category in categoriesArray){
            //get all the app titles in that category
            NSArray *titles = [dict valueForKey:category];
            
            //make a mutable copy of the array
            NSMutableArray *mutableTitles = [titles mutableCopy];
            
            //add new title to the category
            [mutableTitles addObject:@"New App title"];
            
            //set the array back to the dictionary object
            [copyOfDict setObject:mutableTitles forKey:category];
            [mutableTitles release];
        }
        
        //write the dictionary to file
        fileName = [[self documentsPath]stringByAppendingPathComponent:@"Apps.plist"];
        [copyOfDict writeToFile:fileName atomically:YES];
        [dict release];
        [copyOfDict release];
    }
    
    [super viewDidLoad];
}


- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end
 
Old May 1st, 2011, 10:47 AM
Friend of Wrox
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

The issue here is not the code you wrote, but the structure of the .plist file you have created. In Xcode 3, which the book was written using, when creating the .plist you are given a template that shows the root dictionary. You add keys to this dictionary - in this case arrays of strings. In Xcode 4, which it appears you used, the template does not show the root dictionary, so in order to match the book's screenshot the first inclination is to add a root dictionary. This is incorrect. The root dictionary, though not visible in the template, is actually there. So what you end up with is a .plist with a dictionary whose only object is a dictionary with a key of "Root". This dictionary contains the arrays (Games, Entertainment, Utilities) of the strings.
plist
|
Root
|
Root
/ — | — \
array____array____ array
(Games) (Entertainment) (Utilities)


Adding the lines in bold to the -viewDidLoad method allows you to see what is going on.

Code:
} else {
        //load the property list from the resource folder
        NSString *pListPath = [[NSBundle mainBundle] pathForResource:@"Apps" ofType:@"plist"];
        NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
		
        
        //make mutable copy of the dictionary object
        NSMutableDictionary *copyOfDict = [dict mutableCopy];
        
        //get all the different categories
        NSArray *categoriesArray = [[copyOfDict allKeys] sortedArrayUsingSelector:@selector(compare:)];
		NSLog(@"The keys are %@",categoriesArray); // the list of keys in the root dictionary. With the current plist the only key is "Root", not the 3 array keys that were expected
        
        //for each category
        for(NSString *category in categoriesArray){
			NSLog(@"The category is %@",category); // The key to be checked - again with the plist list error the only key is "Root"
            //get all the app titles in that category
            NSArray *titles = [dict valueForKey:category]; 
			NSLog(@"titles is %@",titles); // the object at the key lists its contents 
NSLog(@"titles is a %@", [titles class]); // You see that titles is not an array but __NSCFDictionary
            
            //make a mutable copy of the array
            NSMutableArray *mutableTitles = [titles mutableCopy];
            
            //add new title to the category
            [mutableTitles addObject:@"New App title"];
            
            //set the array back to the dictionary object
            [copyOfDict setObject:mutableTitles forKey:category];
            [mutableTitles release];
        }
What you end up with is the dictionary that is the only key of the actual root dictionary being assigned to the the variable titles. So titles is not an array but a dictionary. You make the mutable copy of this and attempt to add an object. The dictionary class does not have an addObject: method so the crash occurs.

You need to remove one dictionary layer in the plist. To make this simple and not have to retype everything, select the plist in Xcode. Select Root and open the disclosure triangle to view the keys. Select one of the keys and copy or cut it. Close the Root disclosure triangle and click in the white space below it. Paste the copied/cut key there. Repeat this for the remaining keys and then delete Root.

Hopefully this is clear. If not, I will send back your project with the amended .plist file. The issue for your question concerning Chapter 8 has the same resolution, a plist problem.

Bob





Similar Threads
Thread Thread Starter Forum Replies Last Post
Chapter 10, listing 10-10-app kiwibrit BOOK: Professional ASP.NET 3.5 : in C# and VB ISBN: 978-0-470-18757-9 2 August 18th, 2009 04:21 AM
Chapter 10 JimSchubert BOOK: Ruby on Rails for Microsoft Developers 1 May 17th, 2009 11:35 PM
Chapter 10 gogeo BOOK: Beginning Access 2003 VBA 1 January 22nd, 2006 09:41 AM
Chapter 10 czambran BOOK: Beginning CSS: Cascading Style Sheets for Web Design ISBN: 978-0-7645-7642-3 2 March 29th, 2005 09:35 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.