NSMutableArray to NSDictionary iOS 3.1.3 problem - iphone

I have a problem when I try to run my app on an iOS 3.1.3
I run my app in 4.1 and theres is no problem, but with 3.1.3 my app crash.
My app crash in this line:
NSDictionary *atm= (NSDictionary *)[atmData objectAtIndex:0];
And here is a piece of my code:
DataHelper *mydata = [[DataHelper alloc] init];
NSMutableArray *atmData = [mydata getAllAtmByLocation:appDelegate.userLocation];
if(atmData != nil){
NSDictionary *atm= (NSDictionary *)[atmData objectAtIndex:0];
//...
}
Like I said this issue happens only on iOS 3.1.3, in 4.1 it works perfectly.
Thx for ur help!!

I am guessing you're getting a subscript out of range error. Is it possible that getAllAtmByLocation:is returning an empty array? You might change your conditional to:
if (atmData != nil && [atmData count] > 0) {
...
}

Check your [atmData count] and make sure the array actually contains an element. Maybe whatever you're using to populate the array isn't supported in 3.1.3.

Related

VerificationController unrecognized selector iOS 5.0.1

I just added In-App Purchasing to my iOS app and a few of my users are crashing out with
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xf0a6f10
Obtained from BugSense, the memory location refers to the last line of this excerpt from Apple's VerificationController.m
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
{
if (!(transaction && transaction.transactionReceipt && [transaction.transactionReceipt length] > 0))
{
// Transaction is not valid.
return NO;
}
// Pull the purchase-info out of the transaction receipt, decode it, and save it for later so
// it can be cross checked with the verifyReceipt.
NSDictionary *receiptDict = [self dictionaryFromPlistData:transaction.transactionReceipt];
NSString *transactionPurchaseInfo = [receiptDict objectForKey:#"purchase-info"];
...
receiptDict is generated by this code (also included in VerificationController.m)
- (NSDictionary *)dictionaryFromPlistData:(NSData *)data
{
NSError *error;
NSDictionary *dictionaryParsed = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:nil
error:&error];
if (!dictionaryParsed)
{
if (error)
{
#warning Handle the error here.
}
return nil;
}
return dictionaryParsed;
}
which should return an NSDictionary or nil.
ARC is turned on. This problem seems to only occur with iOS 5.0.1 users. While I did make necessary changes to VerificationController.m, this part has been untouched. I can't seem to replicate the problem on my iPad running iOS 5.1.1, but users have said that it is persistent even after reinstalling the app. If anyone can see something simple that I'm not doing right, I'd appreciate it.
EDIT
Follow up question. What does it mean when
- (BOOL)isTransactionAndItsReceiptValid:(SKPaymentTransaction *)transaction
transaction.transactionReceipt
only provides an NSString and is it safe to ignore?
looks like to me
propertyListWithData:data options:NSPropertyListImmutableformat:nil error:&error];
return a string not a dictionary but it doesnt seems logic. are you sure the problem come from this?

Overriding description method for NSObject

