Trying to access data from an array and print it out - objective-c

I have made an array which I store 5 strings and 1 int into which I then store in to another array.
I'm trying to access and print out an array but it only give me this:
2016-01-11 18:47:55.429 quizgame-chrjo564[3378:145727] (null)
I've tried these alternatives:
NSLog(#"%#", [dataArray objectAtIndex:0]);
NSLog(#"%#", dataArray[0]);
Here is all my code:
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *_questions;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self quizStart];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)prepQuestions {
[self question:#"Vad heter jag?" answer1:#"Anton" answer2:#"Christian" answer3:#"Christoffer" answer4:#"Simon" correctAnswer:2];
}
- (void)question:(NSString *)q answer1:(NSString *)a1 answer2:(NSString *)a2 answer3:(NSString *)a3 answer4:(NSString *)a4 correctAnswer:(NSInteger)c {
NSArray *tmpArray = [NSArray arrayWithObjects:
[NSString stringWithString:q],
[NSString stringWithString:a1],
[NSString stringWithString:a2],
[NSString stringWithString:a3],
[NSString stringWithString:a4],
[NSNumber numberWithInteger:c],nil];
NSLog(#"%#", q);
[_questions addObject:tmpArray];
}
- (void)quizStart {
[self prepQuestions];
NSArray *dataArray = [_questions objectAtIndex:0];
NSLog(#"%#", [dataArray objectAtIndex:0]);
}
#end
Thanks in advance
*Updated with error after change:
2016-01-11 19:28:00.816 quizgame-chrjo564[3901:202243] - [__NSCFConstantString objectAtIndex:]: unrecognized selector sent to instance 0x75030
2016-01-11 19:28:00.822 quizgame-chrjo564[3901:202243] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [__NSCFConstantString objectAtIndex:]: unrecognized selector sent to instance 0x75030'

You never initialize _questions.
Change this:
[_questions addObject:tmpArray];
to:
if (!_questions) {
_questions = [NSMutableArray array];
}
[_questions addObject:tmpArray];
Also, here's a suggestion to make your code cleaner and easier to read.
Don't needlessly use stringWithFormat:.
Use modern syntax for arrays and dictionaries.
Use modern syntax for number boxing.
In other words, you question:... method can be written as:
- (void)question:(NSString *)q answer1:(NSString *)a1 answer2:(NSString *)a2 answer3:(NSString *)a3 answer4:(NSString *)a4 correctAnswer:(NSInteger)c {
NSArray *tmpArray = #[ q, a1, a2, a3, a4, #(c) ];
NSLog(#"%#", q);
if (!_questions) {
_questions = [NSMutableArray array];
}
[_questions addObject:tmpArray];
}

Related

Objective C - Accessing typedef block pointer to add and remove from NSArray

I have a typedef
typedef void(^MyCompletionBlock)(NSDictionary *info);
- (void)populateWithCompletion:(MyCompletionBlock)completion
{
NSMutableArray *array = [NSMutableArray new];
[array addObject:completion];
[array removeObject:completion];
NSAssert(array.count == 0, "Why");
}
The object is not removed from the array, the pointer to completion is something like
completion MyCompletion 0x0000000102bcf30c
but when inspecting the contents of NSArray I see
[0] __NSMallocBlock__ * 0x105900610 0x0000000105900610
How do I get the underlying function pointer so that I can remove it from the array? Also, why is the underlying function pointer added to the array instead of my typedef?
Can't reproduce. Here is the complete code of my view controller:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self populateWithCompletion:^(NSDictionary *info) {
NSLog(#"%#", info);
}];
NSLog(#"%#", #"got to here");
// Do any additional setup after loading the view, typically from a nib.
}
typedef void(^MyCompletionBlock)(NSDictionary *info);
- (void)populateWithCompletion:(MyCompletionBlock)completion
{
NSMutableArray *array = [NSMutableArray new];
[array addObject:completion];
[array removeObject:completion];
NSAssert(array.count == 0, #"Why");
}
#end
Launched the app. Console says "got to here".

NSMutableDictionary using objectAtIndex

I am new to Xcode and I have created a NSMutableDictionary *dIc with following data:
Keys : ID , Name
Data :
ID = 1, Name = John
ID = 2, Name = Smith
I want to access dIc with specific row. I want this result for example :
Name = Smith.
I tried :
-(void)initiateArrays
{
dIc =[[NSMutableDictionary alloc] init];
}
- (void)viewDidLoad
{
[self initiateArrays];
[self callingWebSrvc];
[super viewDidLoad];
}
-(void)callingWebSrvc
{
NSInteger i=0;
do {
self.selectedRowId = [[mainMenuID objectAtIndex:i]integerValue];
[self getItemListFromWebSrvc];
i++;
} while (i<= mainMenuData.count - 1);
}
-(void) getItemListFromWebSrvc
{
//............ Request ....................................>>>
.
.
.
//............ Response ....................................>>>
NSInteger i = 0;
do {
elm = [xmlDataTable objectAtIndex:i];
//Set Object into Arrays
[dIc setObject:[NSNumber numberWithInt:selectedRowId] forKey:#"Id"];
[dIc setObject:[elm childNamed:#"Name"].value forKey:#"Name"];
NSArray *keys = [rowArray allKeys];
// values in foreach loop
for (NSString *key in keys) {
NSLog(#"%# is %#",key, [dIc objectForKey:key ]);
}
i=i+1;
} while (i <= xmlDataTable.count-1);
}
-(void)showResult
{
NSString *anObject = [[dIc objectForKey:#"Name" ] objectAtIndex:1];
NSLog(#"The Value is = %#",anObject );
}
but it's not working.
when i call [self showResult]; i got the following error:
-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x8b9a7f0
2014-02-26 00:53:57.718 iWish[3311:70b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x8b9a7f0'
The problem is this line:
NSString *anObject = [[dIc objectForKey:#"Name" ] objectAtIndex:1];
The first object in this story, [dIc objectForKey:#"Name" ], is an NSString. You are then saying objectAtIndex:1 to an NSString - and that is a no-no.

NSUserDefaults array not saving properly

I have a problem i cant get my head around. I have an instance of NSUserDefaults and have stored some values in there. One of these values is an array that contains the players scores (its a game) to be used in another display. After the game is finished, I update the array with the new score and reassign it to the NSUserDefaults, but for some reason it doesn't seem to be behaving correctly and in debug when i try to print the count into he console, its always 0.
Here is the code in question:
// // SAMHighScoreInputViewController.m // Tappity // // Created by Sam on 29/05/13. // Copyright (c) 2013 Sam. All rights reserved. //
#import "SAMHighScoreInputViewController.h"
#import "SAMScoreObject.h"
#interface SAMHighScoreInputViewController ()
#end
#implementation SAMHighScoreInputViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self; }
- (void)viewDidLoad {
self.defaults = [NSUserDefaults standardUserDefaults];
self.nameScoreLabel.text = [NSString stringWithFormat:#"%# - %#", [self.defaults objectForKey:#"lastName"], [self.defaults objectForKey:#"lastScore"]];
self.nameTextField.text = [self.defaults objectForKey:#"lastName"];
[super viewDidLoad]; // Do any additional setup after loading the view. }
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated. }
- (IBAction)textFieldValueChanged:(UITextField *)sender {
self.nameScoreLabel.text = [NSString stringWithFormat:#"%# - %#", self.nameTextField.text, [self.defaults objectForKey:#"lastScore"]];
}
- (IBAction)submitButtonTapped:(UIButton *)sender {
SAMScoreObject *score = [[SAMScoreObject alloc] init];
score.playerName = self.nameTextField.text;
score.score = [self.defaults integerForKey:#"lastScore"];
NSArray *scores = [self.defaults objectForKey:#"scoresArray"];
NSMutableArray *updatedArray = [scores mutableCopy];
[updatedArray addObject:score];
NSArray *updatedArrayScores = [updatedArray copy];
[self.defaults setObject:updatedArrayScores forKey:#"scoresArray"];
[self.defaults setObject:[self.defaults objectForKey:#"scoresArray"] forKey:#"scoresArray"];
[self.defaults synchronize];
NSLog(#"%#, %#", [self.defaults objectForKey:#"lastScore"], [self.defaults objectForKey:#"lastName"]);
NSLog(#"%i", [[self.defaults objectForKey:#"scoresArray"] count]);
[self dismissViewControllerAnimated:YES completion:nil];
} #end
You need to serialize your SAMScoreObject into an NSData object of some form before you can store it in the NSUserDefaults store.
From the documentation:
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.
The fact that you're storing an NSArray object isn't good enough, because the objects in that array aren't one of the supported types.
Where is the scoresArray ever created? You should probably lazily create it when you attempt to update it. For example:
NSArray *scores = [self.defaults objectForKey:#"scoresArray"];
if(scores == nil)
{
scores = [NSArray array];
}
NSMutableArray *updatedArray = [scores mutableCopy];

Apparent memory leak in FastEnumeration when deriving from NSMutableDictionary

I have a class that acts as a subclass of NSMutableDictionary (mostly by delegation) as we have some custom interfaces wrapped around a dictionary. When running the ios leak instrument it is identifying my keyEnumerator method as the source of the leak of NSFastEnumerationEnumerator objects.
Here is my keyEnumeration method as a delegate for the wrapped NSMutableDictionary.
- (NSEnumerator*) keyEnumerator {
return [dictionary keyEnumerator];
}
The backtrace for the leak always shows an enumerator as the source:
- (void) someMethod {
for (NSString *key in myWrappedDictionary) { ... }
}
Here is a typical backtrace:
calloc
class_createInstance
__CFAllocateObject2
-[__NSCFDictionary keyEnumerator]
-[WrappedDictionary keyEnumerator]
-[NSDictionary countByEnumerating...
-[SomeClass someMethod]
I'm looking for a workaround or flaw in my one line of code. I'm using ARC.
An example class is shown below. Invoking [WrappedDictionary createLeaks] will create 9 leaks.
#interface WrappedDictionary : NSMutableDictionary {
NSMutableDictionary *dictionary;
}
- (id) init;
- (NSUInteger) count;
- (NSEnumerator*) keyEnumerator;
- (void)setObject:(id)anObject forKey:(id)key;
#end
#implementation WrappedDictionary
- (id) init {
dictionary = [NSMutableDictionary new];
return self;
}
- (NSUInteger) count { return [dictionary count]; }
- (NSEnumerator*) keyEnumerator {
return [dictionary keyEnumerator];
}
- (void)setObject: anObject forKey:key {
[dictionary setObject:anObject forKey: key];
}
+ (void) createLeaks {
for (int i=0; i < 10; i++) {
WrappedDictionary *dict = [WrappedDictionary new];
[dict setObject:#"1" forKey:#"1"];
[dict setObject:#"2" forKey:#"2"];
[dict setObject:#"3" forKey:#"3"];
for (NSString *key in dict) {
NSLog(#"key=%#",key);
}
}
}
#end
Remember, the leaks instrument just shows where a leaked piece of memory is allocated. That doesn't mean that the allocation point is the source of the leak. The more likely source of the leak is in someMethod, or in the caller of someMethod, particularly if you put this into an ivar and then have a retain cycle on the entire object.
I have discovered a simple workaround.
If I change the keyEnumerator method from
- (NSEnumerator*) keyEnumerator {
return [dictionary keyEnumerator];
}
to
- (NSEnumerator*) keyEnumerator {
NSEnumerator *e = [dictionary keyEnumerator];
return e;
}
the leak goes away. This still does not make sense to me but it apparently forces the compiler to ARC properly the return from dictionary.

Objective C memory management issue

I'm having this issue with some objective C code to load the images on a IKImageBrowserView.
I'm following the image browser example from apple, but I still fail at some point and Im guessing its memory management.
Here is some of the code:
/* Our datasource object */
#interface myImageObject : NSObject
{
NSString *_path;
}
#end
#implementation myImageObject
- (void)dealloc
{
[_path release];
[super dealloc];
}
/* our datasource object is just a filepath representation */
- (void)setPath:(NSString *)path
{
NSLog(#"setting path for %#",path);
if(_path != path)
{
[_path release];
_path = [path retain];
}
}
Now, It seems I'm properly retaining the path value within the object.
now on to the controller code:
-(IBAction)loadMosaicImages:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *urls = [openFiles() retain];
NSInteger n;
n = [urls count];
NSURL *url = [urls objectAtIndex:0];
[self parsePathForImages:[url path]];
[urls release];
[pool drain];
}
- (void)updateDatasource
{
NSLog(#" UDS-> _importedImages length : %#",[_importedImages count]);
//-- update our datasource, add recently imported items
[_images addObjectsFromArray:_importedImages];
//-- empty our temporary array
[_importedImages removeAllObjects];
NSLog(#" UDS-> _images length : %#",[_images count]);
//-- reload the image browser and set needs display
[_imageBrowser reloadData];
}
-(void)parsePathForImages:(NSString *)path{
NSLog(#"Directory within thread method is %#",path);
NSArray *content = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
myImageObject *p;
for(int i=0;i<content.count;i++)
{
// NSLog(#"%#",(NSString *)[content objectAtIndex:i]);
NSLog(#"Complete : %#",[path stringByAppendingPathComponent:(NSString *)[content objectAtIndex:i]]);
/* add a path to our temporary array */
p = [[myImageObject alloc] init];
[p setPath:[path stringByAppendingPathComponent:[content objectAtIndex:i]]];
[_importedImages addObject:p];
[p release];
}
[self updateDatasource];
}
and that's all the relevant code. _images and _importedImages are NSMutableArrays alloced and inited in the awake from nib method, and openFiles() is a static method that opens an NSOpenpanel and returns an NSArray of the paths.
the debug output for this does this:
Directory within thread method is /Users/cromestant/Code/images/
Complete : /Users/cromestant/Code/images/1.jpg
setting path for /Users/cromestant/Code/images/1.jpg
Complete : /Users/cromestant/Code/images/2.jpg
setting path for /Users/cromestant/Code/images/2.jpg
Complete : /Users/cromestant/Code/images/3.jpg
setting path for /Users/cromestant/Code/images/3.jpg
.
.
.
then stops crashes at the first line of the method updateDataSource, on the NSLog with an 'EXEC_BAD_ACCESS'so where am I going wrong with the memory management?
I seem to be creating an autoreleasePool so ht I have time to retain somewhere else, I release my objects.. I really don't have a clue where the problem could be.
thanks in advance.
Actually, I think your problem might not be memory management. It might be here:
NSLog(#" UDS-> _importedImages length : %#",[_importedImages count]);
It should be
NSLog(#" UDS-> _importedImages length : %d",[_importedImages count]);
because the count method returns an integer, not an object.