How to assign the NSArray string object values to other NSString variables - iphone

NSMutableArray *nameArray = [[NSMutableArray alloc] init];
[nameArray addObject:#"abc"];
[nameArray addObject:#"cdf"];
[nameArray addObject:#"jkl"];
//Use a for each loop to iterate through the array
for (NSString *s in nameArray) {
NSLog(#"value is %#", s);
}
The above code shows all the values of nameArray. But I want to assign all those values to these NSString:
NSString *a;
NSString *b;
NSString *cd;
An aray can have 1 or more elements but not more than 5.
Actually,I have 5 buttons, each button on click will add a NSString value(values are: f1,f2,f3,f4 and f5) to NSMutableArray. Now its upto the user if he clicks 2 buttons or 3 or 5 in a day. Now all these values will be saved in NSMutableArray (which can be 1 or 2 but not more than 5). That NSMutableArray will be saved in NSUserDefaults. This NSMutableArray than will be used in another view where I have some UIImageView (1,2,3,4 and 5). Now when I will get the string values from that Array(f1,f2,f3). If it is f1 then an image will be assigned to UIImage 1 if it is f3 then to image 3 and so on.
How to achieve this?

I would do something like that:
NSArray *array = [NSArray arrayWithObjects:#"A", #"B", #"C", #"D", #"E", nil];
NSString *a = nil, *b = nil, *c = nil, *d = nil, *e = nil;
NSUInteger idx = 0;
for ( NSString *string in array )
{
switch ( idx++ ) {
case 0: a = string; break;
case 1: b = string; break;
case 2: c = string; break;
case 3: d = string; break;
case 4: e = string; break;
}
}

As at least one element will be there in your array:
NSString *a = (NSString *)[nameArray objectAtIndex:0];
As maximum will be five elements:
for(int i = 1;i<[array count];i++)
{
if(i == 1)
{
NSString *b = (NSString *)[nameArray objectAtIndex:1];
}
else if(i == 2)
{
NSString *c = (NSString *)[nameArray objectAtIndex:2];
}
else if(i == 3)
{
NSString *d = (NSString *)[nameArray objectAtIndex:3];
}
else if(i == 4)
{
NSString *e = (NSString *)[nameArray objectAtIndex:4];
}
}

a = [nameArray objectAtIndex:0];
b = [nameArray objectAtIndex:1];
cd = [nameArray objectAtIndex:2];
If you want to put your array elements into separate variables with distinct names, there is no automation in objective c (unlike say, in JavaScript) since it is a compiled and not a interpreted language. Something similar you can achieve with NSDictionary, i.e. to "index" objects with strings or whatever type you want.

You could go on with a simple C array of 5 unsigned chars, where the index of the array would point to your data. Something like this:
unsigned char nameArray[5] = {0, 0, 0, 0, 0};
// if you want to set the 3rd variable, use:
nameArray[2] = 1;
// to query:
if (nameArray[2]) { ... }
// When you need to save it to NSUserDefaults, wrap it into an NSData:
NSData* nameData = [NSData dataWithBytes:nameArray length:sizeof(nameArray)];
[[NSUserDefaults standardUserDefaults] setObject:nameData forKey:#"myKey"];
// To query it:
NSData* nameData = [[NSUserDefaults standardUserDefaults] dataForKey:#"myKey"];
const unsigned char* nameArray2 = [nameData bytes];
unsigned char second = nameArray2[2];
EDITED: corrected array access

If there is at most five options the easiest way to do it is with an if-else-if chain.
NSString *label1 = nil, *label2 = nil, *label3 = nil, *label4 = nil, *label5 = nil;
for (NSString *s in nameArray) {
if (label1 == nil)
label1 = s;
else if (label2 == nil)
label2 = s;
else if (label3 == nil)
label3 = s;
else if (label4 == nil)
label4 = s;
else if (label5 == nil)
label5 = s;
}

NSString *str1=nil;
NSString *str2=nil;
NSString *str3=nil;
NSString *str4=nil;
for (LocationObject *objLoc in arrLocListFirstView)
{
if (objLoc.isLocSelected)
{
for (LocationObject *obj in arrLocListFirstView)
{
if (str1 == nil)
str1 = objLoc.strLoc;
else if (str2 == nil)
str2 = obj.strLoc;
else if (str3 == nil)
str3 = obj.strLoc;
else if (str4 == nil)
str4 = obj.strLoc;
}
NSString *combined = [NSString stringWithFormat:#"%#,%#,%#,%#", str1,str2,str3,str4];
lblLocation.text=combined; (displaying text in UILabel)
}
}

Related

How to extract specific data has equal value for some key from NSDictionary into a combined NSArray

Right now i have a dictionary like this, it's just a example, i got A to Z:
(
{
id = 13;
name = "Roll";
firstLetter = R;
},
{
id = 14;
name = "Scroll";
firstLetter = S;
},
{
id = 16;
name = "Rock";
firstLetter = R;
},
{
id = 17;
name = "Start";
firstLetter = S;
}
)
I want to extract the dict has the same firstLetter and combine these into a NSArray object. The expected results like this:
R array:
(
{
id = 13;
name = "Roll";
firstLetter = R;
},
{
id = 16;
name = "Rock";
firstLetter = R;
}
)
and S array:
(
{
id = 14;
name = "Scroll";
firstLetter = S;
},
{
id = 17;
name = "Start";
firstLetter = S;
}
)
How to do that?
I believe the better method would be the one suggested by Saohooou
But it can be optimised as
NSArray *array = #[#{#"id": #13,#"name":#"Roll",#"firstLetter":#"R"},
#{#"id": #14,#"name":#"Scroll",#"firstLetter":#"S"},
#{#"id": #15,#"name":#"Rock",#"firstLetter":#"R"},
#{#"id": #16,#"name":#"Start",#"firstLetter":#"S"}];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[array enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
NSString *key = dict[#"firstLetter"];
NSMutableArray *tempArray = dictionary[key];
if (!tempArray) {
tempArray = [NSMutableArray array];
}
[tempArray addObject:dict];
dictionary[key] = tempArray;
}];
NSLog(#"%#",dictionary);
NSMutableDictionay *dic = [NSMutableDictionay dictionay];
for ( YourObject *obj in yourDic.allValues )
{
NSMutableArray *dateArray = dic[obj.firstLetter];
if ( !dateArray )
{
dateArray = [NSMutableArray array];
[dic setObject:dateArray forKey:obj.firstLetter];
}
[dateArray addObject:obj];
}
so dic is what you want
I assume you organized the dict as an NSArray.
NSMutableDictionary* result = [NSMutableDictionary dictionary]; // NSDictionary of NSArray
for (id entry in dict) {
NSString* firstLetter = [entry firstLetter];
// Find the group of firstLetter
NSMutableArray* group = result[firstLetter];
if (group == nil) {
// No such group --> create new a new one and add it to the result
group = [NSMutableArray array];
result[firstLetter] = group;
}
// Either group has existed, or has been just created
// Add the entry to it
[group addObject: entry];
}
result holds what you want.
try this
NSString *currentStr;
//this int is to detect currentStr
NSInteger i;
NSMutableArray* R_Array = [[NSMutableArray alloc] init];
NSMutableArray* S_Array = [[NSMutableArray alloc] init];
for (NSDictionary *myDict in MyDictArray){
NSString *tempStr = [myDict objectForKey:#"firstLetter"];
if(currentStr = nil && [currentStr isEqualToString:""]){
currentStr = tempStr;
if([currentStr isEqualToString:"R"] ){
[R_Array addObject:myDict];
i = 0;
}else{
[S_Array addObject:myDict];
i = 1;
}
}else{
if([currentStr isEqualToString:tempStr]){
(i=0)?[R_Array addObject:myDict]:[S_Array addObject:myDict];
}else{
(i=0)?[R_Array addObject:myDict]:[S_Array addObject:myDict];
}
}
}
Base on your dictionaries. There are only two type, so i just created two array and use if-else for solving the problem. if there are multy values, you can try switch-case to do it.
Lets do this
NSMutaleDictionary * speDict = [[NSMutableDictionary alloc] init];
for(i=0;i<26;i++){
switch (i){
case 0:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"A"];
break;
case 1:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"B"];
break;
Case 2:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"C"];
break;
...........
Case 25:
[speDict setObject:[NSMutableArray alloc] init] forKey:#"Z"];
break;
}
}
for (NSDictionary *myDict in MyDictArray){
NSString *tempStr = [myDict objectForKey:#"firstLetter"];
switch (tempStr)
case A:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
case B:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
Case C:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
...........
Case Z:
[self addToMySpeDictArrayWithObject:myDict andStr:temStr];
break;
}
-(void)addToMySpeDictArrayWithObject:(NSDictionary*)_dict andStr:(NString*)_str
{
NSMutableArray *tempArray = [speDict objectForKey:_str];
[tempArray addObject:_dict];
}
then the speDict is like
A:
//all firstletter is A
myDict
myDict
myDict
B:
//all firstletter is B
myDict
myDict
.......
First of all the sample you've provided is an array of dicts (not a dict as the question notes). Now, the easiest way to query this array is by using an NSPredicate. Something like this perhaps:
NSArray *objects = ...; // The array with dicts
NSString *letter = #"S"; // The letter we want to pull out
NSPredicate *p = [NSPredicate predicateWithFormat:#"firstLetter == %#", letter];
NSArray *s = [objects filteredArrayUsingPredicate:p]; // All the 'S' dicts
If for some reason you need to group all of your objects without having to ask for a specific letter each time, you could try something like this:
// Grab all available firstLetters
NSSet *letters = [NSSet setWithArray:[objects valueForKey:#"firstLetter"]];
for (NSString *letter in letters)
{
NSPredicate *p = [NSPredicate predicateWithFormat:#"firstLetter == %#", letter];
NSArray *x = [objects filteredArrayUsingPredicate:p];
// Do something with 'x'
// For example append it on a mutable array, or set it as the object
// for the key 'letter' on a mutable dict
}
And of course you could further optimize this approach by implementing a method for filtering the array based on a letter. I hope that this makes sense.

How to get response from .clp(CLIPS) file?

I am trying to load .clp file in my iPhone application. For that I am using below code
NSString *filePath = [[NSBundle mainBundle]
pathForResource:#"autodemo" ofType:#"clp"];
environment = CreateEnvironment();
char *clipsFileChar = (char *)[filePath cStringUsingEncoding:NSASCIIStringEncoding];
Load(clipsFileChar);
Reset();
Run(-1);
NSString *evalS = [NSString stringWithFormat:#"(find-all-facts ((?f state-list)) TRUE)"];
char * evalStr = (char *)evalS;
DATA_OBJECT obj;// = {0,-1};
// obj.type = STRING;
// obj.value = evalStr;
int i = Eval(evalStr, &obj);
NSLog(#"%d",i);
now when I run this code Eval(evalStr, &obj) gives me 0 every time.
I am using autodemo.clp file from this link.
So, how to make Eval() command work and how do I get response returned by clp file?
thanks,
below code solved my problem, hope it will help to someone else.. :)
InitializeEnvironment();
Clear();
NSString *filePath = [[NSBundle mainBundle]
pathForResource:#"autodemo" ofType:#"clp"];
char *clipsFileChar = (char *)[filePath cStringUsingEncoding:NSASCIIStringEncoding];
IncrementGCLocks();
Load(clipsFileChar);
Reset();
Run(-1);
DecrementGCLocks();
[self nextUIState];
- (void)nextUIState
{
DATA_OBJECT theDO;
NSString * evalS = #"(find-all-facts ((?f state-list)) TRUE)";
char *evalStr = (char *)[evalS cStringUsingEncoding:NSASCIIStringEncoding];
int j = EnvEval(GetCurrentEnvironment(), evalStr, &theDO);
NSLog(#"j = %d",j);
if(factDict)
{
[factDict release];
factDict = nil;
factDict = [[NSMutableDictionary alloc] init];
}
id value = [self objectForDataObject:&theDO];
NSLog(#"%#",[value description]);
}
-(id) objectForDataObject: (DATA_OBJECT*) arg
{
switch(arg->type)
{
case FACT_ADDRESS:
{
DATA_OBJECT data = { 0 };
struct fact* aFact = (struct fact*) arg->value;
if(EnvGetFactSlot(GetCurrentEnvironment(),aFact,(char*)[#"current" UTF8String],&data))
{
[factDict setObject:[self objectForDataObject: &data] forKey:#"current"];
[factDict retain];
}
return factDict;
}
case SYMBOL:
{
NSString *str = [NSString stringWithUTF8String: ValueToString(arg->value)];
if ([str isEqual: #"nil"]) return nil;
if ([str hasPrefix: #"<<<"] && [str hasSuffix: #">>>"])
{
return [self dataFromSymbolString: str];
}
return str;
}
case STRING:
{
return [NSString stringWithUTF8String: ValueToString(arg->value)];
}
case INTEGER:
{
return [NSNumber numberWithInt: ValueToInteger(arg->value)];
}
case FLOAT:
{
return [NSNumber numberWithDouble: ValueToDouble(arg->value)];
}
case EXTERNAL_ADDRESS:
{
return (id) arg->value;
}
case MULTIFIELD:
{
int i, count = GetpDOLength(arg);
NSMutableArray *args = [NSMutableArray arrayWithCapacity: count];
FIELD_PTR fptr = (FIELD_PTR) GetMFPtr(GetpValue(arg),GetpDOBegin(arg));
for(i = 0; i < count; ++i, ++fptr)
{
DATA_OBJECT dobj;
dobj.type = fptr->type;
dobj.value = fptr->value;
[args addObject: [self objectForDataObject: &dobj]];
}
return args;
}
default:
return nil;
}
}
If you find out any other and better way(ofcourse there is), please let me know. :)

How to sort an array with alphanumeric values?

I have an array which contains strings like frame_10#3x.png , frame_5#3x.png,frame_19#3x.png etc.
So I want to sort this array according to the number after the underscore i.e. the correct sequence will be frame_5#3x.png,frame_10#3x.png,frame_19#3x.png.
I tried to use the following method but no result:
NSInteger firstNumSort(id str1, id str2, void *context) {
int num1 = [str1 integerValue];
int num2 = [str2 integerValue];
if (num1 < num2)
return NSOrderedAscending;
else if (num1 > num2)
return NSOrderedDescending;
return NSOrderedSame;
}
Please suggest how to do this sorting for array.
NSArray *sry_img = [[NSArray alloc] initWithObjects:#"frame_18#3x.png",#"frame_17#3x.png",#"frame_1222#3x.png",#"frame_10#3x.png",#"frame_3#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",#"frame_1#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",nil];
NSArray *sortedStrings = [sry_img sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
NSLog(#"%#",sortedStrings);
Enjy .......
But
localizedStandardCompare:, added in 10.6, should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method may be tweaked in future releases, and will be different under different localizations, so clients should not depend on the exact sorting order of the strings.
you want to do something like:
NSArray *components1 = [str1 componentsSeparatedByString:#"_"];
NSArray *components2 = [str2 componentsSeparatedByString:#"_"];
NSString *number1String = [components1 objectAtIndex:([components1 count] - 1])];
NSString *number2String = [components2 objectAtIndex:([components2 count] - 1])];
return [number1String compare:number2String];
I am not sure if my solution is the best possible approach but it can solve your problem for the time being :) .
1) First I have written a function to get the numbers before # character in your string and then I implemented simple SELECTION SORT algo to sort the array using this functions.
- (NSString*)getSubStringForString:(NSString*)value {
// First we will cut the frame_ string
NSMutableString *trimmedString = [NSMutableString stringWithString:[value substringWithRange:NSMakeRange(6, [value length]-6)]];
// New String to contain the numbers
NSMutableString *newString = [[NSMutableString alloc] init];
for (int i = 0; i < [trimmedString length] ; i++) {
NSString *singleChar = [trimmedString substringWithRange:NSMakeRange(i, 1)];
if (![singleChar isEqualToString:#"#"]) {
[newString appendString:singleChar];
} else {
break;
}
}
return newString;
}
This is the selection Implementation of the algo for sorting. The main logic is in the for loop. You can copy the code in viewDidLoad method to test.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"frame_10#3x.png",#"frame_5#3x.png",
#"frame_3#3x.png", #"frame_19#3x.png",
nil];
NSLog(#"Values before Sort: %#", array);
int iPos;
int iMin;
for (iPos = 0; iPos < [array count]; iPos++)
{
iMin = iPos;
for (int i = iPos+1; i < [array count]; i++)
{
if ([[self getSubStringForString:[array objectAtIndex:i]] intValue] >
[[self getSubStringForString:[array objectAtIndex:iMin]] intValue]) {
iMin = i;
}
}
if ( iMin != iPos )
{
NSString *tempValue = [array objectAtIndex:iPos];
[array replaceObjectAtIndex:iPos withObject:[array objectAtIndex:iMin]];
[array replaceObjectAtIndex:iMin withObject:tempValue];
}
}
NSLog(#"Sorted Values: %#", array);
I hope that it can atleast keep you going. :)
You can try this-
NSString *str1 = [[[[str1 componentsSeparatedByString:#"frame_"] objectAtIndex:1] componentsSeparatedByString:#"#3x.png"] objectAtIndex:0];
int num1 = [str1 integerValue];

NSString range of string at occurrence

i'm trying to build a function that will tell me the range of a string at an occurrence.
For example if I had the string "hello, hello, hello", I want to know the range of hello at it's, lets say, third occurrence.
I've tried building this simple function, but it doesn't work.
Note - the top functions were constructed at an earlier date and work fine.
Any help appreciated.
- (NSString *)stringByTrimmingString:(NSString *)stringToTrim toChar:(NSUInteger)toCharacterIndex {
if (toCharacterIndex > [stringToTrim length]) return #"";
NSString *devString = [[[NSString alloc] init] autorelease];
for (int i = 0; i <= toCharacterIndex; i++) {
devString = [NSString stringWithFormat:#"%#%#", devString, [NSString stringWithFormat:#"%c", [stringToTrim characterAtIndex:(i-1)]]];
}
return devString;
[devString release];
}
- (NSString *)stringByTrimmingString:(NSString *)stringToTrim fromChar:(NSUInteger)fromCharacterIndex {
if (fromCharacterIndex > [stringToTrim length]) return #"";
NSString *devString = [[[NSString alloc] init] autorelease];
for (int i = (fromCharacterIndex+1); i <= [stringToTrim length]; i++) {
devString = [NSString stringWithFormat:#"%#%#", devString, [NSString stringWithFormat:#"%c", [stringToTrim characterAtIndex:(i-1)]]];
}
return devString;
[devString release];
}
- (NSRange)rangeOfString:(NSString *)substring inString:(NSString *)string atOccurence:(int)occurence {
NSString *trimmedString = [inString copy]; //We start with the whole string.
NSUInteger len, loc, oldLength;
len = 0;
loc = 0;
NSRange tempRange = [string rangeOfString:substring];
len = tempRange.length;
loc = tempRange.location;
for (int i = 0; i != occurence; i++) {
NSUInteger endOfWord = len+loc;
trimmedString = [self stringByTrimmingString:trimmedString fromChar:endOfWord];
oldLength += [[self stringByTrimmingString:trimmedString toChar:endOfWord] length];
NSRange tmp = [trimmedString rangeOfString:substring];
len = tmp.length;
loc = tmp.location + oldLength;
}
NSRange returnRange = NSMakeRange(loc, len);
return returnRange;
}
Instead of trimming the string a bunch of times (slow), just use rangeOfString:options:range:, which searches only within the range passed as its third argument. See Apple's documentation.
So try:
- (NSRange)rangeOfString:(NSString *)substring
inString:(NSString *)string
atOccurence:(int)occurence
{
int currentOccurence = 0;
NSRange rangeToSearchWithin = NSMakeRange(0, string.length);
while (YES)
{
currentOccurence++;
NSRange searchResult = [string rangeOfString: substring
options: NULL
range: rangeToSearchWithin];
if (searchResult.location == NSNotFound)
{
return searchResult;
}
if (currentOccurence == occurence)
{
return searchResult;
}
int newLocationToStartAt = searchResult.location + searchResult.length;
rangeToSearchWithin = NSMakeRange(newLocationToStartAt, string.length - newLocationToStartAt);
}
}
You need to rework the whole code. While it may seem to work, it's poor coding and plain wrong, like permanently reassigning the same variable, initializing but reassigning one line later, releasing after returning (which will never work).
For your question: Just use rangeOfString:options:range:, and do this the appropriate number of times while just incrementing the starting point.

Memory Leak according to Instruments

Been running instruments on my app. Its says i am leaking 864bytes & 624bytes from 2 NSCFString and the library responsible is Foundation.
So that leads me to believe thats its not a leak caused by me? Or is it?
Here is the offending method according to instruments. It seems to be a
substringWithRange
that is leaking.
-(void) loadDeckData
{
deckArray =[[NSMutableArray alloc] init];
NSString* path = [[NSBundle mainBundle] pathForResource:#"rugby" ofType:#"txt"
inDirectory:#""];
NSString* data = [NSString stringWithContentsOfFile:path encoding:
NSUTF8StringEncoding error: NULL];
NSString *newString = #"";
NSString *newline = #"\n";
NSString *comma = #",";
int commaCount = 0;
int rangeCount = 0;
NSString *nameHolder = #"";
NSString *infoHolder = #"";
NSMutableArray *statsHolder = [[NSMutableArray alloc] init];
for (int i=0; i<data.length; i++)
{
newString = [data substringWithRange:NSMakeRange(i, 1)];
if ([newString isEqualToString: comma]) //if we find a comma
{
if (commaCount == 0)// if it was the first comma we are parsing the
NAME
{
nameHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
}
else if (commaCount == 1)//
{
infoHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
//NSLog(infoHolder);
}
else // if we are on to 2nd,3rd,nth comma we are parsing stats
{
NSInteger theValue = [[data
substringWithRange:NSMakeRange(i-rangeCount,rangeCount)]
integerValue];
NSNumber* boxedValue = [NSNumber
numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
}
rangeCount=0;
commaCount++;
}
else if ([newString isEqualToString: newline])
{
NSInteger theValue = [[data substringWithRange:NSMakeRange(i-
rangeCount,rangeCount)] integerValue];
NSNumber* boxedValue = [NSNumber numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
commaCount=0;
rangeCount=0;
Card *myCard = [[Card alloc] init];
myCard.name = nameHolder;
myCard.information = infoHolder;
for (int x = 0; x < [statsHolder count]; x++)
{
[myCard.statsArray addObject:[statsHolder
objectAtIndex:x]];
}
[deckArray addObject:myCard];
[myCard autorelease];
[statsHolder removeAllObjects];
}
else
{
rangeCount++;
}
}
[statsHolder autorelease];
}
Thanks for your advice.
-Code
As Gary's comment suggests this is very difficult to diagnose based on your question.
It's almost certainly a leak caused by you however, I'm afraid.
If you go to the View menu you can open the Extended Detail. This should allow you to view a stack trace of exactly where the leak occurred. This should help diagnose the problem.
When to release deckArray? If deckArray is a class member variable and not nil, should it be released before allocate and initialize memory space?