I have written a class to help save and load data for the sake of persistence for my iPhone application but I have a problem with some NSUIntegers that I'm passing across.
Basically, I have the code to use pointers, but eventually it has to start out being an actual value right? So I get this error
warning: passing argument 1 of 'getSaveWithCampaign:andLevel:' makes pointer from integer without a cast
My code is laid out like so.
(Persistence is the name of the class)
NSDictionary *saveData = [Persistence getSaveWithCampaign:currentCampaign andLevel:[indexPath row]];
Here's Persistence.m
#import "Persistence.h"
#implementation Persistence
+ (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kSaveFilename];
}
+ (NSDictionary *)getSaveWithCampaign:(NSUInteger *)campaign andLevel:(NSUInteger *)level
{
NSString *filePath = [self dataFilePath];
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSDictionary *saveData = [[NSDictionary alloc] initWithContentsOfFile:filePath];
NSString *campaignAndLevelKey = [self makeCampaign:campaign andLevelKey:level];
NSDictionary *campaignAndLevelData = [saveData objectForKey:campaignAndLevelKey];
[saveData release];
return campaignAndLevelData;
}
else
{
return nil;
}
}
+ (NSString *)makeCampaign:(NSUInteger *)campaign andLevelKey:(NSUInteger *)level
{
return [[NSString stringWithFormat:#"%d - ", campaign+1] stringByAppendingString:[NSString stringWithFormat:#"%d", level+1]];
}
#end
You should get rid of the * in ( NSUInteger *) in the getSaveWithCampaign method.
If you read the error message closely, it states that you are making a pointer (*) from an integer without a cast.
Your getSaveWithCampaign method should now have the following signature:
+ (NSDictionary *)getSaveWithCampaign:(NSUInteger)campaign andLevel:(NSUInteger)level
If, on the other hand, for some reason you do want to use pointers, you can pass in the NSUInteger prefixed with an ampersand (&) to pass in the address of the NSUInteger in memory.
Related
I want to add names in a data array only if the name does not previously exist in the data array. When I attempt to print these names, I do get repetitions. Is there a way to solve this?
-(NSMutableArray *)autoComplete
{
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
NSString *url = [NSString stringWithFormat:#"%#45.25,-95.25&limit=100&client_id=Von0J4Bu6INiez5bGby2R&client_secret=50sUjSbg7dba8cQgtpdfr5Ns7wyYTqtmKpUU3khQ",kWSURL];
NSDictionary * returnDict = (NSDictionary *) [self callWebService:url];
if([returnDict objectForKey:#"success"])
{
NSArray *responceArray = [returnDict objectForKey:#"response"];
for (NSDictionary *dict in responceArray) {
placeDC *place = [[placeDC alloc]init];
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * name =[placeDict objectForKey:#"name"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
return dataArray;
}
First Check that is there any response from the Server side or not, to check response use NSLog() or Break Points.
if response is ok then put a the following check your code
if (![dataArray containsObject:#"Some Name"])
{
// add Object
}
You could add the name NSString to an NSSet and check in every cycle whether it contains it or not.
Inside your if you could write something like:
NSArray *responceArray = [returnDict objectForKey:#"response"];
NSSet *names = [[NSSet alloc] init];
for (NSDictionary *dict in responceArray) {
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSString * name =[placeDict objectForKey:#"name"];
if (![names containsObject:name]) {
[names addObject:name];
placeDC *place = [[placeDC alloc]init];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
Hope this helps!
Do one thing, add your dict in another array and search in this array that data already exist or not,
[tempAry addObject: dict];
and before insertion
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", name];
NSArray *filteredArray = [tempAry filteredArrayUsingPredicate:predicate];
if ([filteredArray count] == 0)
{
[dataArray addObject:place];
}
else{
//Already exist
}
Why don't you create a separate dictionary, as an ivar or property of you class, for storing our required value, say it as :
NSMutableDictionary *uniqueValueDict=[NSMutableDictionary new];
And keep storing your required value and key as:
[uniqueValueDict setObject:stateFull forKey:uniqueValueDict];
Your work will be done.
This is the easiest solution that i have applied and this should get you going in picking up unique elements out of array.
NSArray * claimedOfferArray = [[NSArray alloc]initWithObjects:#"A",#"B",#"A",#"C",#"B" nil];
NSArray * distinctArray = [[NSArray alloc]init];
distinctArray =[[NSSet setWithArray:claimedOfferArray] allObjects];
This code will also work with NSMutableArray
Let me know if it works for you..:).
I am trying to save an array, which has some dictionaries inside, to a plist file but it fails. I don't get any errors. I do exactly the same few lines above in the code just with another array and that works.. I can't figure out why it does not save the file.
This is where I save the file: (see some debugger output below)
// When built parse through dictionary and save to file
for ( NSString *keys in [dicByCountry allKeys] )
{
NSArray *arrr = [[NSArray alloc] initWithArray:[dicByCountry objectForKey:keys]];
NSString *fname = [self filePath:[NSString stringWithFormat:#"regions.cid%#.plist",keys]];
if (![arrr writeToFile:fname atomically:YES])
NSLog(#"Could not write file regions.cid%#.plist",keys);
}
Here some GDB Output
(gdb) po fname
/Users/chris/Library/Application Support/iPhone Simulator/4.0/Applications/44A9FF9E-5715-4BF0-9BE2-525883281420/Documents/regions.cid0.plist
(gdb) po arrr
<__NSArrayI 0x8022b30>(
{
countryID = "<null>";
region = "?\U00e2vora";
regionID = 16;
},
{
countryID = "<null>";
region = Vicenza;
regionID = 14;
},
{
countryID = "<null>";
region = Wales;
regionID = 23;
}
)
If you read the documentation closely, writeToFile:atomically: expects the array to contain only objects which can be written into a plist file.
Only objects of type:
NSString
NSData
NSDate
NSNumber
NSArray
NSDictionary
are permitted. If you have arrays or dictionaries within the array you're saving, their values will be examined by the same criteria.
This is somewhat more restrictive than what's usually allowed in NSArrays. In particular, the value [NSNull null] is not acceptable.
I convert NSArray or NSDictionary to NSData before serializing. Following is a category on nsarray for serializing and deserializing. This comfortableby handles some data being nsnull
#implementation NSArray(Plist)
-(BOOL)writeToPlistFile:(NSString*)filename{
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES];
return didWriteSuccessfull;
}
+(NSArray*)readFromPlistFile:(NSString*)filename{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
NSData * data = [NSData dataWithContentsOfFile:path];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
#end //needs to be set for implementation
NSMutableArray count is returning zero after adding objects to it, its been an hour of hacking away trying to figure out why, and I'm still stuck, so that brings me here.
Any ideas based off the following code, what the problem is?
the object 'search' is a custom class defined in the header set as a pointer, with retain, nonatomic attributes.
- (NSMutableArray *) populateArrayFromPlist{
NSLog(#"Populate Array from PList");
NSDictionary *dictionary;
// read "foo.plist" from application bundle
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"asearch.plist"];
dictionary = [NSDictionary dictionaryWithContentsOfFile:finalPath];
for (id key in dictionary)
{
search = [[ASearch alloc] init];
[dictionary valueForKey:key];
[search setID:[[dictionary valueForKey:key] intValue] ];
//[[search searchString] initWithString: key];
search.searchString = [[NSMutableString alloc] initWithString: key];
if (search == nil) {
printf("Let me know now\n\n\n\n");
}
NSLog(#"%#", [search searchString]);
NSLog(#"Setting string Value: %s\n", [key cString]);
NSLog(#"Setting ID Value: %i\n", [[dictionary valueForKey:key] intValue]);
//NSLog(#"aSearchArray count == %i", [[aSearchArray count] intValue]);
[aSearchArray addObject:search];
NSLog(#"aSearchArray count == %i", [aSearchArray count] );
aSearchArray is a nil object that is the only reason why you are getting count as zero.
For more confirmation just create a new local array and try to add your object to it.
You will get a proper count
I have an string which is got from parsing an xml site.
http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500
I want to have an NSString function that will be able to parse the value of c.
Is there a default function or do i have to write it manually.
You could use Regular expression via RegExKit Lite:
http://regexkit.sourceforge.net/RegexKitLite/
Or you could separate the string into components (which is less nice):
NSString *url=#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray *comp1 = [url componentsSeparatedByString:#"?"];
NSString *query = [comp1 lastObject];
NSArray *queryElements = [query componentsSeparatedByString:#"&"];
for (NSString *element in queryElements) {
NSArray *keyVal = [element componentsSeparatedByString:#"="];
if (keyVal.count > 0) {
NSString *variableKey = [keyVal objectAtIndex:0];
NSString *value = (keyVal.count == 2) ? [keyVal lastObject] : nil;
}
}
I made a class that does this parsing for you using an NSScanner, as an answer to the same question a few days ago. You might find it useful.
You can easily use it like:
URLParser *parser = [[[URLParser alloc] initWithURLString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"] autorelease];
NSString *c = [parser valueForVariable:#"c"]; //c=500
Try the following:
NSURL *url = [NSURL URLWithString:#"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500"];
NSMutableString *parameterString = [NSMutableString stringWithFormat:#"{%#;}",[url parameterString]];
[parameterString replaceOccurrencesOfString:#"&" withString:#";"];
// Convert string into Dictionary
NSPropertyListFormat format;
NSString *error;
NSDictionary *paramDict = [NSPropertyListSerialization propertyListFromData:[parameterString dataUsingEncoding:NSUTF8StringEncoding] mutabilityOption: NSPropertyListImmutable format:&format errorDescription:&error];
// Now take the parameter you want
NSString *value = [paramDict valueForKey:#"c"];
Here is the native iOS approach using NSURLComponents and NSURLQueryItem classes:
NSString *theURLString = #"http://www.arijasoft.com/givemesomthing.php?a=3434&b=435edsf&c=500";
NSArray<NSURLQueryItem *> *theQueryItemsArray = [NSURLComponents componentsWithString:theURLString].queryItems;
for (NSURLQueryItem *theQueryItem in theQueryItemsArray)
{
NSLog(#"%# %#", theQueryItem.name, theQueryItem.value);
}
I'm saving some data using a series of NSDictionaries, stored in an NSMutableArray and archived using NSKeyedArchiver.
I'm basically trying to save the states of several instances the class 'Brick', so I've implemented a getBlueprint method like this (slimmed down version)
-(id)getBlueprint
{
// NOTE: brickColor is a string
NSDictionary *blueprint = [NSDictionary dictionaryWithObjectsAndKeys:
brickColor, #"color",
[NSNumber numberWithInt:rotation], #"rotation",
nil];
return blueprint;
}
And so I have another method that creates a new Brick instance when provided with a blueprint.
-(id)initWithBlueprint:(NSDictionary *)blueprint spriteSheet:(NSString *)ssheet
{
if((self == [super init])){
brickColor = [blueprint objectForKey:#"color"];
[self setColorOffset:brickColor];
while(rotation != [[blueprint objectForKey:#"rotation"] intValue]){
[self setRotation:90];
}
}
return self;
}
Which works when I pass it a 'fresh' blueprint, but not when I read a blueprint from a saved file... sort of. For example, the rotation will work, but changing the color wont. So while I can read the value of brickColor using
NSLog(#"brick color %#", [blueprint objectForKey:#"color"]);
if I try something like
if(brickColor == #"purple"){
colorOffset = CGPointMake(72,36);
NSLog(#"Changed offset for -- %# -- to %#", color, NSStringFromCGPoint(colorOffset));
}
And I know that color is purple, the condition doesn't return true. I thought it might be that somehow NSKeyedUnarchiver changed a string into something else, but the following test returns true.
if([color isKindOfClass:[NSString class]]){
NSLog(#"%# IS A STRING", color);
}else{
NSLog(#"!!!!! COLOR IS A NOT STRING !!!!!");
}
As I said, this isn't a problem if I try to use a freshly created NSDictionary as a blueprint, only when a blueprint is archived and then read back in.
So, as usual, I'm wondering if anyone has any ideas why this might be happening.
incase it's relevant, here's how the data is being stored and recieved.
// Saving
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-(void)buildLevelData{
levelData = [[NSMutableArray alloc] initWithCapacity:100];
for(brickSprite *brick in spriteHolder.children){
[levelData addObject:[brick getBlueprint]];
}
}
-(void)saveLevel
{
[self buildLevelData];
NSData *rawDat = [NSKeyedArchiver archivedDataWithRootObject:levelData];
if([self writeApplicationData:rawDat toFile:saveFileName]){
NSLog(#"Data Saved");
}else{
NSLog(#"ERROR SAVING LEVEL DATA!");
}
[[Director sharedDirector] replaceScene:[MainMenu scene]];
}
- (BOOL)writeApplicationData:(NSData *)data toFile:(NSString *)fileName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
if (!documentsDirectory) {
NSLog(#"Documents directory not found!");
return NO;
}
NSString *appFile = [saveDir stringByAppendingPathComponent:fileName];
return ([data writeToFile:appFile atomically:YES]);
}
// Loading
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- (void) loadRandomMapFrom:(NSString *)dir
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [paths objectAtIndex:0];
if(!docsDir){
NSLog(#"Cound Not Find Documents Directory When trying To Load Random Map");
return;
}
dir = [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"/%#", dir]];
// we'll also set the file name here.
NSArray *existingFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dir error:nil];
// get last file for this test
NSString *filePath = [dir stringByAppendingPathComponent:[existingFiles objectAtIndex:([existingFiles count] - 1)]];
NSMutableArray *levelData = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
[self buildMapWithData:levelData];
}
-(void)buildMapWithData:(NSMutableArray *)lData
{
for(NSDictionary *blueprint in lData){
brickSprite *brick = [[brickSprite alloc] initWithBlueprint:blueprint spriteSheet:#"blocks.png"];
[spriteHolder addChild:brick];
}
}
Sorry about the mess of a question. There's a lot going on that I'm struggling to fully understand myself so it's hard to break it down to the bare minimum.
You should always compare strings with [firstString isEqualToString:secondString], because firstString == secondString only checks for pointer equality, e.g. if both strings are stored at the same location (which they'll never be when comparing dynamically created objects and string constants).