I am very new to Objective-C with Cocoa, and I need help.
I have a for statement in which I loop i from 1 to 18, and I would like to add an object to an NSMutableArray in this loop. Right now I have:
chapterList = [[NSMutableArray alloc] initWithCapacity:18];
for (int i = 1; i<19; i++)
{
[chapterList addObject:#"Chapter"+ i];
}
I would like it to add the objects, chapter 1, chapter 2, chapter 3... , chapter 18. I have no idea how to do this, or even if it is possible. Is there a better way? Please Help
Thanks in advance,
chapterList = [[NSMutableArray alloc] initWithCapacity:18];
for (int i = 1; i<19; i++)
{
[chapterList addObject:[NSString stringWithFormat:#"Chapter %d",i]];
}
good luck
Try:
[chapterList addObject:[NSString stringWithFormat:#"Chapter %d", i]];
In Objective-C/Cocoa you can't append to a string using the + operator. You either have to use things like stringWithFormat: to build the complete string that you want, or things like stringByAppendingString: to append data to an existing string. The NSString reference might be a useful place to start.
If you're wanting strings that merely say Chapter 1, Chapter 2, you can just do this:
chapterList = [[NSMutableArray alloc] initWithCapacity:18];
for (int i = 1; i<19; i++) {
[chapterList addObject:[NSString stringWithFormat:#"Chapter %d",i]];
}
And don't forget to release the array when you're done, as you're calling alloc on it.
Related
I am getting a stream from a live feed. It looks something like this as a mutableArray:
"Columbia Heights",
E04,
"Cleveland Park",
A05
The first line is a name and the second is a station code.
I need to turn this into a dictionary that is Plist compliant.
So the result in mind would look like this:
name:
"Columbia Heights",
code:
E04,
name:
"Cleveland Park",
code:
A05
What I've written so far is this:
NSMutableDictionary *stationDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"Name",#"name",#"Code",#"code", nil];
int i = 0;
for (i=0; i < counter; i++) {
// get names and codes for each of 3 fave stations
//[stationArray addObject:[mutableFaveArray objectAtIndex:i]];
NSString *tempName = [mutableFaveArray[i] valueForKey:#"name"];
NSString *tempCode = [mutableFaveArray[i] valueForKey:#"code"];
[stationDict setObject:tempName forKey:#"name"];
[stationDict setObject:tempCode forKey:#"code"];
}
I'm no longer getting an error, but I get as output, the same as my input.. I'm also only getting the last record..
"Cleveland Park",
A05
Updated Code:
NSMutableDictionary *stationDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"Name",#"name",#"Code",#"code", nil];
int i = 0;
for (i=0; i < mutableFaveArray.count; i++) {
NSString *tempName = [mutableFaveArray[i] valueForKey:#"name"];
NSString *tempCode = [mutableFaveArray[i] valueForKey:#"code"];
[stationDict setObject:tempName forKey:#"name"];
[stationDict setObject:tempCode forKey:#"code"];
[stationArray addObject:stationDict];
}
This results in the last dictionary entry being saved twice..
{
code = A05;
name = "Cleveland Park";
},
{
code = A05;
name = "Cleveland Park";
}
The problem is that you're only creating a single dictionary, stationDict, before the for loop. You then hit the for loop, which changes the values in stationDict, adds stationDict to the stationArray, changes the values in stationDict again, adds that same dictionary to stationArray, and so on. What you end up with is an array that contains the same object repeated mutableFaveArray.count times.
The solution is to either create a new dictionary at the beginning of the body of the for loop, or add a copy of the dictionary to add to the array. So, either this:
for (i=0; i < mutableFaveArray.count; i++) {
stationDict = [NSMutableDictionary dictionary];
//...continue with the rest of your code...
or this:
//...other for loop code precedes this...
[stationArray addObject:[stationDict copy]];
}
Either approach ensures that each thing you add to the array is a dictionary that's distinct from the others you've added. As a refinement, you could probably speed up the code a little by using a non-mutable dictionary. If you have to create a new dictionary each time through the loop, you can create it with the data you want it to contain rather than changing the objects, so you don't necessarily need it to be mutable. Also, you can declare the loop variable inside the for statement, which ensures that it'll go out of scope as soon as the for terminates. Also, you can use Objective-C's notation for dictionaries:
NSMutableArray *stationArray = [NSMutableArray array];
for (int i=0; i < mutableFaveArray.count; i++) {
[stationArray addObject:#{#"name":mutableFaveArray[i][#"name"],
#"code":mutableFaveArray[i][#"code"]}];
}
You can further abbreviate that and maybe speed it up a bit using fast enumeration:
NSMutableArray *stationArray = [NSMutableArray array];
for (NSDictionary *fave in mutableFaveArray) {
[stationArray addObject:#{#"name":fave[#"name"],
#"code":fave[#"code"]}];
}
Or you can let mutableFaveArray do the enumerating for you:
__block NSMutableArray *stationArray = [NSMutableArray array];
[mutableFaveArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop))
{
[stationArray addObject:#{#"name":obj[#"name"],
#"code":obj[#"code"]}];
}];
That last one might be a bit faster, but perhaps a bit harder to read.
I have a variable name referencing question for the Objective C gurus out there.
Lets say I have 6 UILabels on a form, the are setup with properties naming them myLabel1 - myLabel6
I would like to go through a for loop and populate these with something depending on the loop but im unsure how to specifiy the for loops variable and make it part of the labels name.
Here is what I would like to do:
for (int LP = 0; i <5)
{
labelLP.text = [NSString stringWithFormat:#"My label number:%d", LP};
}
What im not sure of is how to reference the label and append the LP int and use it in my loop. I'm sure there is a way to do this just not sure how.. Anyone??
you can always take advantage of the dynamic runtime of objective-c:
id var = object_getIvar(self,class_getInstanceVariable([self class], [[NSString stringWithFormat:#"label%d",LP] UTF8String]));
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
Whether one likes this approach is a question of style, but here's a way that should work:
for (int LP = 1; i <=6)
{
NSString *labelName = [NSString stringWithFormat: #"label%d", i];
UILabel *labelLP = (UILabel*)[self valueForKey: labelName];
labelLP.text = [NSString stringWithFormat:#"My label number:%d", LP};
}
I don't think you can create variable names on the fly, at least not trivially.
You could always use a switch case inside your loop:
for (int i=0; i<5; i++) {
switch(i) {
case 1:
myLabel1.text = [NSString stringWithFormat:#"My label number: %d", i];
break;
case 2:
myLabel2.text = [NSString stringWithFormat:#"My label number: %d", i];
break;
...
...
}
}
You could also store your labels in an array, and loop through that array.
The important point is not to get fixated about the variable names, but to think about why you need your objects and how to get them.
Hey guys, using obj-c and the cocos2d framework;
How would I populate an NSMutableArray with CCSprite's with a for-loop to reduce code.
I have +100 sprites/images that need to go into this array, so a for-loop is necessary.
This is my current code:
_backgrounds = [[NSMutableArray alloc]initWithCapacity:31];
for (int i = 31; i > 1; i--){
[_backgrounds addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"background_%d.png", i]]];
}
Im looking for something along the lines of this: (Although this code doesnt work),
for (int i = 31; i > 1; i--){
[backgrounds addObject:[CCSprite spriteWithFile:#"background%d.png", i]];
}
Thanks in advanced,
Oliver.
Chances are your shared CCSpriteFrameCache does not contain any values. You must populate it prior to accessing anything from it.
sorry for the simple question but how do you make a CAlayers using a for loop?
I have this now but what is the proper way of doing this?
for (int n = 1; n <= 6; n++) {
NSString *theCloud = [NSString stringWithFormat:#"cloudImage%d",n];
NSString *theCloudLayer = [NSString stringWithFormat:#"cloudLayer%d",n];
CALayer *theCloudLayer = theCloud.layer;
}
any help is appreciated.
Use an NSArray or NSMutableArray, not a bunch of variables with numbers at the end of their names (also known as a Poor Man's Array).
So that would be something like:
NSArray *cloudImages; // Use this to store your objects currently in the cloudLayerN variables
NSMutableArray *cloudLayers = [NSMutableArray array];
for (id cloud in cloudImages) {
[cloudLayers addObject:[cloud layer]];
}
I need to pick string valur from an NSMutableArray then save it into a plist. I've builded an NSMutableArray to display infos in table View. Maximum allowed index is 8. (paste just two in example)
The problem if the String doesn't exist, I get the following error:
sDict is a dictionary for saving datas to a property list file.
the code:
- (IBAction)save:(id)sender {
(...)
NSString *One;
NSString *Two;
...etc
if ([self.smOne objectAtIndex:0])
One = [self.smOne objectAtIndex:0];
if ([self.smOne objectAtIndex:1])
Two = [self.smOne objectAtIndex:1];
...etc
if (One)
[sDict setObject:[self.smTwo objectAtIndex:0]
forKey:[UserM stringByAppendingString:One]];
[sDict setObject:[self.smThree objectAtIndex:0]
forKey:[UserS stringByAppendingString:One]];
[sDict setObject:[self.smFour objectAtIndex:0]
forKey:[UserP stringByAppendingString:One]];
if (Two)
[sDict setObject:[self.smTwo objectAtIndex:1]
forKey:[UserM stringByAppendingString:Two]];
[sDict setObject:[self.smThree objectAtIndex:1]
forKey:[UserS stringByAppendingString:Two]];
[sDict setObject:[self.smFour objectAtIndex:1]
forKey:[UserParM stringByAppendingString:Two]];
...etc
}
This code works if all objects are present, but fails if it miss one of the object at index.
I really don't know how to check properly if the object is present or not, cause code above seem's to don't works well.
I've tried with [self.smOne count] but as problem to pass as a Int or String to make conditions with.
Thanks for answer.
it looks like you're explicitly checking smOne from indices 1 through 8. But you also mentioned that the array can have up to 8. So if it's missing, say, 6, 7 and 8, you'd still be calling [smOne objectAtIndex:6], which would result in an NSRangeException being raised as 6 is out of bounds for the array.
try this instead:
int i = 0;
for ( NSString *aString in self.smOne )
{
[sDict setObject:[self.smTwo objectAtIndex:i]
forKey:[UserM stringByAppendingSting:aString]];
[sDict setObject:[self.smThree objectAtIndex:i]
forKey:[UserS stringByAppendingString:aString]];
[sDict setObject:[self.smFour objectAtIndex:i]
forKey:[UserP stringByAppendingString:aString]];
i++;
}
it'll go through each object in the smOne array and add the object into sDict regardless of how many items you have in smOne.
also, be careful with how you're generating your keys. there's the possibility that [UserM stringByAppendingSting:aString] won't always be unique.
Sorry to ask again but i have dificulties to find how to rebuild arrays from the key/string couple saved with the loop.
i've tried this:
int i = 0;
for (NSString *SMServ in [temp objectForKey:
[UserMen stringByAppendingFormat:#"%d",i]]){
NSString *SMMem[i];
SMMem[i] = [temp objectForKey:[UserMen stringByAppendingFormat:#"%d",i]];
NSArray *theArray = [ NSArray arrayWithObjects:SMMem count:i];
i++;
}
But nothing happens.
if i try with for (i = 0; i < 9; i ++) and (i + 1) instead of [i], i get same bounds errors in the first example.
thanks again for help.
Well, finally it ,works. Thanks for link to the documentation, i read too fast last time.
I'm sure this is not the cleanest way, but it works with this loop:
for (key in sDict) {
if ([sDict valueForKey:[UserMen stringByAppendingFormat:#"%d",i]]) {
tempMe = [sDict valueForKey:[UserMen stringByAppendingFormat:#"%d",i]];
if (tempMe) {
[manArray insertObject:tempMe atIndex:(0 + a)];
[bankArray insertObject:[NSString stringWithFormat:#"%d",i] atIndex:(0 + a)];
a++;
}
}
if ([sDict valueForKey:[UserSerial stringByAppendingFormat:#"%d",i]]) {
SMSer = [sDict valueForKey:[UserSerial stringByAppendingFormat:#"%d",i]];
if (SMSer) {
[serArray insertObject:SMSer atIndex:(0 + b)];
b++;
}
}
if ([sDict valueForKey:[UserPart stringByAppendingFormat:#"%d",i]]) {
SMPart = [sDict valueForKey:[UserPart stringByAppendingFormat:#"%d",i]];
if (SMPart) {
[partArray insertObject:SMPart atIndex:(0 + c)];
c++;
}
}
i++;
}