MWPhotoBrowser add data from plist? - iphone

trying to get some data from a plist into the MWPhotoBrowser sample app.
Any ideas how to do it?
UIViewController *converterController = nil;
NSMutableArray *photos = [[NSMutableArray alloc] init];
converterController = [[MWPhotoBrowser alloc] initWithPhotos:photos];
converterController.hidesBottomBarWhenPushed = YES;
//here individual images can be added. However need to add images from a plist.
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image1" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image2" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image3" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image4" ofType:#"jpg"]]];
if (converterController) {
[self.navigationController pushViewController:converterController animated:YES];
[converterController release];
}
[photos release];
Can add objects individually as shown above, but not able to do it with a plist.
Can anyone share an idea?
thanks

w
ell i got this but it doesnt work.
SString *path = [[NSBundle mainBundle] pathForResource:
#"ImageData" ofType:#"plist"];
// Build the array from the plist
photos = [[NSMutableArray alloc] initWithContentsOfFile:path];
crashes the app.
I must use the MWPhoto property.
Help anyone?
Maybe Michael Waterfall wants to look into this?
EDIT:
OK here is the working code (well it works ok so far)
NSUInteger nimages = 0;
for (; ; nimages++) {
NSString *nameOfImage_ = #"imageSufix";
NSString *imageName = [NSString stringWithFormat:#"%#%d.jpg", nameOfImage_, (nimages + 1)];
//NSLog(#"Name is %#", imageName); log the names
image = [UIImage imageNamed:imageName];
if (image == nil) {
break;
}
[photos addObject:[MWPhoto photoWithImage:image]];

Related

NSMutableDictionary not working in voids and IBActions

I created an NSMutableDictionary called *temp in my .h file of the main viewController, and added this code to bring in the information from my .plist file.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
}
In the same view controller, I added a button action and added the following code:
-(IBAction)mathButton:(UIButton *)_sender
{
label1.text = [temp objectForKey:#"m1name"];
}
Where "label1 is a text field in the .xib, and m1name is one of the keys in the .plist
But when I run it, it doesn't work, and highlights label1.text = [temp objectForKey:#"m1name"]; and calls it bad access.
I've been stuck on this for a couple of days, and tried lots of things. An answer would be really helpful.
Thanks
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
You're not retaining the dictionary created via dictionaryWithContentsOfFile:path. You should either change that line to:
temp = [[NSMutableDictionary dictionaryWithContentsOfFile:path] retain];
(and make sure it's released in dealloc), or, if temp is a property, set it via
self.temp = [NSMutableDictionary dictionaryWithContentsOfFile:path];
In .h:
#interface ...
{
NSMutableDictionary* temp;
}
In .m:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle] pathForResource: #"Data"
ofType: #"plist"];
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath: path];
if (exists)
{
temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSLog(#"%#", [temp description]);
}
}
- (IBAction) mathButton: (UIButton *)_sender
{
label1.text = [temp objectForKey: #"m1name"];
}
If MRC:
- (void) dealloc
{
[temp release];
[super dealloc];
}

Memory leaks when deleting row from a tableview

I am loading data from a plist into a tableview in my application. Data is stored in a mutable dictionary of mutable dictionaries.
Here is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Categories";
// load data from plist fle
self.categories = [[[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]] autorelease];
// add buttons to navigation menu
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem = self.addButton;
}
My tableview is editable, so user can delete categories. In my commitEditingStyle:forRowAtIndexPath: method I update my data model:
[self.categories removeObjectForKey: [[self.categories allKeys] objectAtIndex:indexPath.row]];
When I profile my app it leaks memory. I am not very proficient in using the profile tool, but it seems to find leaks in my categories dictionary every time I delete a row.
I wonder where I missed releasing something? Is it a problem that object I am removing is a dictionary as well and I need to remove its objects too?
This leaks (if the property is retain or copy):
self.categories = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
Use this instead:
categories = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
or this:
self.categories = [[[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]] autorelease];
I wonder if this would give you anything different?
NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
self.categories = d;
[d release];

Creating NSMutableArray from xml file

I have an xml file with the following information.
<?xml version="1.0"?>
-<Party>
-<Player>
<Name>Butch</Name>
<Level>1</Level>
<Class>Fighter</Class>
</Player>
-<Player>
<Name>Shadow</Name>
<Level>2</Level>
<Class>Rogue</Class>
</Player>
-<Player>
<Name>Crak</Name>
<Level>3</Level>
<Class>Wizard</Class>
</Player>
</Party>
I try to add this to an NSMutableArray by doing the following.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Party" ofType:#"xml"];
NSData *xmlData = [[NSMutableArray alloc] initWithContentsOfFile:filePAth];
When I run this, my array object has no data in it.
If I replace the line with;
NSdata *xmlData = [NSdata dataWithContentsOfFole:filePath];
it will load my data but it is not in the format I require.
I'm very new to Objective-c and iPhone development and any help will be greatly appreciated.
If anymore info is needed I'll be happy to provide it.
edit - I'm using GDataXML to parse my xml
edit - My Parser class is as follows
#implementation PartyParser
+(NSString *)dataFilePath:(BOOL)forSave{
return [[NSBundle mainBundle] pathForResource:#"Party" ofType:#"xml"];
}
+(Party *)loadParty{
NSString *filePath = [self dataFilePath:FALSE];
//NSData *xmlData = [NSData dataWithContentsOfFile:filePath];
NSData *xmlData = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if(doc ==nil){return nil;}
NSLog(#"%#", doc.rootElement);
Party *party = [[[Party alloc] init] autorelease];
NSArray *partyMembers = [doc.rootElement elementsForName:#"Player"];
for (GDataXMLElement *partyMember in partyMembers)
{
NSString *name;
int level;
RPGClass rpgClass;
//Name
NSArray *names = [partyMember elementsForName:#"name"];
if(names.count > 0)
{
GDataXMLElement *firstName = (GDataXMLElement *) [names objectAtIndex:0];
name = firstName.stringValue;
}else continue;
//Level
NSArray *levels = [partyMember elementsForName:#"level"];
if(levels.count > 0)
{
GDataXMLElement *firstLevel = (GDataXMLElement *) [levels objectAtIndex:0];
level = firstLevel.stringValue.intValue;
}else continue;
//Class
NSArray *classes = [partyMember elementsForName:#"class"];
if(classes.count > 0)
{
GDataXMLElement *firstClass = (GDataXMLElement *) [classes objectAtIndex:0];
if([firstClass.stringValue caseInsensitiveCompare:#"fighter"] == NSOrderedSame)
{
rpgClass = RPGClassFighter;
}
else if([firstClass.stringValue caseInsensitiveCompare:#"rogue"] == NSOrderedSame)
{
rpgClass = RPGClassRogue;
}
else if([firstClass.stringValue caseInsensitiveCompare:#"wizard"] == NSOrderedSame)
{
rpgClass = RPGClassWizard;
}
else
{
continue;
}
}else continue;
Player *player = [[[Player alloc] initWithName:name level:level rpgClass:rpgClass] autorelease];
[party.players addObject:player];
}
//NSLog(#"%#", doc.rootElement);
//
[doc release];
[xmlData release];
return party;
}
#end
The XML file can not be any type of XML. It needs to be in the "property list" format.
Take a look at some Apple docs or some of the .plist files that will be in your project. That will show you how to create such a file.
Alternatively, create one using the "PList Editor" application that comes with the developer tools. It has a good UI for creating these files.
Lastly, your line "NSData* xmlData = ..." is very wrong - you're assigning a mutable array object to an NSData* variable. The types are not interchangeable by a long shot.
If you want to do full-blown XML parsing, there are various options that deserve a topic of their own. The XML used for plists is limited to Cocoa collections and simple data types.
Take a look to this XML Parser. It is called "TBXML", I have used that for a while and I'm quite happy with the result.
http://www.tbxml.co.uk/TBXML/TBXML_Free.html
Just place your XML file (e.g. "myFileName.xml") anywhere in your project.
Read the xml file contents to NSData using:
NSString *myBundleString = [[NSBundle mainBundle] pathForResource:#"myFileName" ofType:#"xml"];
NSData *myData = [NSData dataWithContentsOfFile:myBundleString];
And parse your data using NSXMLParser:
NSXMLParser *myParser = [[NSXMLParser alloc] initWithData:myData];
[myParser setDelegate:self];
[myParser parse];
Happy parsing using the delegate methods!

how to load image in background in UITableCell in iphone application

I have develop an RSS application. in My table cell I am displaying images which i retrive from imge link in RSS feed and Title.
Images are loaded successfully but the problem is that it hang my application.
as there any way to load image in background.
my current code is.
int blogEntryIndex1 = [indexPath indexAtPosition: [indexPath length] -1];
imgstring=[[blogEntries objectAtIndex: blogEntryIndex1] objectForKey: #"image"];
NSURL *url = [NSURL URLWithString:imgstring];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
cell.imageView.image=[img autorelease];
any idea please, Thanks in advance...
Repost... You should also look at lazy table loading via Apple's sample code http://developer.apple.com/iphone/library/samplecode/LazyTableImages/Introduction/Intro.html
Update another example here: http://www.markj.net/iphone-asynchronous-table-image/
Well guys i have done it the code is...
- (void) loadImage:(id)object {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Get the data to pass in
NSDictionary *dict = (NSDictionary *)object;
// Get the cell and the image string
NSString *imgstring = [dict objectForKey:#"imgstring"];
MyfirstCell *cell = [dict objectForKey:#"cell"];
NSURL *url = [NSURL URLWithString:imgstring];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
cell.myimnage.image = img;
[pool release];
}
I will call the above method in my code...
if(searching) {
//cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
int blogEntryIndex = [indexPath indexAtPosition: [indexPath length] -1];
// Tell your code to load the image for a cell in the background
NSString *imgstring =[[blogEntries objectAtIndex: blogEntryIndex] objectForKey: #"image"];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:cell, #"cell", imgstring, #"imgstring", nil];
[self performSelectorInBackground:#selector(loadImage:) withObject:dict];
//background code end here..
Thanks to deanWombourne who has given me this code....
And take a look to this document also from Apple.
http://developer.apple.com/iphone/library/documentation/cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html
Most the time I use NSURLConnection to download things.
You can use this way:
((UIImageView *)cell.backgroundView).image = bgImage;
((UIImageView *)cell.selectedBackgroundView).image = bgImage;

Find out when all processes in (void) is done?

I need to know how you can find out when all processes (loaded) from a - (void) are done, if it's possible.
Why? I'm loading in data for a UITableView, and I need to know when a Loading... view can be replaced with the UITableView, and when I can start creating the cells.
This is my code:
- (void) reloadData {
NSAutoreleasePool *releasePool = [[NSAutoreleasePool alloc] init];
NSLog(#"Reloading data.");
NSURL *urlPosts = [NSURL URLWithString:[NSString stringWithFormat:#"%#", URL]];
NSError *lookupError = nil;
NSString *data = [[NSString alloc] initWithContentsOfURL:urlPosts encoding:NSUTF8StringEncoding error:&lookupError];
postsData = [data componentsSeparatedByString:#"~"];
[data release], data = nil;
urlPosts = nil;
self.numberOfPosts = [[postsData objectAtIndex:0] intValue];
self.postsArrayID = [[postsData objectAtIndex:1] componentsSeparatedByString:#"#"];
self.postsArrayDate = [[postsData objectAtIndex:2] componentsSeparatedByString:#"#"];
self.postsArrayTitle = [[postsData objectAtIndex:3] componentsSeparatedByString:#"#"];
self.postsArrayComments = [[postsData objectAtIndex:4] componentsSeparatedByString:#"#"];
self.postsArrayImgSrc = [[postsData objectAtIndex:5] componentsSeparatedByString:#"#"];
NSMutableArray *writeToPlist = [NSMutableArray array];
NSMutableArray *writeToNoImagePlist = [NSMutableArray array];
NSMutableArray *imagesStored = [NSMutableArray arrayWithContentsOfFile:[rootPath stringByAppendingPathComponent:#"imagesStored.plist"]];
int loop = 0;
for (NSString *postID in postsArrayID) {
if ([imagesStored containsObject:[NSString stringWithFormat:#"%#.png", postID]]){
NSLog(#"Allready stored, jump to next. ID: %#", postID);
continue;
}
NSLog(#"%#.png", postID);
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[postsArrayImgSrc objectAtIndex:loop]]];
// If image contains anything, set cellImage to image. If image is empty, try one more time or use noImage.png, set in IB
if (imageData == nil){
NSLog(#"imageData is empty before trying .jpeg");
// If image == nil, try to replace .jpg with .jpeg, and if that worked, set cellImage to that image. If that is also nil, use noImage.png, set in IB.
imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[postsArrayImgSrc objectAtIndex:loop] stringByReplacingOccurrencesOfString:#".jpg" withString:#".jpeg"]]];
}
if (imageData != nil){
NSLog(#"imageData is NOT empty when creating file");
[fileManager createFileAtPath:[rootPath stringByAppendingPathComponent:[NSString stringWithFormat:#"images/%#.png", postID]] contents:imageData attributes:nil];
[writeToPlist addObject:[NSString stringWithFormat:#"%#.png", postID]];
} else {
[writeToNoImagePlist addObject:[NSString stringWithFormat:#"%#", postID]];
}
imageData = nil;
loop++;
NSLog(#"imagePlist: %#\nnoImagePlist: %#", writeToPlist, writeToNoImagePlist);
}
NSMutableArray *writeToAllPlist = [NSMutableArray arrayWithArray:writeToPlist];
[writeToPlist addObjectsFromArray:[NSArray arrayWithContentsOfFile:nowPlist]];
[writeToAllPlist addObjectsFromArray:[NSArray arrayWithContentsOfFile:[rootPath stringByAppendingPathComponent:#"imagesStored.plist"]]];
[writeToNoImagePlist addObjectsFromArray:[NSArray arrayWithContentsOfFile:[rootPath stringByAppendingPathComponent:#"noImage.plist"]]];
[writeToPlist writeToFile:nowPlist atomically:YES];
[writeToAllPlist writeToFile:[rootPath stringByAppendingPathComponent:#"imagesStored.plist"] atomically:YES];
[writeToNoImagePlist writeToFile:[rootPath stringByAppendingPathComponent:#"noImage.plist"] atomically:YES];
[releasePool release];
}
It is as simple as returning a bool at the bottom of the selector being run in the background, and reaload the UITableView.
Thanks to #iWasRobbed:
I have never done this, but just speculating: have you tried returning a BOOL at the very end so that the reloadData function will return TRUE when it gets to that point? I am assuming (possibly incorrectly) that the device serially handles tasks one-at-a-time, so give it a shot.