NSMutableDictionary containing UIImageViews...Add mutable copy to an NSMutableArray? Alternative? - objective-c

I'm trying to build words in arrays by their key value in a dictionary. However, it won't work the way I'd like it to, because I can't "copy" a UIImageView.
It would be PERFECT, if when adding the letter from the dictionary to an array, it gives me a copy instead of the real object. I don't want to make multiple images of the same letter and add it to the dictionary, because then I could no longer call it by key "s" or "a", and I need more than one array to use the same letters at at time.
What can I do?
//How I create the letters
char s = 's';
NSString *key = [NSString stringWithFormat:#"%c", s];
alphabetS = [[UIImageView alloc] init]];
[alphabetS setImage:[UIImage imageNamed:#"s.png"]];
[allTilesDictionary setObject:alphabetS forKey:key];
[alphabetS release];
//How I use the imageviews from the dictionary
NSMutableArray *wordOne = [[NSMutableArray alloc] initWithObjects:[allTilesDictionary objectForKey:#"s"],[allTilesDictionary objectForKey:#"h"],[allTilesDictionary objectForKey:#"o"],[allTilesDictionary objectForKey:#"p"], nil];
EDIT: My solution. It works perfectly.
for (UIImageView *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters.image;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}

Your original code, slightly modified:
//How I create the letters
char s = 's';
NSString *key = [NSString stringWithFormat:#"%c", s];
[allTilesDictionary setObject:[UIImage imageNamed:#"s.png"] forKey:key];
//How I use the imageviews from the dictionary
NSMutableArray *wordOne = [[NSMutableArray alloc] initWithObjects:[allTilesDictionary objectForKey:#"s"],[allTilesDictionary objectForKey:#"h"],[allTilesDictionary objectForKey:#"o"],[allTilesDictionary objectForKey:#"p"], nil];
Your use of that code, slightly modified:
for (UIImage *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}
No unnecessary UIImageViews created.

for (UIImageView *letters in wordOne)
{
newLetter = [[UIImageView alloc] init];
newLetter.image = letters.image;
newLetter.userInteractionEnabled = YES;
//I can now either lay them out wherever I want on the view, or add them to a new array.
}

Related

How to create an NSarray with NSAttributedStrings but keeping the attributes within the array?

I want to store different strings with different attributes and store all of them in one array and then display the objects in one label but each object with its respective attribute.
Any suggestions?
EDIT: Solution derived from rmaddy's answer
NSDictionary *redAttrs = #{NSForegroundColorAttributeName:[UIColor redColor]};
NSDictionary *greenAttrs = #{NSForegroundColorAttributeName:[UIColor colorWithRed:0.118 green:0.506 blue:0.000 alpha:1.000]};
NSDictionary *orangeAttrs = #{NSForegroundColorAttributeName:[UIColor orangeColor]};
NSString *stringUm = #"Brazil";
NSString *stringDois = #"USA";
NSString *stringTres = #"England";
NSMutableAttributedString *redString = [[NSMutableAttributedString alloc] initWithString:stringUm];
[redString setAttributes:redAttrs range:NSMakeRange(0,4)];
NSMutableAttributedString *greenString = [[NSMutableAttributedString alloc] initWithString:stringDois];
[greenString setAttributes:greenAttrs range:NSMakeRange(0,2)];
NSMutableAttributedString *orangeString = [[NSMutableAttributedString alloc] initWithString:stringTres];
[orangeString setAttributes:orangeAttrs range:NSMakeRange(0,4)];
NSArray *myStrings = [[NSArray alloc] initWithObjects:redString, greenString, orangeString, nil];
NSLog(#"%#", [myStrings description]);
NSMutableAttributedString *result = [[NSMutableAttributedString alloc]init];
NSAttributedString *delimiter = [[NSAttributedString alloc] initWithString: #", "];
for (NSAttributedString *str in myStrings) {
if (result.length) {
[result appendAttributedString:delimiter];
}
[result appendAttributedString:str];
}
_lblUm.attributedText = result;
Your question is very unclear. But based on your comment to gerrytan's answer, your goal is clearer.
If you have an array of NSAttributedString objects, then you can create a single string by appending them all together with an NSMutableAttributedString.
NSArray *myStrings = ... // your array of NSAttributedString objects
NSMutableAttributedString *result = [[NSMutableAttributedString alloc] init];
// Put this delimiter between each string - change as desired
NSAttributedString *delimiter = [[NSAttributedString alloc] initWithString:#", "];
for (NSAttributeString *str in myStrings) {
if (result.length) {
[result appendAttributedString:delimiter];
}
[result appendAttributedString:str];
}
myLabel.attributedText = result;
UILabel only supports one NSAttributedString. I think what you can do is to place multiple UILabel side by side for each string on the array

Objects in NSMutableArray are all null

UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SudokuCell.png"]];
NSLog(#"%#", image);
[[self.blocks objectAtIndex:row] setObject:image atIndex:col];
NSLog(#"%#", [[self.blocks objectAtIndex:row] objectAtIndex:col]);
Is the code that I'm running. The first NSLog prints a UIImageView object, and the second NSLog prints (null). Why does the second NSLog not print the same thing as the first one?
The array self.blocks is initialized as such:
self.blocks = [[NSMutableArray alloc] initWithCapacity: 9];
for (int i = 0; i < 9; i++)
{
[self.blocks addObject:[[NSMutableArray alloc]initWithCapacity:9]];
}
NSMutableArray doesn't have a setObject:atIndex: method. You should use insertObject:atIndex: instead. Note, that the index can't be higher than the array's count (not the capacity) eg. it won't automatically fill up your array with "empty" values.

Dynamically Create Object Within Loop - Objective C

I'm looking for a way to dynamically create NSString objects in objective C based on how many of them I need (between 1 and 5). I then want to use those strings as names of objects which also are dynamically created;
Pseudo Code:
for (i=1, i <= number_of_characters, i++)
{
NSMutableString* theString = [NSMutableString character];
[theString appendString:[NSString stringWithFormat:#"%i ",i]];
UILabel *theString;
[theString release];
}
and I am hoping to get several UILabel objects named:
character1
character2
character3
and so on...
Thanks!
You can create UILabel objects on the fly, but you can't create variables at runtime. If you want to set the text of the label to theString, that's no problem:
NSMutableArray *labels = [NSMutableArray array];
for (i=1, i <= number_of_characters, i++)
{
NSMutableString* theString = [NSString stringWithFormat:#"%i ",i];
UILabel *label = [[UILabel alloc] initWithFrame:someCGRect];
label.text = theString;
[labels addObject:label];
[theString release];
}
Now you've got an array full of labels, each of which has a number as its text. The labels haven't been added to any view yet, so you'll want to take care of that.

Different Keys Point to Same Object(s) in NSMutableDictionary

I have a custom object called Person that among other things contains an NSString field called descriptor, which stores what sort of person that Person object is (angry, sad, wild, happy, morose, etc). All of my Person objects are in an NSMutableArray, but I would like to store them in an NSMutableDictionary in such a manner:
Key: A, Object: An NSMutableArray where all Person objects have descriptor starting with 'A'
Key: B, Object: An NSMutableArray where all Person objects have descriptor starting with 'B'
Key: C, Object: An NSMutableArray where all Person objects have descriptor starting with 'C'
etc...
I've tried to do this in my code below, and at the comment //POINT 1, the keys and arrays seem to match up, but at //POINT 2, when I print out the complete dictionary, all the keys come up with the same values!
So I wanted to know why the NSMutableArray I seem to have is not being stored as I want it in the NSMutableDictionary?
- (void)buildDictionaryForIndexList {
NSMutableDictionary *tempDict = [[[NSMutableDictionary alloc] init] autorelease];
NSMutableArray *personsStartingWithLetter = [[NSMutableArray alloc] init];
NSMutableArray *indexList = [[[NSMutableArray alloc] init] autorelease];
NSInteger loopCounter = 1;
NSString *firstLetter = [[[NSString alloc] init] autorelease];
for (Person *v in persons) {
firstLetter = [[v descriptor] substringWithRange:NSMakeRange(0, 1)];
if ([indexList containsObject:firstLetter]) {
[personsStartingWithLetter addObject:v];
if (loopCounter == [persons count]) {
[tempDict setObject:personsStartingWithLetter forKey:firstLetter];
}
} else {
if (loopCounter > 1) {
//POINT 1
NSLog(#"%#",[indexList objectAtIndex:[indexList count]-1]);
for (Person *q in personsStartingWithLetter) {
NSLog(#"%#",[q descriptor]);
}
[tempDict setObject:personsStartingWithLetter forKey:[indexList objectAtIndex:([indexList count] - 1)]];
[personsStartingWithLetter removeAllObjects];
}
[indexList addObject:firstLetter];
[personsStartingWithLetter addObject:v];
} // else
loopCounter++;
} // for
//POINT 2
NSEnumerator *enumerator = [tempDict keyEnumerator];
for (NSString *str in enumerator) {
NSLog(#"%#",str);
for (Person *c in [tempDict objectForKey:str]) {
NSLog(#"%#",[c descriptor]);
}
}
self.dictionary = tempDict;
} // buildDictionaryForIndexList
So, for example, at POINT 1 my output is:
A
Angry
Amiable
B
Belligerent
C
Cool
...
W
Wild
but at POINT 2 my output is
T
Wild
J
Wild
A
Wild
...
W
Wild
Change [tempDict setObject:personsStartingWithLetter forKey:[indexList objectAtIndex:([indexList count] - 1)]]; (just after point 1) to [tempDict setObject:[[personsStartingWithLetter copy] autorelease] forKey:[indexList objectAtIndex:([indexList count] - 1)]];. The problem is that NSDictionary copies the key, but retains the value. Therefore, if you add a mutable array to the dictionary and then change it, the array in the dictionary also changes. You need to create a non-mutable copy of the array to put in the dictionary.
The whole method is a bit overcomplicated.
- (void)buildDictionaryForIndexList
{
NSMutableDictionary *tempDict = [[[NSMutableDictionary alloc] init] autorelease];
for (Person *v in persons)
{
NSString* firstLetter = [[v descriptor] substringWithRange:NSMakeRange(0, 1)];
NSMutableArray* personsStartingWithLetter = tempDict [firstLetter];
if (personsStartingWithLetter == nil)
{
personsStartingWithLetter = [NSMutableArray array];
tempDict [firstLetter] = personsStartingWithLetter;
}
[personsStartingWithLetter addObject:v];
} // for
self.dictionary = tempDict;
}
You start with an empty dictionary that will contain arrays. For every person, you check whether there is a suitable array or not, and if there isn't one, you create it. So now there is an array for the person, so you add it to the array. That's all.

Fill NSMutableArray from another NsMutableArray

I have two classes indexViewController and flashCardQuestionViewController.
In the indexViewController i have table filled with an array.
Now i am getting some data from the database:
-(void)getMultipleChoiceAnswer
{
if(optionid!=nil)
[optionid removeAllObjects];
else
optionid = [[NSMutableArray alloc] init];
if(optionText!=nil)
[optionText removeAllObjects];
else
optionText = [[NSMutableArray alloc] init];
clsDatabase *clsDatabaseObject = [[clsDatabase alloc] init];
sqlite3_stmt *dataRows = [clsDatabaseObject getDataset:"select optionID,OptionText from flashCardMultipleAnswer where questionId=1"];
while(sqlite3_step(dataRows) == SQLITE_ROW)
{
[optionid addObject:[NSNumber numberWithInt:sqlite3_column_int(dataRows,0)]];
[optionText addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(dataRows,1)]];
}
sqlite3_finalize(dataRows);
[clsDatabaseObject release];
}
and I am calling this method in the viewDidLoad method of the indexViewController.
Now I have another NSMutableArray in the flashCardQuestionViewController named listNoOfOptionsInQuestion.
I want to fill listNoOfOptionsInQuestion with objects from optionText array in indexViewController.
How can I do this?
There are a number of ways to copy arrays: you can either use -[NSArray copy] to get an immutable copy, or -[NSArray mutableCopy] for a mutable copy. Don't forget that copy adds a reference so you'll need a release or autorelease somewhere (if you're not using GC that is).
Alternatively, you can use -[NSMutableArray addObjectsFromArray:].
Given your example, it looks like you want to do something like this at the end:
[flashCardQuestionViewController setListNoOfOptionsInQuestion:optionText];
And then in FlashCardQuestionViewController, you want something like:
- (void)setListNoOfOptionsInQuestion:(NSArray *)options
{
if (options != listNoOfOptionsInQuestion) {
[listNoOfOptionsInQuestion release];
listNoOfOptionsInQuestion = [options mutableCopy];
}
}
Rahul,
Do you really need to have a completely different copy of the MutableArray in each object. Would it be possible to have both objects point to the same array? For instance:
ClassOne *one = [[ClassOne alloc] init];
ClassTwo *two = [[ClassTwo alloc] init];
// build mutable array mArray
// ...
one.objectArray = mArray;
two.objectArray = mArray;
Or do you need to make changes to the two arrays in different ways? The try this (as suggested by Chris above) :
ClassOne *one = [[ClassOne alloc] init];
ClassTwo *two = [[ClassTwo alloc] init];
// build mutable array mArray
// ...
one.objectArray = mArray;
two.objectArray = [mArray mutableCopy];
again, if this isn't what you need then you'll have to give us a more precise question or problem that we can identify.