I'm not sure if this is a simulator issue, but I don't remeber having this problem before when I was using the iPad 5.0 simulator and below (now I'm running iPad 5.1 simulator). I overrode the description method for my Condition object to be:
- (NSString *)description {
NSString *str = [[NSString alloc] initWithFormat:#"Condition: %#", _conditionName];
return [str autorelease];
}
I have an array of these objects. My values are all valid. When I do:
for (Condition *p in self.reportsArray) {
NSLog(#"%#", [p description]);
}
It logs all my values, and then it crashes at the end. When I look at Instruments with Zombies, the last 4 calls are
-[NSPlaceHolderString initWithBytes:length:encoding:]
+[NSString stringWithUTF8String:]
-[NSAutoreleasePool release]
-[NSPlaceholderString initWithFormat:locale:arguments:]
Am I overriding description correctly?
Edit:
In Instruments, I get: message was sent to a deallocated object (zombie) at address:0x8ccf190. On the app itself, I get EXC_BAD_ACCESS.
It seems like the string returned from your description method is being released too soon.
Try rewriting your method using the stringWithFormat: class method.
- (NSString *)description {
return [NSString stringWithFormat:#"Condition: %#", _conditionName];
}
Make sure _conditionName is not a primitive.
Because the format string "%#" expects an object.

How to determine if plist contains NSDictionary or NSMutableArray?

I may be phrasing the question incorrectly based on my situation - sorry if that's the case.
Here's the issue: In a previous version of my app, I'm saving an NSMutableArray to a plist using NSCoding.
In a new version, I've added settings data, so I now put the previous array and the new data in an NSDictionary then use NSCoding. Works fine.
However, for this release, I'll have to determine if an existing plist is the old version (NSMutableArray) or the new one (NSDictionary).
The basic code is this:
NSData *codedData=[[NSData alloc] initWithContentsOfFile:plistPath];
//EITHER this (array): allMsgs=[NSKeyedUnarchiver unarchiveObjectWithData:codedData];
//OR this (nsdict): tmpdict=(NSDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:codedData];
How can I read the plist and determine if it's an NSDictionary or NSMutableArray without throwing errors?
Just store the unarchived object as an id, then use isKindOfClass: to check its class:
id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:codedData];
if ([unarchivedObject isKindOfClass:[NSArray class]]) {
// do something
} else if ([unarchivedObject isKindOfClass:[NSDictionary class]]) {
// do something else
}

App crashing because of glGetString

I am running cocos2d-iphone 1.0.0 and following this tutorial to use cocos2d with ARC. Unfortunately, I am getting a 'SIGABRT' crash error whenever I try to add a TMX Tiled Map to a CCLayer. I have traced this problem down to the -(BOOL)checkForGLExtension:(NSString *)searchName, and even further to within this function to NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding];
Here is the checkForGLExtension function:
- (BOOL) checkForGLExtension:(NSString *)searchName {
// For best results, extensionsNames should be stored in your renderer so that it does not
// need to be recreated on each invocation.
NSLog(#"%#", glExtensions);
NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding];
NSLog(#"%#", extensionsString);
NSArray *extensionsNames = [extensionsString componentsSeparatedByString:#" "]; }
The encoding: part of NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding];is probably making the application crash. I am also receiving NULL in my logs for GL_VENDOR, GL_VERSION, GL_RENDERER, and even glExtensions.
Looking back at gl.h in the OpenGLES.framework shows me this:
/* StringName */
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
#define GL_VERSION 0x1F02
#define GL_EXTENSIONS 0x1F03
In which all of them are NULL.
NOTE: I have no idea about iOS development :)
Getting NULL from glGetString usually means that the OpenGL context is not bound or was created incorrectly. You should check that. Also check for GL error with glGetError.

Stumped: property list works in simulator and in other Apps, but not when I test on the iphone 4

I'm working on an app that writes data out to a .plist from a view and then pulls it in to populate some UILabels in another view. I've done this several times in the past and it has worked fine on both the device and simulator. This time it's working fine on the simulator but not on the device. I've been through looking at all the connections and code but just can't find why it's not functioning. My suspicion is that for some reason the data is not at the end of the file path, but if it isn't I can't understand why this is the case.
I've Also tried cleaning the targets through the menu and deleting and reinstalling the app on the testing device in the hope that this may rectify the situation, but no joy.
Can anyone offer some insight into why I'm having this problem and how to rectify it? It's why it works on the simulator but not the phone that is confusing me, especially when I've used the same code in the past to make fully functioning apps. I'm using xCode 4 and testing on an iphone 4:
The code is as follows. First I check to see if there is data at the end of a data file path like this:
- (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirctory = [paths objectAtIndex:0];
return [documentsDirctory stringByAppendingPathComponent:memberDetails];
}
Then in viewWillAppear I get the data and use it to populate UIlabels in the View. a Few of the labels are visible or invisible based on the data they contain. The viewWillAppear is as follows:
-(void)viewWillAppear:(BOOL)animated
{
// Check data file path and if it exists, load data from there.
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
///All of the following handles the reloading of data from the plist.
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
memName.text = [array objectAtIndex:0];
memAddress.text = [array objectAtIndex:1];
memOccupation.text = [array objectAtIndex:2];
sherex.text = [array objectAtIndex:3];
if ([[array objectAtIndex:3] isEqualToString:#"winstonwinston"]) {
cvName.hidden = NO;
memName.hidden = NO;
cvAddress.hidden = NO;
memAddress.hidden = NO;
cvOccupation.hidden = NO;
memOccupation.hidden = NO;
sherex.hidden = YES;
altText.hidden = YES;
}
else {
cvName.hidden = YES;
memName.hidden = YES;
cvAddress.hidden = YES;
memAddress.hidden = YES;
cvOccupation.hidden = YES;
memOccupation.hidden = YES;
sherex.hidden = YES;
altText.hidden = NO;
}
[array release];
}
[super viewWillAppear:animated];
}
One thing perhaps worth pointing out is that the if/else statement doesn't seem to be working on the device either. In other words everything in the view is visible. To me this would seem to suggest that the problem might not be the data since if should be able to determine whether or not there is an item called 'winstonwintson' in existence or not and display the hidden/showing elements of the view accordingly.
If anyone has some insight please help! I'm totally stuck. Thanks for taking the time to read this.
If it involves files and works on the simulator but not on the device it's usually one of two problems.
you use filenames that work ok on a case insensitive file system (the simulator) but not on the device (case sensitive filesystem).
The only way I can imagine how this affects you is when you try to copy an initial dataset to the documents directory. For example if you try to copy from your bundle, check the path that is returned by [[NSBundle mainBundle] pathForResource:#"foo" ofType:#"bar"]; If the path is nil you have to check your filenames again, they have to be exactly the same.
you write to directories that are not writeable on the device.
One very unlikely possibility is that memberDetails contains something like /../foo and you try to write in a non writeable directory. On the simulator you can write your files wherever you want, on the device such accesses will fail.
So the two questions you should try to answer are:
how do you save the data in the documents directory?
what is the content of memberDetails? (how does the returned path from dataFilePath look?)
EDIT:
NSLog is always a great help in debugging such problems, just print out your paths and check if they are ok.
Something like this:
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"foo" ofType:#"bar"];
NSLog(#"Source: %#", sourcePath);
if (![[NSFileManager...
or you could use a if condition
if (sourcePath == nil) {
NSLog(#"Something is wrong with the sourcePath, because sourcePath == nil!");
}
EDIT2:
Since neither of those view configuring parts are called most likely if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) is never true. This means the file does not exist.
Delete app from phone, clean project, re-build and run. It is sometimes helpful to turn off backgrounding, to do that add:
<key>UIApplicationExitsOnSuspend</key><true/>
to your app plist.