Convert NSString to fetch synthesized information - iphone

//COPY THIS CODE IN A FRESH PROJECT!!!
//THIS 2 LINES ARE JUST EXAMPLES, OF VALUES PUSHES OUT A DATABASE
NSString *messagelevel1 = #"45";
NSString *currentlevel = #"1";
NSString *HuidigLevel = currentlevel;
NSDecimalNumber *huidigleveldec = [[NSDecimalNumber alloc] initWithString: HuidigLevel];
float HuidigLevelRek = [huidigleveldec floatValue];
//HERE IS THE PROBLEM
NSString* LevelTotaal=[[NSString alloc] initWithFormat:#"messagelevel%.f",HuidigLevelRek];
NSString*result = LevelTotaal;
NSLog(#"%#",result);
// THE ABOVE RESULT SHOULD RETURN THE SAME VALUE AS THE NEXT (messagelevel1) LINE BUT IT RETURNS ONLY "messagelevel1" AND NOT THE VALUE!
NSLog(#"%#",messagelevel1);
I want the *result string behaves like the *huidiglevel string and fetch some information, but because the LevelTotaal is a NSString, It doesn't fetch this information. I really got no idea where to google for this problem, searching the Developer docs didn't helped either . Maybe you guys can help me out?
Actually the second NSLog returns the value and to first NSLog just returns messagelevel1. To tell you in short ;)
I hope you guys get what I'm saying!

I think what you're trying to do is use variable variables, a system that does not exist in Objective-C. In PHP, you can use variable variables:
$hello = 'abcdef';
$varName = 'hello';
print $$varName; // prints the value of $hello, which is 'abcdef'
Like many things in PHP, this is not really a good way to design software. Instead, consider using something like a NSDictionary, this allows you to give specific data a key.
NSMutableDictionary *aDict = [NSMutableDictionary dictionary];
[aDict setObject:[NSNumber numberWithFloat:4.5] forKey:#"messageLevel1"];
NSString *result = [aDict objectForKey:#"messageLevel1"];
You can obtain the data dynamically, the key can be generated or obtained at runtime.
Edit:
Rather than having variables called messageLevel1, messageLevel2, messageLevel3 ... messageLeveln, just use an array.
NSMutableArray *messageLevels = [NSMutableArray array];
[messageLevels addObject:#"1"];
[messageLevels addObject:#"45"];
[messageLevels addObject:#"123"];
NSString *result = [messageLevels objectAtIndex:HuidigLevelRek];

Related

NSDictionary won't write to plist

I'm trying to write an NSDictionary with a complex structure to a plist for use in an iPhone app. However, the file doesn't seem to write at all, and I have no idea why.
This is what the structure should look like:
Level Dict
Roads Array
Road1 Array
Vertex1 Dict
x Number
y Number
Vertex2 Dict
...
And this is what my code looks like:
NSMutableDictionary *levels = [[NSMutableDictionary alloc] init];
NSMutableArray *roads = [[NSMutableArray alloc] init];
for(ChainLinkRoad *r in data.roads){
NSMutableArray *road = [[NSMutableArray alloc] init];
for(ChainPoint *p in r.v){
NSNumber *x = [NSNumber numberWithFloat: p.x];
NSNumber *y = [NSNumber numberWithFloat: p.y];
NSMutableDictionary *vertex = [[NSMutableDictionary alloc] init];
[vertex setObject:x forKey:#"x"];
[vertex setObject:y forKey:#"y"];
[road addObject:vertex];
}
[roads addObject:road];
}
[levels setObject:roads forKey:#"Roads"];
bool b = [levels writeToFile:#"test.plist" atomically:YES];
//returns true
I've tried converting the mutables to their immutable counterparts, but that didn't work. I'm able to access data from the final NSDictionary (levels) just fine.
Edit: I should add that this plist is not for actual use in the iphone game. It's for personal use when designing levels. The code won't exist in the final version.
A common problem is, that the dictionary isnt valid for string transformation like invalid UTF-8 characters. Make a output on the console to check it.
If that doesnt help you, save only some elements to see what is going on.
I just posted an answer for this same issue yesterday. Instead of trying to save out the individual data elements of a class save the entire object using NSKeyArchiver and NSCoding. Click the link for a full explanation.
How can I save Array of Class Objects in to a Plist(Iphone Development)

Objective-c Array Learning

Okay I am learning about arrays and how to work with them like I used to...... (Used to do alot of scripting but now am trying to learn to develop ipad and iphone app's
But my issue is I have it where it pulls a bunch of data from yahoo finance with a for loop..
But now my issue is how can I work with just one peice of the array data that has been pulled
here is my example
-(IBAction) clicked:(id)sender {
NSString * StockOneYahooFinance = [NSString stringWithFormat:#"http://finance.yahoo.com/q/hp?s=S+Historical+Prices"];
NSString * PulledStockOne = [NSString stringWithContentsOfURL:[NSURL URLWithString:StockOneYahooFinance] encoding:1 error:nil];
for (i=1;i<=10;i++){
NSString *StartPulling = [[PulledStockOne componentsSeparatedByString:#"nowrap align="] objectAtIndex:i];
NSString *StartOpen = [[StartPulling componentsSeparatedByString:#">"] objectAtIndex:3];
NSString *Open = [[StartOpen componentsSeparatedByString:#"<"] objectAtIndex:0];
NSString *StartClose = [[StartPulling componentsSeparatedByString:#">"] objectAtIndex:9];
NSString *Close = [[StartClose componentsSeparatedByString:#"<"] objectAtIndex:0];
NSMutableArray *StockOpens = [[NSMutableArray alloc] initWithCapacity:6];
[StockOpens addObject:Open];
sixtyday.text = [OpenValues objectAtIndex:10];
nintyday.text = [CloseValues objectAtIndex:10];
if ([OpenValues objectAtIndex:10]=[OpenValues objectAtIndex:11] {
sevenday.text = #"Plus One";
}
}
}
But now I want to do something like
year.text=StockOpens[5];
How can I do this.
Starting in Xcode 4.4 (LLVM 4.0), literals can be used for C-style subscripting in Objective-C.
year.text = StockOpens[5];
LLVM has documented the use of literal here: Objective-C Literals
Note: Because Clang will translate the literal usage, in this case to objectAtIndexedSubscript:, the OS X v10.8 (or iOS 6) Foundation framework is required.
StockOpens is an array object so you need to call a method to get the object at an index. On NSMutableArray its [StockOpens ObjectAtIndex:5]
year.text = [[StockOpens objectAtIndex:5]StringValue];
To do StockOpens[5] you need to use a C-array.
This depends on what kind/class of objects you fill StockOpens with, if it's simply NSStrings, you can do
year.text = [StockOpens objectAtIndex:5];
If it's some other object that is not a string, you can maybe call its description:
year.text = [[StockOpens objectAtIndex:5] description];
P. s.: there's documentation on developer.apple.com, please read it! This question is so simple (and fundamental) that it must not be asked on SO.

Creating dynamic NSMutableDictionary query with multiple values

I'm working on a project and I want to be able to handle some template type messages. The template would contain something like:
"{{user1}} has just created an account"
I then have a data map that would give you a location within the NSMutableDictionary where the data is located:
"activity.message.status"
I then want to be able to query the NSMutableDictionary by splitting up that string, so that it becomes something like:
[[[myDictionary objectForKey:#"activity"] objectForKey:#"message"] objectForKey:#"status"]
I could make something as long as it was consistant on being just 3 strings, but some may be more or less.
Any help would be extremely appreciated.
It's actually much easier than splitting strings into keys. Apples Key-Value-Coding allows exactly what you want.
[myDictionary valueForKeyPath:#"activity.message.status"];
A key path is a string of dot separated keys that is used to specify a sequence of object properties to traverse. The property of the first key in the sequence is relative to the receiver, and each subsequent key is evaluated relative to the value of the previous property.
For example, the key path address.street would get the value of the address property from the receiving object, and then determine the street property relative to the address object.
Key-Value Coding Programming Guide
You would do something like,
NSArray *array = [#"activity.message.status" componentsSeperatedByString:#"."];
Which will create an array containing {activity,message,status).
Now you have your array you can use for querying your dictionary.
[[[myDictionary objectForKey:[array objectAtIndex:0]] objectForKey:[array objectAtIndex:1]] objectForKey:[array objectAtIndex:2]];
Which is equivalent to:
[[[myDictionary objectForKey:#"activity"] objectForKey:#"message"] objectForKey:#"status"];
Hope this helps !
It's not clear to me from your question how we should map user1 to activity.message.status. For now I'll assume you mean that the template might contain a string like "{{activity.message.status}}" and you want to be able to parse that.
Here's one iteration that operates on an NSMutableString that can be looped until no match is found:
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\{\\{.+?\\}\\}"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSRange matchRange = [regex rangeOfFirstMatchInString:string
options:0 range:NSMakeRange(0, [string length])];
NSRange keyPathRange = NSMakeRange(matchRange.location + 2, matchRange.length - 4);
NSString *keyPath = [string substringWithRange:keyPathRange];
NSString *newSubstring = [myDictionary valueForKeyPath:keyPath];
[string replaceCharactersInRange:matchRange withString:newSubstring];
I haven't tested this code.
How about a (recursive ... cool) category method on NSMutableDictionary like this:
- (void)setObject:(id)object forCompoundKey:(NSString *)compoundKey {
NSArray *keys = [compoundKey componentsSeparatedByString:#"."];
if ([keys count] == 1) {
return [self setObject:object forKey:compoundKey];
}
// get the first component of the key
NSString *key = [keys objectAtIndex:0];
// build the remaining key with the remaining components
NSRange nextKeyRange;
nextKeyRange.location = 1;
nextKeyRange.length = [keys count] - 1;
NSArray nextKeys = [keys subarrayWithRange:nextRange];
NSString *nextKey = [nextKeys componentsJoinedByString:#"."];
NSMutableDictionary *nextDictionary = [NSMutableDictionary dictionary];
[self addObject:nextDictionary forKey:key];
// now the cool part... recursion
[nextDictionary setObject:object forCompoundKey:nextKey];
}
I haven't tested this, but it passes a quick desk check. The objectForCompoundKey: retrieval can be written analogously.

Creating a Two-Dimensional Array with Concrete Positions

I need to create a custom array:
In php I would define as follows:
$myarray[100][80] = 1;
But I don't know how to do it in objective-c...
I don't need an array [0][0],[0][1],[0][2], ... I only need concrete positions in this array [80][12], [147][444], [46][9823746],...
The content of these positions always will be = 1;
for this you would use a dictionary rather than an array as they are always 0,1,2 keyed so something along the lines of:
NSNumber *one = [NSNumber numberWithInt:1];
NSString *key = #"80,12";
NSDictionary *items = [NSDictionary dictionaryWithObject:one forKey:key];
Then to pull them out again you would use the objectForKey: method.
You cannot put ints directly into arrays or dictionaries that's why it is wrapped in the NSNumber object. To access the int after getting the NSNumber out of the dictionary you would use something like:
NSNumber tempNum = [items objectForKey:key];
int i = tempNum.intValue;
See the docs here for a full explanation of the NSDictionary class. Hope this helps...
I an not a PHP master but I believe in php arrays are not real arrays they are hash tables right?
Anyway, I think you are looking for NSDictionary or NSMutableDictionary class.
That looks more like a bitset than an array.
Allocating so many cells for that seems useless, so maybe you could revert the problem, and store the positions in an array.
Well in objective c we can use NSMutableArray to define 2-D arrays.
See the following code, it might help you
NSMutableArray *row = [[NSMutableArray alloc] initWithObjects:#"1", #"2", nil];
NSMutableArray *col = [[NSMutableArray alloc] init];
[col addObject:row];
NSString *obj = [[col objectAtIndex:0] objectAtIndex:0];
NSLog(#"%#", obj);

what is the exact meaning of "message" in this line on iphone

NSDictionary *story = [stories objectAtIndex: indexPath.row];
cell.text=[NSString stringwithFormat:[story objectForKey#"message];
i dont knw what exaclty "message " contains (what is the meaning of objectForKey#"message")
EDIT CODE
NSString *key =[appDelegate.books objectAtIndex:indexPath.row];
//dict y=#"Name";
NSArray *nameSection = [dict objectForKey:key];
NSDictionary *story = [nameSection objectAtIndex: indexPath.row];
cell.text=[NSString stringwithFormat:[story objectForKey:key]];
NSLog(#"Value Of message: %#", [dict objectForKey:key]);
why my code crashes
If you are more familiar with Java or C# the code is equivalent to something like this:
// Assuming stories is declared as: List<Dictionary<string, string> stories;
Dictionary<string, string> story = stories[indexPath.row];
cell.Text = String.Format(story["message"]);
In Smalltalk-style (and therefore Objective-C too) Object Oriented programming, methods are more like messages to other objects. So a good Objective-C method name should read like an English sentence (Subject-Verb-Object). Because of this working with dictionaries (hash tables) looks like this:
[myDictionary setObject:#"Value" forKey:#"someKey"];
[myDictionary objectForKey:#"someKey"]; // == #"Value"
In Java it would be:
myDictionary.put("someKey", "Value");
myDictionary.get("someKey"); // == "Value"
Notice how the key ("someKey") was the first argument in the Java example. In Objective-C you name your arguments with the method name, hence setObject: forKey:. Also notice that in Objective-C strings start with an # symbol. That's because Objective-C strings are different from regular C strings. When using Objective-C you almost always use Objective-C's # strings.
In C# there is a special syntax for Dictionaries so it becomes:
myDictionary["someKey"] = "Value";
myDictionary["someKey"]; // == "Value"
One important problem that you might encounter if you're new is the problem of native types.
In Java to add an int to a Dictionary you used to have to do:
myDictionary.put("someKey", new Integer(10));
Because the primitive types (int, char/short, byte, boolean) aren't real Objects. Objective-C has this problem too. So if you want to put an int into a dictionary you must use NSNumber like so:
[myDictionary setObject:[NSNumber numberForInt:10]
forKey:#"someKey"];
And you pull out the integer like so:
NSNumber *number = [myDictionary objectForKey:#"someKey"];
[number intValue]; // == 10
EDIT:
Your code might be crashing if you have a '%' character in your string, since stringWithFormat is just like NSLog in that it takes many arguments. So if story["message"] is "Hello" then it'll work fine without extra arguments but if it's "Hello %#" you need to add one argument to stringWithFormat.
NSString *message = #"Hello %#";
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:message forKey:#"message"];
NSString *output = [NSString stringWithFormat:[dict objectForKey:#"message"], #"World!"];
// output is now #"Hello World!".
#"message" is a key for a value stored in the NSDictionary object. The first line declares an NSDictionary named story that appears to come from an array.
If you want to find what value is stored for the key:#"message", consider using:
NSLog(#"Value Of message: %#", cell.text);
Run and check the console to see the output. (SHIFT + COMMAND + Y) in XCode will bring up the console, if that's what you are using. If you are unfamiliar with NSArrays/NSDictionaries, give Apple's Documentation a look.
I'm just guessing at all of this since that is a very limited sample of code. Try submit more code when you ask a question so that the viewers can get a better idea of your questions.
That is an example of key-value coding, and a lot of information is available on the Apple dev site if you're interested:
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html