I want to store the same number in an array 100 times. These numbers will change later on, but I want to write an if statement using a counter to populate all 100 slots initially with the value of 0. Is there an easy way to do this?
Something like this, where 'block01' needs to change to 'block02', 'block03' etc.:
int block01 = 0;
NSMutableDictionary* myDict = [[NSMutableDictionary alloc] init];
if(myDict)
{
[myDict setObject:block01 forKey:#"block01stored"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSString *path = [documentPath stringByAppendingPathComponent:#"blocks.save"];
BOOL successfulWrite = [myDict writeToFile: path atomically: YES];
if(successfulWrite == NO)
}
This should help you. It's a loop that will execute 99 times (1 - 100) adding zero as the object for a key formatted to include the current number.
NSMutableDictionary* myDict = [[NSMutableDictionary alloc] init];
for (int i = 1; i <= 100; i ++) {
if(myDict)
{
[myDict setObject:[NSNumber numberWithInt:0] forKey:[NSString stringWithFormat:#"block%.3istored",i]];
}
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSString *path = [documentPath stringByAppendingPathComponent:#"blocks.save"];
BOOL successfulWrite = [myDict writeToFile: path atomically: YES];
if(successfulWrite == NO)
EDIT: To get the value for a certain key you can use the following:
int myInt = [[myDict objectForKey:#"block050stored"] intValue];
And if you want to replace the object for a certain key it's as easy as:
[myDict setObject:[NSNumber numberWithInt:1] forKey:#"block020stored"];
Now, the %.3i tells the string to add a number (i) formatted to always be three digits long. (000, 001, 010, 099, 100)
[NSString stringWithFormat:#"block%.3istored",i]
So the above line basically means, create a string with the words "block" and "stored" with a three digit representation of what ever the current value of the int "i" is in between them.
You can create NSNumber (which is an object, but int is not) and then store it into NSMutableDictionary:
NSNumber* num = [NSNumber numberWithInt:0];
for (int i = 1; i<=100; i++) {
[myDict setObject:num forKey:[NSString stringWithFormat:#"block%dstored",i]];
}
Related
I need to parse a string like [abc]000, and what I want to get is an array containing abc and 000. Is there an easy way to do it?
I'm using code like this:
NSString *sampleString = #"[abc]000";
NSArray *sampleParts = [sampleString componentsSeparatedByString:#"]"];
NSString *firstPart = [[[sampleParts objectAtIndex:0] componentsSeparatedByString:#"["] lastObject];
NSString *lastPart = [sampleParts lastObject];
But it's inefficient and didn't check whether the string is in a format like [**]**.
For this simple pattern, can just parse yourself like:
NSString *s = #"[abc]000";
NSString *firstPart = nil;
NSString *lastPart = nil;
if ([s characterAtIndex: 0] == '[') {
NSUInteger i = [s rangeOfString:#"]"].location;
if (i != NSNotFound) {
firstPart = [s substringWithRange:NSMakeRange(1, i - 1)];
lastPart = [s substringFromIndex:i + 1];
}
}
Or you could learn to use the NSScanner class.
As always, there are lots of ways to do this.
OPTION 1
If these are fixed length strings (each part is always three characters) then you can simply get the substrings directly:
NSString *sampleString = #"[abc]000";
NSString *left = [sampleString substringWithRange:NSMakeRange(1, 3)];
NSString *right = [sampleString substringWithRange:NSMakeRange(5, 3)];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
OPTION 1 (shortened)
NSArray *parts = #[ [sampleString substringWithRange:NSMakeRange(1, 3)],
[sampleString substringWithRange:NSMakeRange(5, 3)] ];
NSLog(#"%#", parts);
OPTION 2
If they aren't always three characters, then you can use NSScanner:
NSString *sampleString = #"[abc]000";
NSScanner *scanner = [NSScanner scannerWithString:sampleString];
// Skip the first character if we know that it will always start with the '['.
// If we can not make this assumption, then we would scan for the bracket instead.
scanner.scanLocation = 1;
NSString *left, *right;
// Save the characters until the right bracket into a string which we store in left.
[scanner scanUpToString:#"]" intoString:&left];
// Skip the right bracket
scanner.scanLocation++;
// Scan to the end (You can use any string for the scanUpToString that doesn't actually exist...
[scanner scanUpToString:#"\0" intoString:&right];
NSArray *parts = #[ left, right ];
NSLog(#"%#", parts);
RESULTS (for all options)
2013-05-10 00:25:02.031 Testing App[41906:11f03] (
abc,
000
)
NOTE
All of these assume well-formed strings, so you should include your own error checking.
try like this ,
NSString *sampleString = #"[abc]000";
NSString *pNRegex = #"\\[[a-z]{3}\\][0-9]{3}";
NSPredicate *PNTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", pNRegex];
BOOL check=[PNTest evaluateWithObject:sampleString ];
NSLog(#"success:%i",check);
if success comes as 1 then you can perform the action for separating string into array.
I'm trying to replace a dictionary in a mutable array.
Steps 1 through 4 should be good, but I'm having some trouble in step 5 - 6. Can you show me what has to be done to make this function work:
- (void) updatePlist {
// 1: String with plist path:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory
stringByAppendingPathComponent:#"Object.plist"];
// 2: Create a mutable dictionary containing current object and write
// "Yes" to the "Favorite" string:
NSMutableDictionary *mutDict = [NSMutableDictionary
dictionaryWithDictionary:[detailsDataSource objectAtIndex:detailIndex]];
[mutDict setObject:#"Yes" forKey:#"Favorite"];
// 3: Make a string containing current object name:
NSString *nameString = [[detailsDataSource objectAtIndex:detailIndex]
valueForKey:#"Name"];
// 4: Make a mutable array containing all objects:
NSArray *allObjectsArray = [[NSArray alloc] initWithContentsOfFile:path];
NSMutableArray *tmpMutArr = [NSMutableArray arrayWithArray:allObjectsArray];
// 5: Search for the dictionary in tmpMutArr with "Name" value matching nameString:
int *index;
for(int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:[NSString
stringWithFormat:#"%#", nameString]])nameString];)
{
index = i;
}
}
}
// 6: Replace the old dictionary with the new one and write array to plist:
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
allObjectsArray = nil;
allObjectsArray = [[NSArray alloc] initWithArray:tmpMutArr];
[allObjectsArray writeToFile:path atomically:YES];
}
EDIT:
Now the problem is:
for(int i=0;i<[tmpMutArr count];i++)
{
if([[tmpMutArr objectAtIndex:i] isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *tempDict = [tmpMutArr objectAtIndex:i];
if([[tempDict valueForKey:#"Name"] isEqualToString:
[NSString stringWithFormat:#"%#", nameString]])nameString];)
{
index = i; // Here 1
}
}
}
// ---------------------------- v And here 2
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
1: Incompatible integer to pointer conversion assigning to 'int' from 'int'; take the adress with &
2: Incompatible pointer to integer conversion sending 'int *' to parameter of type NSUInteger' (aka 'unsigned int')
Replace the line:
if([tempDict valueForKey:#"Name" == [NSString stringWithFormat:#"", nameString];)
with this line:
if([[tempDict valueForKey:#"Name"] isEqualToString: [NSString stringWithFormat:#"%#", nameString]])
since you are using string comparison here.
As pointed out in the comments by Martin R, you are trying to save an int value into a int pointer variable.
int index; //instead of 'int *index;'
That change should do the trick.
It could have worked if you had written int *index; and then index = &i;, since you are saving a pointer to an integer that way. But it doesn't seem to be what you are trying to do.
The second error is due you are providing an int pointer instead of an integer to this method:
[tmpMutArr replaceObjectAtIndex:index withObject:
[NSDictionary dictionaryWithDictionary:mutDict]];
But declaring index as an integer solves both errors already.
I have a NSMutableArray where i want to replace the sign | into a ; how can i do that?
NSMutableArray *paths = [dic valueForKey:#"PATH"];
NSLog(#"pathArr ", paths)
pathArr (
(
"29858,39812;29858,39812;29925,39804;29936,39803;29949,39802;29961,39801;30146,39782;30173,39779;30220,39774;30222,39774|30215,39775;30173,39779;30146,39782;29961,39801;29949,39802;29936,39803;29925,39804;29858,39812;29858,39812;29856,39812;29800,39819;29668,39843;29650,39847;29613,39855;29613,39855;29613,39856;29605,39857;29603,39867;29603,39867;29599,39892;29596,39909;29587,39957;29571,40018;29563,40038;29560,40043"
)
)
Update
This is where i got my path from
NSArray *BusRoute = alightDesc;
int i;
int count = [BusRoute count];
for (i = 0; i < count; i++)
{
NSLog (#"BusRoute = %#", [BusRoute objectAtIndex: i]);
NSDictionary *dic = [BusRoute objectAtIndex: i];
NSMutableArray *paths = [dic valueForKey:#"PATH"];
}
Provide that your object in the array path is string, you can do this
NSMutableArray *path2=[[NSMutableArray alloc]initWithArray:nil];
for (NSObject *obect in path) {
for (NSString *string in (NSArray*)obect) {
[path2 addObject:[string stringByReplacingOccurrencesOfString:#"|" withString:#","]];
}
}
NSLog(#"pathArr %# ", path2);
your array paths contains an another array which has string as object.
Hope this helps
//Copy the Array into a String
NSString *str = [paths componentsJoinedByString: #""];
//then replace the "|"
str = [str stringByReplacingOccurrencesOfString:#"|" withString:#";"];
i did this to replace a string in a .plist so it might work for you
array1 = [NSMutableArray arrayWithContentsOfFile:Path1];
NSString *item = [#"dfdfDF"];
[array1 replaceObjectAtIndex:1 withObject:item];
[array1 writeToFile:Path1 atomically:YES];
NSLog(#"count: %#", [array1 objectAtIndex:1]);
you may cast or convert paths to NSString and then do:
paths = (NSString *) [paths stringByReplacingOccurrencesOfString:#"|" withString:#";"];
if this does't work, create new NSString instance that containing pathArr text, invoke replaceOccurrences method and do invert conversion
NSMutableString *tempStr = [[NSMutableString alloc] init];
for (int i = 0; i < [paths count]; i++)
{
[tempStr appendString:[path objectAtIndex:i]];
}
then use this method for tempStr. And then try:
NSArray *newPaths = [tempStr componentsSeparatedByString:#";"];
may be last method not completely correct, so try experiment with it.
Uh, why don't you just go:
NSString *cleanedString = [[[dic valueForKey:#"PATH"] objectAtIndex:0] stringByReplacingOccurrencesOfString:#";" withString:#"|"];
If there are more than one nested array, you can go
for(int i = 0; i < [[dic valueForKey:#"PATH"] count]; i++)
{
NSString *cleanedString = [[[dic valueForKey:#"PATH"] objectAtIndex:i] stringByReplacingOccurrencesOfString:#";" withString:#"|"];
// do something with cleanedString
}
I'm struggling to save several locations into a plist file for later use,
after a bit of googling I discovered that an array of CLLocation per se cannot be saved,
so I was wondering about a way to do it.
I was thinking about a couple of classes to "serialize"/"deserilize" a single CLLocation object into an NSDictionary and then store an array of those NSDictionaries into the plist file, but I was wondering if there could be a better/smarter/reliable way to achieve that.
thanks in advance.
EDIT:
this is the function I use to save the data in the plist (the c_propertyName takes the code from the answer)
- (void) addLocation {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"/Locations.plist"];
NSArray *keys = [curLocation c_propertyNames];
NSDictionary *dict = [curLocation dictionaryWithValuesForKeys:keys];
[dict writeToFile: path atomically:YES];
}
EDIT 2 — SOLUTIONS:
Ok, I've figured all out. right below, I've posted a two-optioned solution to my own question.
It's quite easy with KVC.
Here's method of NSObject category to get property names (requires <objc/runtime.h>)
- (NSArray *)c_propertyNames {
Class class = [self class];
u_int count = 0;
objc_property_t *properties = class_copyPropertyList(class, &count);
if (count <= 0) {
return nil;
}
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, count)];
NSMutableSet *retVal = [NSMutableSet setWithCapacity:count];
[set enumerateIndexesWithOptions:NSEnumerationConcurrent
usingBlock:^(NSUInteger idx, BOOL *stop) {
const char *propName = property_getName(properties[idx]);
NSString *name = [NSString stringWithUTF8String:propName];
[retVal addObject:name];
}];
return [retVal allObjects];
}
then use it like this :
NSArray *keys = [yourLocation c_propertyNames];
NSDictionary *dict = [yourLocation dictionaryWithValuesForKeys:keys];
then save that dictionary.
I like solution 2 but serialization can be simpler if all one is trying to do is write straight to a file.
[NSKeyedArchiver archiveRootObject:arrayOfLocations toFile:path];
after some hours of search I've figured out the entire scenario.
Here you got a couple of solutions; the first is the more "dirty", because it's the first I've came up with, while the second is the more elegant. Anyway, I'll leave'em both because maybe they could both come in handy to somebody.
S O L U T I O N — 1
Thanks to the help of mit3z I could put together the pieces to figure out a solution.
as he points out, you can implement this method into a category on the NSObject:
- (NSArray *)c_propertyNames;
( look at his response for this part's code and further more details about it )
this gives me the liberty to do such thing:
- (void) addLocation {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"/Locations.plist"];
NSArray *keys = [curLocation c_propertyNames]; // retrieve all the keys for this obj
NSDictionary *values = [self.curLocation dictionaryWithValuesForKeys:keys];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(NSString *key in keys) {
NSString *aaa = [NSString stringWithFormat:#"%#", (NSString *)[values valueForKey:key]];
[dict setValue:aaa forKey:key];
}
[dict writeToFile:path atomically:YES];
}
the superdumb for loop is needed to convert all the data in the NSDictionary into NSStrings so that they can be written into the plist file without troubles, if you just make the dictionary and then you attempt to save it right away, you wan't succeed.
In this way I can have all the CLLocation obj "serialized" into a dict and then written into a plist file.
S O L U T I O N — 2
I came up with a really easiest (and more elegant) way to do so: using the NSCoding.
Because of the fact (that I realized that)the CLLocation datatype conforms NSCoding, you can invoke the data archiver via NSKeyedArchiver to get a blob describing your array and then store it right to the plist, like that:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"/Locations.plist"];
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
[data setValue:[NSKeyedArchiver archivedDataWithRootObject:arrayOfLocations] forKey:#"LocationList"];
[data writeToFile:path atomically:YES];
[data release];
and voila'. simple as that! :)
based on the same principles you can easily get back your data, via NSKeyUnarchiver:
self.arrayOfLocations = [[NSMutableArray alloc] initWithArray:[NSKeyedUnarchiver unarchiveObjectWithData: (NSData *)[dict objectForKey:#"LocationList"]]];
Helle everyone,
I have copied my plist into Sandbox (FileManager) and now I'm able to change plist's values.
I'm trying to do that but it doesn't work.
Here is my plist structure :
and my snippet
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"BlogList.plist"];
NSMutableDictionary *ressourceDico = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
NSArray *ressourceArray = [NSArray arrayWithArray:[ressourceDico objectForKey:#"BlogList"]];
for(int i = 0; i < [ressourceArray count] ; i++)
{
NSMutableDictionary *dico = [ressourceArray objectAtIndex:i];
if(![[dico objectForKey:#"isSaved"] boolValue] && [[dico objectForKey:#"identifier"] isEqualToString:identifier])
{
[dico setObject:[NSNumber numberWithBool:YES] forKey:#"isSaved"];
[dico writeToFile:plistPath atomically:YES];
}
}
You can't write just a part of the dictionary into the file, in order to 'update' just a part of it. Instead you have to, write the whole dictionary into the file.
So I think, you will have to send writeToFile:atomically: after looping over the array elements, but the reciever might be ressourceDico instead of dico.