Reputation: 5
AppCommons.h
#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>
@interface AppCommons : NSObject <SKProductsRequestDelegate,SKRequestDelegate>
- (void) getInAppPrice : (NSString *) inAppIdentifier;
@end
AppCommons.m
#import "Config.h"
#import "AppCommons.h"
#import "AppDelegate.h"
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
@implementation AppCommons
SKProductsRequest *productsRequest;
- (void) getInAppPrice : (NSString *) inAppIdentifier {
NSSet *productIdentifiers = [NSSet setWithObject:inAppIdentifier ];
productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
productsRequest.delegate = self;
[productsRequest start];
// we will release the request object in the delegate callback
}
#pragma mark -
#pragma mark SKProductsRequestDelegate methods
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
for(SKProduct *product in response.products)
{
NSLog(@"Product Price : %@",product.price);
NSLog(@"Product Price Locale : %@",product.priceLocale);
}
}
@end
This is my class to get the cost of an in app purchase. I am calling getInAppPrice method from another class using the below lines
AppCommons *appCommon = [[AppCommons alloc] init];
[appCommon getInAppPrice:inAppProductIdentifier];
I am getting following error when response is received
"* -[AppCommons respondsToSelector:]: message sent to deallocated instance 0xd4f0580
Please help .. Thank you.
Upvotes: 0
Views: 804
Reputation: 6211
This is not an answer per se, but an explanation of the reason of the error. The answer given by trojanfoe is absolutely correct, but doesn't exactly explain the situation.
You are calling some function that does:
- (void)myMethod {
AppCommons *appCommon = [[AppCommons alloc] init];
[appCommon getInAppPrice:inAppProductIdentifier];
}
Inside this function you call getInAppPrice
which creates a new object and set's that new object's delegate as your appCommon
. Then that object waits in the background.
Therein lies your problem. While that second object is waiting in the background, your appCommon
object gets released because the code gets to the end of the function and releases appCommon
. If your SKProductsRequest
delegate property were not weak then your appCommon
would still have a retain count of 1, but since it is not then your appCommon
has a retain count of 0 after your function ends, therefore ARC sees the memory as re-usable and frees the object.
Then you get your response in the background from your SKProductsRequest
object. It check's it's delegate pointer (The pointer is still a valid pointer, but it now points to a freed object (or worse, a completely different object)) to see if it responds to the delegate functions. That is when there is a call to a freed object.
So trojanfoe's answer of make the appCommons
object a class variable so that it is retianed past the end of your function is the proper answer.retained
Upvotes: 1
Reputation: 122401
I suspect you are doing that within the scope of a method, like this:
- (void)myMethod {
AppCommons *appCommon = [[AppCommons alloc] init];
[appCommon getInAppPrice:inAppProductIdentifier];
}
which means that appCommon
will be destroyed when the method returns.
Instead make an instance variable or property so that the lifetime of the AppCommons
object lives past this method call.
MyClass.h:
@class AppCommons;
@interface MyClass : NSObject {
AppCommons *_appCommons;
}
...
@end
MyClass.m:
#import "MyClass.h"
#import "AppCommons.h"
@implementation MyClass
- (id)init {
self = [super init];
if (self) {
_appCommons = [[AppCommons alloc] init];
}
return self;
}
- (void)myMethod {
[_appCommons getInAppPrice:inAppProductIdentifier];
}
@end
Upvotes: 2