iphone Development - pick unique image from array problem, syntax help - iphone

Code:
//pick one filename
int numFileNames = [imageArray count];
int chosen = arc4random() % numFileNames;
NSString *oneFilename = [imageArray objectAtIndex: chosen];
thanks!!

There's one error in your NSMutableArray:
You need to initialize it first.
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
;)
and here's a suggestion, if you do not necessarily require the interface builder's assistance, you might want to consider cocos2d. The stuffs you wanted to do can be done easily in it.
--
as for step 3. Do a random pick using Rand(), make a loop to check if the selected image is already added in an array (this array is for picked images), if it's in the array randomize again, if not then add in into the picked array, and do ball1.image = [UIImage imageNamed:[imageArray objectatindex:randomNum]];

The question does not specify the issue at hand, it just mentions that the developer wants to store a unique image name in array, so coding can be done:
NSMutableArray *arrImages = [NSMutableArray new];
for (int i=0; i<2; i++) {
NSString *imgName = [NSString stringWithFormat:#"imageBall%d",i];
//Here we can check whether image is already added or not.
if (![arrImages contains Object:imgName]) {
[arrImages addObject:imgName];
}
}
int choosen = arc4random() % (int)arrImages.count;
NSString *imageFileName = arrImages[choosen];

Related

Create 1 million NSMutableArrays with unique names easily

After teaching myself (mostly from this website) I have finally been unable to find a solution to a problem.
I am trying to easily create 1 million NSMutableArrays with unique names. What I mean by easily is not having 'hard code' all of the individual arrays.
What I would like to do is something like this:
for (int i = 1; i <= 1000000; i++) {
NSString *arrayNumber = [NSString stringWithFormat:#"%d", i];
NSString *millionArrayNumber = #"millionArrayNumber";
NSString *arrayName = [millionArrayNumber stringByAppendingString:arrayNumber];
NSMutableArray *[NSString arrayName] = [NSMutableArray array];
}
I can understand why this doesn't work but I can't think of another way of doing it. I thought it might be possible to use something similar to:
[button setTag = 1];
If I change the code to:
for (int i = 1; i <= 1000000; i++) {
NSMutableArray *millionArray = [NSMutableArray array];
[millionArray setTag: i];
}
I would then use the tag to control the arrays as you can do with buttons. This doesn't work for arrays though.
I hope I haven't been ambiguous.
I'm not sure how to convert a string into literal code like you're doing, but I think it's possible.
However, you can always just kick 1 million arrays to an NSMutableDictionary and give each one your unique key name.
NSMutableDictionary *arrayStore = [NSMutableDictionary dictionary];
for (int i = 1; i <= 1000000; i++) {
NSString *arrayNumber = [NSString stringWithFormat:#"%d", i];
NSString *millionArrayNumber = #"millionArrayNumber";
NSString *arrayName = [millionArrayNumber stringByAppendingString:arrayNumber];
arrayStore[arrayName] = [NSMutableArray array];
}
And obviously to get whatever array you want later, you just use:
NSMutableArray *uniqueArray = arrayStore[arrayName];
Edit: Not sure if you want to keep the number as the unique key as mentioned in the comment below but if so, you can do it with this:
NSMutableDictionary *arrayStore = [NSMutableDictionary dictionary];
for (int i = 1; i <= 1000000; i++) {
arrayStore[#(i)] = [NSMutableArray array];
}
And access it with (for example, array number 100):
NSMutableArray *uniqueArray = arrayStore[#100];

Performance issue creating Section Index Titles for UITableView

I'm displaying an array of contacts ( [[ContactStore sharedStore]allContacts] ) in a tableview and have divided the list into alphabetic sections. I have used the following code to return an array of the first letters of the contacts, and a dictionary of the number of entries per letter.
//create an array of the first letters of the names in the sharedStore
nameIndex = [[NSMutableArray alloc] init];
//create a dictionary to save the number of names for each first letter
nameIndexCount = [[NSMutableDictionary alloc]init];
for (int i=0; i<[[[ContactStore sharedStore]allContacts]count]; i++){
//Get the first letter and the name of each person
Contact *p = [[[ContactStore sharedStore]allContacts]objectAtIndex:i];
NSString *lastName = [p lastName];
NSString *alphabet = [lastName substringToIndex:1];
//If that letter is absent from the dictionary then add it and set its value as 1
if ([nameIndexCount objectForKey:alphabet] == nil) {
[nameIndex addObject:alphabet];
[nameIndexCount setValue:#"1" forKey:alphabet];
//If its already present add one to its value
} else {
NSString *newValue = [NSString stringWithFormat:#"%d", ([[nameIndexCount valueForKey:alphabet] intValue] + 1)];
[nameIndexCount setValue:newValue forKey:alphabet];
}
}
This works, however it is very slow when the array is large, I'm sure there's a better way to do this but I'm quite new to this so am not sure how. Are there any suggestions for a better way to do this?
Although Bio Cho has a good point, you might see an increase in performance by calling
[[ContactStore sharedStore]allContacts]
only once. For example:
nameIndex = [[NSMutableArray alloc] init];
nameIndexCount = [[NSMutableDictionary alloc] init];
/*
Create our own copy of the contacts only once and reuse it
*/
NSArray* allContacts = [[ContactStore sharedStore] allContacts];
for (int i=0; i<[allContacts count]; i++){
//Get the first letter and the name of each person
Contact *p = allContacts[i];
NSString *lastName = [p lastName];
NSString *alphabet = [lastName substringToIndex:1];
//If that letter is absent from the dictionary then add it and set its value as 1
if ([nameIndexCount objectForKey:alphabet] == nil) {
[nameIndex addObject:alphabet];
[nameIndexCount setValue:#"1" forKey:alphabet];
//If its already present add one to its value
} else {
NSString *newValue = [NSString stringWithFormat:#"%d", ([[nameIndexCount
valueForKey:alphabet] intValue] + 1)];
[nameIndexCount setValue:newValue forKey:alphabet];
}
}
Though I can't say for sure, I'd guess that repeatedly accessing your shared store is what's killing you. Maybe only accessing it once will give you what you need.
Consider storing your contacts in Core Data and using an NSFetchedResultsController.
The NSFetchedResultsController will only load a subset of the rows which are visible on the table view, thus preventing your user from having to wait for all the contacts to be sorted.
NSFetchedResultsController will also sort your contacts by an attribute (ie. first or last name), and you can set your section titles to be the first letter of the field you're sorting by.
Take a look at this question and this tutorial.

Questions app without repetition

I want to make a question app which shows a random question from a plist I made. This is the function (there are only 7 questions for now).
My function gives a random question but it always starts with the same question
and a question can be repeated. I need your help to generate the question randomly and without repetition.
currentQuestion=rand()%7;
NSDictionary *nextQuestion = [self.questions objectAtIndex:currentQuestion];
self.answer = [nextQuestion objectForKey:#"questionAnswer"];
self.qlabel.text = [nextQuestion objectForKey:#"questionTitle"];
self.lanswer1.text = [nextQuestion objectForKey:#"A"];
self.lanswer2.text = [nextQuestion objectForKey:#"B"];
self.lanswer3.text = [nextQuestion objectForKey:#"C"];
self.lanswer4.text = [nextQuestion objectForKey:#"D"];
rand()%7; will always produces a unique sequence of random numbers.
Use arc4random() % 7; instead.
currentQuestion=arc4random() %7;
I'd do it this way (in ARC, written out extra long for clarity):
#property (nonatomic,strong) NSDictionary *unaskedQuestions;
- (NSString *)nextRandomUnaskedQuestion {
if (!self.unaskedQuestions) {
// using your var name 'nextQuestion'. consider renaming it to 'questions'
self.unaskedQuestions = [nextQuestion mutableCopy];
}
if ([self.unaskedQuestions count] == 0) return nil; // we asked everything
NSArray *keys = [self.unaskedQuestions allKeys];
NSInteger randomIndex = arc4random() % [allKeys count];
NSString *randomKey = [keys objectAtIndex:randomIndex];
NSString *nextRandomUnaskedQuestion = [self.unaskedQuestions valueForKey:randomKey];
[self.unaskedQuestions removeObjectForKey:randomKey];
return nextRandomUnaskedQuestion;
}
Use an array of your question keys. Say you have array named arrKeys --> [A], [B], [C], [D], ... , [z], nil
Use (arc4random() % array.length-1) {as suggested by Suresh} to generate rendom index for your array. Say you got rand = 3
Get the key from array arrKeys #3 = D. Then from your NSDictionary use [nextQuestion objectForKey:#"D"] and also remove the 'D' key from your array as [arrKeys removeObjectAtIndex:3]. Repeat 1-3 steps for next question.

Store score at the time of completing game & get data on HighScore button press in iphone

I have done this code to store score.
But this is giving me the last added score only, not storing data every time on new index.
-(IBAction)btnSaveScore:(id)sender
{
if(!dictWinData)
dictWinData = [[NSMutableDictionary alloc] init];
array = [NSMutableArray arrayWithObjects:txt_EnterName.text,
[NSString stringWithFormat:#"%i",iTap], nil];
int increment = 0;
NSLog(#"array data is:--> %#",array);
for (int intWinData = 1; intWinData < [array count]; intWinData++)
{
[dictWinData setObject:array forKey:[NSString stringWithFormat:#"NameScore%d",increment]];
increment++;
}
}
If any mistake is there in my code then please let me guide for this.
Is there anyother way to store the data..?
Is NSUserDefaults helpful to store & display data...?
How to use NSUserDefaults to store & retrive data.
Thanks.
The issue is with this line:
int increment = 0;
Every time you press the save button the increment will be initialized to zero and hence every time the value is added to dictionary for same key NameScore0. Hence it will over write the existing dictionary value.
You need to make the increment as static like static int increment = 0; or make it as a global variable, it will solve the issue.
-(IBAction)btnSaveScore:(id)sender
{
if(!dictWinData)
dictWinData = [[NSMutableDictionary alloc] init];
array = [NSMutableArray arrayWithObjects:txt_EnterName.text,
[NSString stringWithFormat:#"%i",iTap], nil];
static int increment = 0;
for (int intWinData = 1; intWinData < [array count]; intWinData++)
{
[dictWinData setObject:array forKey:[NSString stringWithFormat:#"NameScore%d",increment]];
increment++;
}
}
NSUserDefaults is used for displaying the application setting in the ios device's settings pane. Don't save your application data there.
Instead of NSUserDefaults you can use plist to store data.
Please check the link

NSArray to NSMutableArray as random stack

Just a conceptual description first:
I am reading input from a text file (a list of words) and putting these words into an NSArray using componentsSeparatedByString method. This works.
But I wanted to select the words randomly and then delete them from the array so as to ensure a different word each time. Of course, you cannot change the NSArray contents. So...
I copied the contents of the NSArray into an NSMutableArray and use IT for the selection source. This also works - 269 objects in each array.
To return a word from the NSMutableArray I use the following code:
note- the arrays are declared globally
as
arrMutTextWords = [[NSMutableArray alloc] init]; //stack for words
arrTextWords = [[NSArray alloc] init]; //permanent store for words
-(NSString*) getaTextWord
{
// if the mutable text word array is empty refill
if ([arrMutTextWords count] == 0){
for (int i = 0 ; i < [arrTextWords count]; i++)
[arrMutTextWords addObject:[arrTextWords objectAtIndex:i]];
}
int i = random() % [arrMutTextWords count];
NSString* ptrWord = [arrMutTextWords objectAtIndex:i];
[arrMutTextWords removeObjectAtIndex:i];
return ptrWord;
}
The program crashes during a call to the method above - here is the calling code:
arrTmp is declared globally arrTmp = [[NSArray alloc] init]; //tmp store for words
for (int i = 0 ; i < 4; i++) {
tmpWord = [self getaTextWord];
[arrTmp addObject:tmpWord];
[arrTmp addObject:tmpWord];
}
I'm thinking that somehow deleting strings from arrMutTextWords is invalidating the NSArray - but I can't think how this would occur.
One possible source for problems is your fetching AND removing the NSString object from your list. Removing it releases that NSString instance therefore devalidating your reference.
To be shure to retain a reference you should use this code sequence instead:
NSString * ptrWord = [[[arrMutTextWords objectAtIndex:i] retain] autorelease];
[arrMutTextWords removeObjectAtIndex:i];
return ptrWord;
By the way: You should use
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray: array];
instead of copying all values by hand. While i do not know the implementation of NSMutableArray, i know from times long ago (NeXTstep), that there are several possible optimizations that may speed up basic NSArray operations.
And finally copying this way is much more concise.
Just ran this through XCode and got random words returned, however I skipped the whole for loop and used addObjectsFromArrayfrom NSMutableArray.
NSArray *randomArray = [[NSArray alloc] initWithObjects:#"Paul", #"George", #"John", nil];
NSMutableArray *muteArray = [[NSMutableArray alloc] init];
[muteArray addObjectsFromArray:randomArray];
int i = random() % [muteArray count];
NSString* ptrWord = [muteArray objectAtIndex:i];
[muteArray removeObjectAtIndex:i];
NSLog(#"ptrWord %#", ptrWord); //gave me a different name each time I ran the function.
Hope this clears some things up.