Multiple sharedInstance called failed - iphone

In my application i have called sharedinstance multiple time in multiple method deffinition ,
Here my code,
Method 1
-(void) showActionSheet:(id)sender forEvent:(UIEvent*)event
{
if(isQuantity==YES)
{
[[WebService sharedInstance] getQuantity:^(BOOL result)
{
if(result)
{
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
Quantity = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:TRUE withPredicate:nil];
NSLog(#"array ->%#",Quantity);
isQuantity=NO;
}
}];
}
popoverController1 = [[TSPopoverController alloc]initWithContentViewController:tableViewController1];
popoverController1.cornerRadius = 5;
popoverController1.titleText = #"Quantity";
popoverController1.popoverBaseColor = [UIColor blackColor];
popoverController1.popoverGradient= NO;
[popoverController1 showPopoverWithTouch:event];
}
Method 2
-(void) showActionSheetw:(id)sender forEvent:(UIEvent*)events
{
if(isSize==YES)
{
[[WebService sharedInstance] getDimension:^(BOOL result)
{
if(result){
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
dime = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
NSLog(#"array ->%#",dime);
}
}];
}
popoverController2 = [[TSPopoverController alloc] initWithContentViewController:tableViewController2];
popoverController2.cornerRadius = 5;
popoverController2.titleText = #"Size";
popoverController2.popoverBaseColor = [UIColor blackColor];
popoverController2.popoverGradient= NO;
// popoverController.arrowPosition = TSPopoverArrowPositionHorizontal;
[popoverController2 showPopoverWithTouch:events];
}
EDIT
- (void) getDimension:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETDIMENSION param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"Dimension Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetDimensionResult"];
NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
Getdimension *userDetails = [Getdimension newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
- (void) getQuantity:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETQUANTITY param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"GetQuantityResult Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetQuantityResult"];
// NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
GetQuantity *userDetails = [GetQuantity newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
Instance method
+ (id)sharedInstance
{
#synchronized(self)
{
if (manager == nil)
manager = [[self alloc] init];
}
return manager;
}
-(id)init
{
if(self = [super init])
{
}
return self;
}
-(NSString *)NSStringFromDictionaryUsingJSON:(id)dictionary
{
SBJsonWriter *writer = [[SBJsonWriter alloc]init];
return [writer stringWithObject:dictionary];
}
-(id)DictionaryFromResponse:(NSData *)response
{
NSString *responseBody = [[NSString alloc] initWithData:response encoding:NSASCIIStringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc]init];
return [parser objectWithString:responseBody error:nil];
}
sharedInstance only works one time,ie,. if i call any of the method first its worked,if calls other method second time app gets crashed.Can any one please help me to sort it out

I guess sharedInstance method is messy.
It should be
+ (id)sharedInstance
{
if (manager == nil)
manager = [[self alloc] init];
return manager;
}
Enjoy Programming !

Have you declared instance of your class as static,
Declare you class object as :
static ClassName *manager;
And the allocate the same object in your sharedInstance method.
The reason may be that the memory object was released but reference is still there in the memory.So when you execute the shared instance method it found a reference to !nil object and leads your application to crash.
This is singleton class feature of iOS(objective C)

Related

Syncing Data with Parse, not downloading data

I have been following the How To Synchronize Core Data with a Web Service – Part 1 from RayWenderlinch.com I am trying to customize it to my application and have an issue with the actual downloading of the data from Parse using AFNetworking
The application should connect to parse, see the two classes "Club" and "IronSet" check and see if there are and new records (or on initial run, grab everything) and download only the newly added stuff.
Then it will save those records to core data, then delete the files from the Cache/JSONRecords/Club(or IronSet). It seems I am never actually grabbing the data from Parse, although it is connecting successfully, and does not throw an error until it goes to delete the the files from the Cache.
I am getting the "All operations completed" indicating the SyncEngine should be complete with the download in the downloadDataForRegisteredObjects
Error
2013-08-26 19:39:03.981 WGT Golf Calculator[3287:c07] All operations completed
2013-08-26 19:39:03.991 WGT Golf Calculator[3287:c07] Unable to delete JSON records at Club -- file://localhost/Users/**/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/, reason Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be completed. (Cocoa error 4.)" UserInfo=0x75610f0 {NSUnderlyingError=0x75615e0 "The operation couldn’t be completed. No such file or directory", NSFilePath=/Users/**/Library/Application Support/iPhone Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/Club, NSUserStringVariant=(
Remove
)}
MLVAppDelegate.m
#import "MLVAppDelegate.h"
#import "MLVSyncEngine.h"
#import "Club.h"
#import "IronSet.h"
#implementation MLVAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[Club class]];
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[IronSet class]];
return YES;
}
MLVAFParseAPIClient.h
#import "AFHTTPClient.h"
#interface MLVAFParseAPIClient : AFHTTPClient
+ (MLVAFParseAPIClient *)sharedClient;
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters;
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate;
#end
MLVAFParseAPIClient.m
#import "MLVAFParseAPIClient.h"
#import "AFJSONRequestOperation.h"
static NSString * const kSDFParseAPIBaseURLString = #"https://api.parse.com/1/";
static NSString * const kSDFParseAPIApplicationId = #"APP ID REMOVED";
static NSString * const kSDFParseAPIKey = #"API KEY REMOVED";
#implementation MLVAFParseAPIClient
+ (MLVAFParseAPIClient *)sharedClient
{
static MLVAFParseAPIClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{sharedClient = [[MLVAFParseAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kSDFParseAPIBaseURLString]];
});
return sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setParameterEncoding:AFJSONParameterEncoding];
[self setDefaultHeader:#"X-Parse-Application-Id" value:kSDFParseAPIApplicationId];
[self setDefaultHeader:#"X-Parse-REST-API-Key" value:kSDFParseAPIKey];
}
return self;
}
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = nil;
request = [self requestWithMethod:#"GET" path:[NSString stringWithFormat:#"classes/%#", className] parameters:parameters ];
return request;
}
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate
{
NSMutableURLRequest *request = nil;
NSDictionary *parameters = nil;
if (updatedDate) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.'999Z'"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSString *jsonString = [NSString stringWithFormat:#"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}}", [dateFormatter stringFromDate:updatedDate]];
parameters = [NSDictionary dictionaryWithObject:jsonString forKey:#"where"];
}
request = [self GETRequestForClass:className parameters:parameters];
return request;
}
#end
MLVCoreDataController.m
#import "MLVCoreDataController.h"
#interface MLVCoreDataController ()
#property (strong, nonatomic) NSManagedObjectContext *masterManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectContext *backgroundManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#end
#implementation MLVCoreDataController
#synthesize masterManagedObjectContext = _masterManagedObjectContext;
#synthesize backgroundManagedObjectContext = _backgroundManagedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (id)sharedInstance {
static dispatch_once_t once;
static MLVCoreDataController *sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma mark - Core Data stack
// Used to propegate saves to the persistent store (disk) without blocking the UI
- (NSManagedObjectContext *)masterManagedObjectContext {
if (_masterManagedObjectContext != nil) {
return _masterManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_masterManagedObjectContext performBlockAndWait:^{
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
}];
}
return _masterManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)backgroundManagedObjectContext {
if (_backgroundManagedObjectContext != nil) {
return _backgroundManagedObjectContext;
}
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
_backgroundManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundManagedObjectContext performBlockAndWait:^{
[_backgroundManagedObjectContext setParentContext:masterContext];
}];
}
return _backgroundManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)newManagedObjectContext {
NSManagedObjectContext *newContext = nil;
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[newContext performBlockAndWait:^{
[newContext setParentContext:masterContext];
}];
}
return newContext;
}
- (void)saveMasterContext {
[self.masterManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.masterManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save master context due to %#", error);
}
}];
}
- (void)saveBackgroundContext {
[self.backgroundManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.backgroundManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save background context due to %#", error);
}
}];
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"WGTCalculator" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"WGTCalcul.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
MLVSyncEngine.h
#import <Foundation/Foundation.h>
typedef enum {
MLVObjectSynced = 0,
MLVObjectCreated,
MLVObjectDeleted,
} MLVObjectSyncStatus;
#interface MLVSyncEngine : NSObject
#property (atomic, readonly) BOOL syncInProgress;
+ (MLVSyncEngine *)sharedEngine;
- (void)registerNSManagedObjectClassToSync:(Class)aClass;
- (void)startSync;
#end
MLVSyncEngine.m
#import "MLVSyncEngine.h"
#import "MLVCoreDataController.h"
#import "MLVAFParseAPIClient.h"
#import "AFHTTPRequestOperation.h"
#import "AFJSONRequestOperation.h"
NSString * const kMLVSyncEngineInitialCompleteKey = #"MLVSyncEngineInitialSyncCompleted";
NSString * const kMLVSyncEngineSyncCompletedNotificationName = #"MLVSyncEngineSyncCompleted";
#interface MLVSyncEngine ()
#property (nonatomic, strong) NSMutableArray *registeredClassesToSync;
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#end
#implementation MLVSyncEngine
#synthesize registeredClassesToSync = _registeredClassesToSync;
#synthesize syncInProgress = _syncInProgress;
#synthesize dateFormatter = _dateFormatter;
+ (MLVSyncEngine *)sharedEngine
{
static MLVSyncEngine *sharedEngine = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedEngine = [[MLVSyncEngine alloc] init];
});
return sharedEngine;
}
- (void)registerNSManagedObjectClassToSync:(Class)aClass
{
if (!self.registeredClassesToSync) {
self.registeredClassesToSync = [NSMutableArray array];
}
if ([aClass isSubclassOfClass:[NSManagedObject class]]) {
if (![self.registeredClassesToSync containsObject:NSStringFromClass(aClass)]) {
[self.registeredClassesToSync addObject:NSStringFromClass(aClass)];
} else {
NSLog(#"Unable to register %# as it is already registered", NSStringFromClass(aClass));
}
} else {
NSLog(#"Unable to reguster %# as it is not a subclass of NSManagedObject", NSStringFromClass(aClass));
}
}
- (BOOL)initialSyncComplete{
return [[[NSUserDefaults standardUserDefaults] valueForKey:kMLVSyncEngineInitialCompleteKey] boolValue];
}
- (void)setInitialSyncCompleted{
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kMLVSyncEngineInitialCompleteKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)executeSyncCompletedOperations {
dispatch_async(dispatch_get_main_queue(), ^{
[self setInitialSyncCompleted];
NSError *error = nil;
[[MLVCoreDataController sharedInstance] saveBackgroundContext];
if (error) {
NSLog(#"Error saving background context after creating objects on server: %#", error);
}
[[MLVCoreDataController sharedInstance] saveMasterContext];
[[NSNotificationCenter defaultCenter]
postNotificationName:kMLVSyncEngineSyncCompletedNotificationName
object:nil];
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = NO;
[self didChangeValueForKey:#"syncInProgress"];
});
}
- (void)startSync
{
if (!self.syncInProgress) {
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = YES;
[self didChangeValueForKey:#"syncInProgress"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{[self downloadDataForRegisteredObjects:YES];
});
}
}
- (NSDate *)mostRecentUpdatedAtDateForEntityWithName:(NSString *)entityName {
__block NSDate *date = nil;
//
// Create a new fetch request for the specified entity
//
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
//
// Set the sort descriptors on the request to sort by updatedAt in descending order
//
[request setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"updatedAt" ascending:NO]]];
//
// You are only interested in 1 result so limit the request to 1
//
[request setFetchLimit:1];
[[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] performBlockAndWait:^{
NSError *error = nil;
NSArray *results = [[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] executeFetchRequest:request error:&error];
if ([results lastObject]) {
//
// Set date to the fetched result
//
date = [[results lastObject] valueForKey:#"updatedAt"];
}
}];
return date;
}
- (void)newManagedObjectWithClassName:(NSString *)className forRecord:(NSDictionary *)record {
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:className inManagedObjectContext:[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext]];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:newManagedObject];
}];
[record setValue:[NSNumber numberWithInt:MLVObjectSynced] forKey:#"syncStatus"];
}
- (void)updateManagedObject:(NSManagedObject *)managedObject withRecord:(NSDictionary *)record {
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:managedObject];
}];
}
- (void)setValue:(id)value forKey:(NSString *)key forManagedObject:(NSManagedObject *)managedObject {
if ([key isEqualToString:#"createdAt"] || [key isEqualToString:#"updatedAt"]) {
NSDate *date = [self dateUsingStringFromAPI:value];
[managedObject setValue:date forKey:key];
} else if ([value isKindOfClass:[NSDictionary class]]) {
if ([value objectForKey:#"__type"]) {
NSString *dataType = [value objectForKey:#"__type"];
if ([dataType isEqualToString:#"Date"]) {
NSString *dateString = [value objectForKey:#"iso"];
NSDate *date = [self dateUsingStringFromAPI:dateString];
[managedObject setValue:date forKey:key];
} else if ([dataType isEqualToString:#"File"]) {
NSString *urlString = [value objectForKey:#"url"];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[managedObject setValue:dataResponse forKey:key];
} else {
NSLog(#"Unknown Data Type Received");
[managedObject setValue:nil forKey:key];
}
}
} else {
[managedObject setValue:value forKey:key];
}
}
- (NSArray *)managedObjectsForClass:(NSString *)className withSyncStatus:(MLVObjectSyncStatus)syncStatus {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"syncStatus = %d", syncStatus];
[fetchRequest setPredicate:predicate];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate;
if (inIds) {
predicate = [NSPredicate predicateWithFormat:#"objectId IN %#", idArray];
} else {
predicate = [NSPredicate predicateWithFormat:#"NOT (objectId IN %#)", idArray];
}
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"objectId" ascending:YES]]];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (void)downloadDataForRegisteredObjects:(BOOL)useUpdatedAtDate {
NSMutableArray *operations = [NSMutableArray array];
for (NSString *className in self.registeredClassesToSync) {
NSDate *mostRecentUpdatedDate = nil;
if (useUpdatedAtDate) {
mostRecentUpdatedDate = [self mostRecentUpdatedAtDateForEntityWithName:className];
}
NSMutableURLRequest *request = [[MLVAFParseAPIClient sharedClient]
GETRequestForAllRecordsOfClass:className
updatedAfterDate:mostRecentUpdatedDate];
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Request for class %# failed with error: %#", className, error);
}];
[operations addObject:operation];
}
[[MLVAFParseAPIClient sharedClient] enqueueBatchOfHTTPRequestOperations:operations progressBlock:^(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations) {
} completionBlock:^(NSArray *operations) {
NSLog(#"All operations completed");
[self processJSONDataRecordsIntoCoreData];
}];
}
- (void)processJSONDataRecordsIntoCoreData {
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
//
// Iterate over all registered classes to sync
//
for (NSString *className in self.registeredClassesToSync) {
if (![self initialSyncComplete]) {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
for (NSDictionary *record in records) {
[self newManagedObjectWithClassName:className forRecord:record];
}
} else {
NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:#"objectId"];
if ([downloadedRecords lastObject]) {
NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:#"objectId" usingArrayOfIds:[downloadedRecords valueForKey:#"objectId"] inArrayOfIds:YES];
int currentIndex = 0;
for (NSDictionary *record in downloadedRecords) {
NSManagedObject *storedManagedObject = nil;
if ([storedRecords count] > currentIndex) {
storedManagedObject = [storedRecords objectAtIndex:currentIndex];
}
if ([[storedManagedObject valueForKey:#"objectId"] isEqualToString:[record valueForKey:#"objectId"]]) {
[self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
} else {
[self newManagedObjectWithClassName:className forRecord:record];
}
currentIndex++;
}
}
}
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"Unable to save context for class %#", className);
}
}];
[self deleteJSONDataRecordsForClassWithName:className];
[self executeSyncCompletedOperations];
}
}
- (void)initializeDateFormatter {
if (!self.dateFormatter) {
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
[self.dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
}
}
- (NSDate *)dateUsingStringFromAPI:(NSString *)dateString {
[self initializeDateFormatter];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-5)];
return [self.dateFormatter dateFromString:dateString];
}
- (NSString *)dateStringForAPIUsingDate:(NSDate *)date {
[self initializeDateFormatter];
NSString *dateString = [self.dateFormatter stringFromDate:date];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-1)];
dateString = [dateString stringByAppendingFormat:#".000Z"];
return dateString;
}
#pragma mark - File Management
- (NSURL *)applicationCacheDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSURL *)JSONDataRecordsDirectory{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *url = [NSURL URLWithString:#"JSONRecords/" relativeToURL:[self applicationCacheDirectory]];
NSError *error = nil;
if (![fileManager fileExistsAtPath:[url path]]) {
[fileManager createDirectoryAtPath:[url path] withIntermediateDirectories:YES attributes:nil error:&error];
}
return url;
}
-(void)writeJSONResponse:(id)response toDiskForClassWithName:(NSString *)className{
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]] ;
if (![(NSDictionary *)response writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Error saving response to disk, will attempt to remove NSNull values and try again.");
//remove NSNulls and try again...
NSArray *records = [response objectForKey:#"results"];
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (NSDictionary *record in records) {
NSMutableDictionary *nullFreeRecord = [NSMutableDictionary dictionaryWithDictionary:record];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]]) {
[nullFreeRecord setValue:nil forKey:key];
}
}];
[nullFreeRecords addObject:nullFreeRecord];
}
NSDictionary *nullFreeDictionary = [NSDictionary dictionaryWithObject:nullFreeRecords forKey:#"results"];
if (![nullFreeDictionary writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Failed all attempts to save response to disk: %#", response);
}
}
}
- (void)deleteJSONDataRecordsForClassWithName:(NSString *)className {
NSURL *url = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
NSError *error = nil;
BOOL deleted = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (!deleted) {
NSLog(#"Unable to delete JSON records at %#, reason %#", url, error);
}
}
- (NSDictionary *)JSONDictionaryForClassWithName:(NSString *)className {
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
return [NSDictionary dictionaryWithContentsOfURL:fileURL];
}
- (NSArray *)JSONDataRecordsForClass:(NSString *)className sortedByKey:(NSString *)key {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
return [records sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:key ascending:YES]]];
}
#end
Honestly, if your data model is that simple, and you're deleting the local persistent store / cache on every load, you probably would be much better off not using Core Data.
Keep it simple by loading data as needed. Save a cache using NSCoding, to be loaded initially as a placeholder, while the app waits for new information to be downloaded.
So it turns out the answer was pretty straight forward, the tutorial uses an older Version of AFNetworking where AFHTTPRequestOperation can download the data but does not see it as JSON.
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
}
Needed to be updated with AFJSONRequestOperation
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSDictionary * responseObject = (NSDictionary * )JSON;
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSLog(#"Response for %#: %#", className, responseObject);
[self writeJSONResponse:responseObject toDiskForClassWithName:className];

CoreData inserting very huge DB exc_bad_access

I have ~60000 values in my DB.
I must to keep them all. But while inserting values I get exc_bad_access.
Here is my code:
if (context == nil)
{
context = [(radioAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", context);
}
[self performSelectorOnMainThread:#selector(deleteAllFromDB) withObject:nil waitUntilDone:YES];
// here is JSON parsing
int i=0;
#synchronized(self)
{
NSLog(#"Start");
NSEntityDescription *entity = [[NSEntityDescription entityForName:#"Station" inManagedObjectContext:context] autorelease];
for (NSString*string in stations)
{
if (![string isEqualToString:#""])
{
Station*station = [[[Station alloc] initWithEntity:entity insertIntoManagedObjectContext:nil] retain];
NSError *err = nil;
id parsedData = [NSJSONSerialization JSONObjectWithData:[string dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers error:&err];
if (err) {
NSLog(#"error is %#", [err localizedDescription]);
}
[station setName:[parsedData objectForKey:#"nm"]];
[station setBit: [parsedData objectForKey:#"btr"]];
[station setEnabled: [NSNumber numberWithInt:1]];
//encoding id of the station
scanner = [NSScanner scannerWithString:[parsedData objectForKey:#"id"]];
[scanner scanHexInt:&tempInt];
NSNumber *numb = [[NSNumber alloc]initWithInt:i];
[station setNumber: [NSNumber numberWithInt:[numb intValue]]];
//encoding country ID
numb = [NSNumber numberWithInt:i];
[station setCountryID: [NSNumber numberWithInt:[numb intValue]]];
//encoding genre ID
numb = [NSNumber numberWithInt:i];
[station setGenerID:[NSNumber numberWithInt:[numb intValue]]];
[station setOrder:[NSNumber numberWithInt:i]];
[context insertObject:station];
float k = [stations count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
i++;
[scanner release];
[numb release];
[station release];
[parsedData release];
}
}
[context save:nil];
[entity release];
NSLog(#"Stop");
NSEntityDescription *entityGen = [NSEntityDescription entityForName:#"Genre" inManagedObjectContext:context];
NSURL* urlForGenre = [NSURL URLWithString:#"xxx.xxx"];
NSData *genres = [[NSData alloc] initWithContentsOfURL:urlForGenre];
NSError *err = nil;
NSArray *parsedGenres = [NSJSONSerialization JSONObjectWithData:genres options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
for (int i =0; i<parsedGenres.count; i++)
{
Genre*gen = [[Genre alloc] initWithEntity:entityGen insertIntoManagedObjectContext:nil];
gen.name = [[parsedGenres objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedGenres objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
gen.number = [NSNumber numberWithInt:[numb integerValue]];
float k = [parsedGenres count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:gen];
[gen release];
}
[entityGen release];
[context save:nil];
NSEntityDescription *entityCon = [NSEntityDescription entityForName:#"Country" inManagedObjectContext:context];
NSURL* urlForCoun = [NSURL URLWithString:#"yyy.yyy"];
NSData *countr = [[NSData alloc] initWithContentsOfURL:urlForCoun];
err = nil;
NSArray *parsedCountr = [NSJSONSerialization JSONObjectWithData:countr options:NSJSONReadingMutableContainers error:&err];
if (err)
{
NSLog(#"error is %#", [err localizedDescription]);
}
NSMutableArray* temp = [[NSMutableArray alloc] init];
for (int i =0; i<parsedCountr.count; i++)
{
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
countr.name = [[parsedCountr objectAtIndex:i] objectForKey:#"nm"];
int tempInt;
NSScanner *scanner= [[NSScanner alloc] init];
scanner = [NSScanner scannerWithString:[[parsedCountr objectAtIndex:i] objectForKey:#"id"]];
[scanner scanInt:&tempInt];
NSNumber *numb = [[NSNumber alloc] init];
numb = [NSNumber numberWithInt:tempInt];
countr.number = [NSNumber numberWithInt:[numb integerValue]];
[temp addObject:countr];
float k = [parsedCountr count];
k = (i + 1)/k;
[self performSelectorOnMainThread:#selector(increaseProgress:) withObject:[NSNumber numberWithFloat:k] waitUntilDone:YES];
[context insertObject:countr];
[countr release];
}
[context save:nil];
If my app doesn't crash, yes, it happens not by every launch. It crashes on:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Please help! And sorry for my terrible English.
Update:
On:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
Thread 7: EXC_BAD_ACCESS (code=1, address=0x3f800008)
Other error is exc_bad_access too. But with code=2 and on other thread.
Update 2:
I enabled zombies mode in scheme of my debug. Nothing happened.
Update 3:
I think I have problems with memory.
GuardMalloc: Failed to VM allocate 4128 bytes
GuardMalloc: Explicitly trapping into debugger!!!
You can't pass nil as managedObjectContext parameter to initWithEntity:insertIntoManagedObjectContext: method. Try changing this:
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:nil];
to this
// pass managed object context parameter
Country*countr = [countr initWithEntity:entityCon insertIntoManagedObjectContext:context];
Based on the documentation and my experience you can pass nil as managedObjectContext.
I was also getting an EXC_BAD_ACCESS and it came that the reason was that I was not retaining the managed object model(I was only creating a model to get the entity description and then it was released).
In particular, this is what I was doing:
In a test class, in the setUp method:
- (void)setUp
{
[super setUp];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSURL *modelURL = [bundle URLForResource:#"TestDatamodel" withExtension:#"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
STAssertNotNil(model, nil);
_entity = [[model entitiesByName] objectForKey:NSStringFromClass([MyEntity class])];
STAssertNotNil(_entity, nil);
// ...
}
Then in a test method I was creating a managed object without a context like this:
NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:_entity insertIntoManagedObjectContext:nil];
And I was getting EXC_BAD_ACCESS here.
The solution was to add an ivar to the test class to keep a reference to the managed object model.

How to get cookies and use them for other requests like POST ( iOS )?

My previous question was about the problem that I have to login each time for doing web services like posting a link or uploading a picture. Philipe answered that I have to use cookies instead of login process for each request. I found this method for getting cookies:
- (void)getCookies {
NSHTTPURLResponse * response;
NSError * error;
NSMutableURLRequest *request;
request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://MyWebsite.com/login.php"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:120];
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"%#", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:#"http://MyWebsite.com/login.php"]];
NSLog(#"%d", all.count);
for (NSHTTPCookie *cookie in all) {
NSLog(#"Name: %# : Value: %#", cookie.name, cookie.value);
NSLog(#"Comment: %# : CommentURL: %#", cookie.comment, cookie.commentURL);
NSLog(#"Domain: %# : ExpiresDate: %#", cookie.domain, cookie.expiresDate);
NSLog(#"isHTTPOnly: %c : isSecure: %c", cookie.isHTTPOnly, cookie.isSecure);
NSLog(#"isSessionOnly: %c : path: %#", cookie.isSessionOnly, cookie.path);
NSLog(#"portList: %# : properties: %#", cookie.portList, cookie.properties);
NSLog(#"version: %u", cookie.version);
}
}
I also found this code to use these cookies, but I'm not sure how to use it:
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookies];
Here is my method for POSTing, I am using RestKit API:
- (IBAction)addLinkPressed:(UIButton *)sender {
[RKClient clientWithBaseURLString:#"http://MyWebsite.com"];
NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
self.linkField.text, #"url",
self.linkTitleField.text, #"title",
self.linkSummaryField.text, #"summary",
nil];
RKRequest *request = [[RKClient sharedClient] post:#"/send_link.php" params:params delegate:self];
[request setUserData:#"sendLink"];
}
Question: Which property of cookies should I store to use it for login information and where should I put it in my code?
I solved this issue by some inefficient way. Here is my methodology:
First I try to post to the web service and after posting I parse the returning HTML to see if the posting was successful or not. If posting was successful I give an appropriate message to the user that you post successfully but if it was not successful it could have two reasons: First: there were some error during the post execution Second: the user was not logged in. The way that I recognize the differentiation between fist and second error is just parsing the response HTML.
Here is the code that I used for this methodology (this is for the time that the user wants to change the password)
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
NSRange range = [[error localizedDescription] rangeOfString:#"-1012"];
if (range.length > 0){
//First error occurs here
}
RKLogError(#"Hit error: %#", error);
}
- (IBAction)requestToChangePasswordPressed {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
[RKClient clientWithBaseURLString:#"http://WebServiceDomain.com"];
NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
self.oldPasswordField.text, #"oldPassword",
self.passwordNew.text, #"newPassword",
self.confirmPasswordField.text, #"confirmPassword",
nil];
RKRequest *request = [[RKClient sharedClient] post:#"/change_password.php" params:params delegate:self];
[request setUserData:#"changePassword"];
[self.view endEditing:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
- (void)autoLogin {
[RKClient clientWithBaseURLString:#"http://WebServiceDomain.com"];
[RKObjectManager sharedManager].client=[RKClient sharedClient];
RKParams *parameters = [RKParams params];
[parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:#"defaultUsername"] forParam:#"username"];
[parameters setValue:[[NSUserDefaults standardUserDefaults] objectForKey:#"defaultPassword"] forParam:#"password"];
[[RKClient sharedClient] setAuthenticationType:RKRequestAuthenticationTypeHTTP];
// because we have two POSTs and we want to use the same method for both of the for didLoadResponse: we set the UserDate like bellow
RKRequest *request = [[RKClient sharedClient] post:#"/login.php" params:parameters delegate:self];
[request setUserData:#"login"];
}
- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response
{
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
id userData = [request userData];
if ([userData isEqual:#"login"]) {
if ([request isGET]) {
// Handling GET /foo.xml
if ([response isOK]) {
// Success! Let's take a look at the data
NSLog(#"Retrieved XML: %#", [response bodyAsString]);
}
} else if ([request isPOST]) {
// Handling POST /other.json
if ([response isJSON]) {
NSLog(#"Got a JSON response back from our POST!");
}
} else if ([request isDELETE]) {
// Handling DELETE /missing_resource.txt
if ([response isNotFound]) {
NSLog(#"The resource path '%#' was not found.", [request resourcePath]);
}
}
}
else if ([userData isEqual:#"sendLink"]) {
NSData *addLinksHtmlData = response.body;
// 2
TFHpple *addlinksParser = [TFHpple hppleWithHTMLData:addLinksHtmlData];
// 3
NSString *errorLinksXpathQueryString = #"//div[#class='errorBox']/ul/li";
NSArray *errorLinksNodes = [addlinksParser searchWithXPathQuery:errorLinksXpathQueryString];
// 4
NSMutableArray *newErrorLinks = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in errorLinksNodes) {
// 5
AllModels *errorTitle = [[AllModels alloc] init];
[newErrorLinks addObject:errorTitle];
// 6
errorTitle.errorTitle = [[element firstChild] content];
}
// 8
self.linkErrorObjects = newErrorLinks;
NSString *successLinksXpathQueryString = #"//div[#class='successBox']";
NSArray *successLinksNodes = [addlinksParser searchWithXPathQuery:successLinksXpathQueryString];
// 4
NSMutableArray *newSuccessLinks = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in successLinksNodes) {
// 5
AllModels *successTitle = [[AllModels alloc] init];
[newSuccessLinks addObject:successTitle];
// 6
successTitle.successTitle = [[element firstChild] content];
}
// 8
self.linkSuccessObjects = newSuccessLinks;
}
else {
NSLog(#"HTTP status code: %d", response.statusCode);
NSLog(#"HTTP status message: %#", [response localizedStatusCodeString]);
NSLog(#"Header fields: %#", response.allHeaderFields);
NSLog(#"Body: %#", response.bodyAsString);
NSData *HtmlData = response.body;
// 2
TFHpple *addParser = [TFHpple hppleWithHTMLData:HtmlData];
// 3
NSString *errorXpathQueryString = #"//div[#class='errorBox']/ul/li";
NSArray *errorNodes = [addParser searchWithXPathQuery:errorXpathQueryString];
// 4
NSMutableArray *newError = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in errorNodes) {
// 5
AllModels *errorTitle = [[AllModels alloc] init];
[newError addObject:errorTitle];
// 6
errorTitle.errorTitle = [[element firstChild] content];
}
// 8
self.ErrorObjects = newError;
NSString *successXpathQueryString = #"//div[#class='successBox']";
NSArray *successNodes = [addParser searchWithXPathQuery:successXpathQueryString];
// 4
NSMutableArray *newSuccess = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in successNodes) {
// 5
AllModels *successTitle = [[AllModels alloc] init];
[newSuccess addObject:successTitle];
// 6
successTitle.successTitle = [[element firstChild] content];
}
// 8
self.successObjects = newSuccess;
[self errorCheck];
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
- (void)errorCheck {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Loading";
if(self.errorObjects.count > 0) {
AllModels *errorlink = [self.errorObjects objectAtIndex:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"There is a problem" message:errorlink.errorTitle delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil , nil];
[alert show];
}
else {
if(self.linkErrorObjects.count > 0) {
[self autoLogin];
[self requestToChangePasswordPressed];
}
else {
AllModels *successlink = [self.successObjects objectAtIndex:0];
self.successLabel.hidden = NO;
self.successLabel.text = successlink.successTitle;
NSLog(#"Success Title: %#",successlink.successTitle);
[UIView animateWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{ self.successLabel.alpha = 0.0; }
completion:^(BOOL fin) { if (fin) [self.successLabel removeFromSuperview]; }];
[self performSelector:#selector(dismissModalViewController) withObject:nil afterDelay:1.0];
}
}
[MBProgressHUD hideHUDForView:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}

Memory Leak related

i am working on a fishing app these days and i am getting a memory leak problem
-(void)requestFinished:(ASIFormDataRequest *) request {
if(hud != nil){
[hud show:NO];
[hud release];
hud = nil;
}
isLoading = NO;
self.responseText = [request responseString];
[self parseXml]; //I am getting leak here
if ( [self.responseText hasPrefix:#"<result>"]) {
UIAlertView *info = [[[UIAlertView alloc] initWithTitle:#" " message:#"Limited Internet access, please find a stronger signal in the area" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]autorelease];
[info show];
}
if (!isRefreshButtonClicked) {
[UIAccelerometer sharedAccelerometer].delegate = self;
[NSThread detachNewThreadSelector:#selector(parseXml) toTarget:self withObject:nil];
} }
This is my function...
-(void) parseXml
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
_fishes = [[fishes parseXml:self.responseText] retain];
[self performSelectorOnMainThread:#selector(parseXmlDone) withObject:nil waitUntilDone:YES];
[pool release];
Here _fishes is an array which is getting a value from a array return type function.....and here is that function...
+(NSMutableArray *)parseXml:(NSString *)xmlString {
//xmlString = [xmlString stringByReplacingOccurrencesOfString:#"&" withString:#""];
const char *cString = [xmlString UTF8String];
NSMutableArray *fishes = [NSMutableArray array];
NSData *xmlData = [NSData dataWithBytes:cString length:strlen(cString)];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; }
//parseXml
NSArray *_fishes = [doc.rootElement elementsForName:#"fishery"];
for (GDataXMLElement *_fish in _fishes) {
NSMutableDictionary *fish = [NSMutableDictionary dictionary];
NSArray *ids = [_fish elementsForName:#"id"];
if ([ids count]>0) {
GDataXMLElement *firstId = (GDataXMLElement *)[ids objectAtIndex:0];
[fish setValue:firstId.stringValue forKey:#"id"];
} else continue;
NSArray *names = [_fish elementsForName:#"name"];
if ([names count]>0) {
GDataXMLElement *firstName = (GDataXMLElement *)[names objectAtIndex:0];
[fish setValue:firstName.stringValue forKey:#"name"];...........
........
else continue;
NSArray *distances = [_fish elementsForName:#"distance"];
if ([distances count]>0) {
GDataXMLElement *distance = (GDataXMLElement *)[distances objectAtIndex:0];
[fish setValue:distance.stringValue forKey:#"distance"];
}else continue;
[fishes addObject:fish];
}
[doc release];
return fishes;
}
#end
I hope u guys will understand my problem...thanx
In -parseXml,
_fishes = [[fishes parseXml:self.responseText] retain];
will leak any previous object _fishes was pointing to in case -parseXml is sent more than once. You could use a retain property instead of an instance variable, or a setter method that releases the previous object, or release the previous object before assigning a new (retained) object to _fishes.

Problem passing NSError back as a return parameter

I am having a problem passing an NSError object back. The first line of code to access the object (in this case, I inserted an NSLog) causes "EXC_BAD_ACCESS".
Is this because I am not explicitly creating an NSError object, but rather getting one from the NSURLRequest and passing it back? In this particular function (downloadFile:), some errors I want to retrieve from other functions, but I create an NSError on two other occasions in the function.
Any help is appreciated.
Here is the offending code:
-(void)someCode {
NSError *err = nil;
localPool = [[NSAutoreleasePool alloc] init];
if (!iap) {
iap = [[InAppPurchaseController alloc] init];
}
if (![self.iap downloadFile:#"XXXXX.plist" withRemoteDirectory:nil withLocalDelete:YES withContentType:#"text/xml" Error:&err] ) {
//"EXC_BAD_ACCESS" on calling NSLog on the next line?
NSLog(#"Error downloading Plist: %#", [err localizedDescription]);
[self performSelectorOnMainThread:#selector(fetchPlistFailed:) withObject:err waitUntilDone:NO];
[localPool drain], localPool = nil;
return NO;
}
//Removed the remainder of the code for clarity.
[localPool drain], localPool = nil;
return YES;
}
-(BOOL)downloadFile:(NSString *)fileName
withRemoteDirectory:(NSString *)remoteDirectory
withLocalDelete:(BOOL)withLocalDelete
withContentType:(NSString *)contentTypeCheckString
Error:(NSError **)error {
UIApplication *app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES;
NSError *localError = nil;
NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
NSString *urlString = [NSString stringWithFormat:#"http://XXXXX/%#", fileName];
NSLog(#"Downloading file: %#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *req = [[NSURLRequest alloc] initWithURL:url];
NSHTTPURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&localError];
[req release];
if (response == nil || localError) {
NSLog(#"Error retrieving file:%#", [localError localizedDescription]);
if (error != NULL) {
*error = localError;
//THIS NSLog call works just fine.
NSLog(#"Error copied is:%#", [*error localizedDescription]);
}
[localPool drain], localPool = nil;
app.networkActivityIndicatorVisible = NO;
return NO;
}
//Rest of function omitted for simplicity.
}
I guess your NSError object is autoreleased and put on your localPool. You drained that localPool, thus destroying the NSError.
Do you really need localPool in every method? If not, just remove the localPools.
Also, it looks like you forgot to drain the localPool in someCode. Hopefully you just didn't copy it...
-(void)someCode {
NSError *err = nil;
localPool = [[NSAutoreleasePool alloc] init];
if (!iap) {
iap = [[InAppPurchaseController alloc] init];
}
if (![self.iap downloadFile:#"XXXXX.plist" withRemoteDirectory:nil withLocalDelete:YES withContentType:#"text/xml" Error:&err] ) {
....
[localPool drain], localPool = nil;
return NO;
}
[localPool drain], localPool = nil; // missing
}