iOS: Custom class import - ios

I moved some code that will be used multiple times into a class.
I'm not getting errors, but I'm also not getting results. It seems to skip over my class completely.
Ideally, this class is supposed to do NSURL conns and XMLParser stuff to chew up the data feed from our hosting API. I already have this working but wanted to congeal and somewhat normalize/centralize some of the main logic of my code.
The one function 'bdCheckIfFileExistsAndisValid' is supposed to take a string but return BOOL and it isn't being called at all.
Neither is 'bdParsePlaylistXML' that is supposed to take a string and return an array.
I put breakpoints everywhere in my class and none are hit.
I'm new so I'm not sure if I did everything right. Here's some code, thanks in advance.
--------------------CUSTOM CLASS:(.h)
#interface bdXMLParser : NSObject {
NSMutableArray *playlist;
//Playlist XML info
BOOL recordTrackName;
BOOL recordTrackDescription;
BOOL recordTrackThumbnailAbsoluteLocation;
BOOL recordTrackURL;
NSString *TrackName;
NSString *TrackDescription;
NSString *TrackThumbnailAbsoluteLocation;
NSString *TrackURL;
}
-(NSMutableArray*) bdParsePlaylistXML:(NSString *) playlistXMLFileName;
-(BOOL) bdCheckIfFileExistsAndisValid:(NSString *) localFileName;
----------------CUSTOM CLASS (.m):
#import "bdXMLParser.h"
#implementation bdXMLParser
{
NSMutableData *webData;
NSMutableArray *playlist;
NSXMLParser *xmlParserPlaylist;
}
-(NSString*) bdDocumentsDirectory{
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
return documentsPath;
}
-(int) bdCheckFileCreationDate:(NSString *) fileName {
//get XML file path
NSString *localFilePath = [[self bdDocumentsDirectory] stringByAppendingPathComponent:fileName];
//local file check
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSDictionary* attrs = [filemgr attributesOfItemAtPath:localFilePath error:nil];
NSDate *fileCreationDate = [attrs objectForKey: NSFileCreationDate];
NSDate *rightNow = [NSDate date];
NSTimeInterval lastDiff = [fileCreationDate timeIntervalSinceNow];
int lastDiffINT = round(lastDiff);
NSLog(#"NSFileCreationDate:%#",fileCreationDate);
NSLog(#"CurrentDate:%#",rightNow);
NSLog(#"lastDiff:%f",lastDiff);
return lastDiffINT;
}
-(BOOL) bdCheckIfFileExistsAndisValid:(NSString *) fileName {
//local file check
NSString* foofile = [[self bdDocumentsDirectory] stringByAppendingPathComponent:fileName];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
if ((fileExists == YES) && ([self bdCheckFileCreationDate:foofile] > -86400))//(24 hrs = 86400 seconds)
return YES;
else
return NO;
}
HERE's THE VIEW WHERE I'M TRYING TO USE IT:(menu.h)
#import "bdXMLParser.h"
#interface MenuScreenViewController : UIViewController <NSXMLParserDelegate>
- (IBAction)btnPlayerPlayPause:(id)sender;
(menu.m)
- (IBAction)btnPlayerPlayPause:(id)sender {
//if array exists, don't reload xml, dont reparse xml, just go to the view
if (playlist.count == 0){
//Playlist!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//========================================================================
//1st: check to see if we have a local cached xml data
//if we do, check if it is <24hr old and if so load it
//if not, go get it with connection and overwrite/store it
//init blogs NSMutableArray
playlist = [[NSMutableArray alloc] init];
//local file check
bdXMLParser *myParser;
BOOL fileExistsAndValid = NO;
=HERE!==fileExistsAndValid = [myParser bdCheckIfFileExistsAndisValid:PlaylistName];
//1st
if (fileExistsAndValid)//(<24 hrs old)
{
NSLog (#"File fileExistsAndValid");
=AND HERE!!=playlist = [myParser bdParsePlaylistXML:PlaylistName];
NSLog(#"playlist:%u", playlist.count);
//load first track
[self LoadTrack:0];
}
else{
NSLog (#"File doesn't exist");
//call refresh function
//[self refreshAlbumPhotoXML];
[myParser bdRefreshPlaylistXML];
}
}
}

you forgot initing the class
bdXMLParser *myParser= [[bdXMLParster alloc]init];

Related

Copying a realm-file seems to cause realm Migration-block call - why?

After copying a .realm-file from folder-location1 to folder-location2 (and also changing its name from location1.realm to location2.realm using NSFileManager) - it seems that after doing so, the first call to this new file causes a migration-block call! (i.e. setSchemaVersion). I wonder WHY ???
Prior calls to the "location1/location1.realm" File did not cause a migration-block call - however calls to "location2/location2.realm" do - and the files are identical in structure (at least in Realm-Browser there is no obvious difference) !!
Here is my code :
ApplicatonSuppPathHandler *ApplicationSupportPathHandler = [[ApplicatonSuppPathHandler alloc] init];
// creation of location where this directory shall be placed on the iPhone
// typically /library/Application Support/<bundleID_name>/RLMGeneralDatabasesFolderName/...
// = name of directory that the .realm-File finally should be placed in
NSString *RLMLocation1DirectoryName = folderName;
// if it does not exist already, create the RLMLocation_xyz-directory (.../library/Application Support/<bundleID_name>/RLMDatabasesFolderName)
if([ApplicationSupportPathHandler getURLToApplicationDirectoryWithSubDirectory:RLMLocation1DirectoryName] == nil) {
[ApplicationSupportPathHandler createSubDirectoryAtLocationToApplicationDirectory:RLMLocation1DirectoryName];
}
// get the name of entire directory just created
NSURL *RLMLocation1Directory = [ApplicationSupportPathHandler getURLToApplicationDirectoryWithSubDirectory:RLMLocation1DirectoryName];
// name of entire path-name (including filename !! ...needed for copy function below...)
NSString *RLMLocation1Path = [[RLMLocation1Directory path] stringByAppendingPathComponent:fileName];
// HERE IS WHERE THE MIGRATION BLOCK IS CALLED - WHY ?????
// *******************************************************
RLMRealm *realm_Location1 = [RLMRealm realmWithPath:RLMLocation1Path]; // pointing to realm file at path
// the rest does work after the migration-block call...
[realm_Location1 beginWriteTransaction];
[realm_Location1 deleteAllObjects];
[realm_Location1 addObject:RLMTopoRes];
[realm_Location1 commitWriteTransaction];
Below is the implementation of the used ApplicationSuppPathHandler class-methods:
#implementation ApplicatonSuppPathHandler
- (NSURL*)getURLToApplicationDirectoryWithSubDirectory:(NSString*)SubDirectoryName {
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0)
{
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:SubDirectoryName];
BOOL isDir;
BOOL exists = [fm fileExistsAtPath:[dirPath path] isDirectory:&isDir];
if (exists) {
/* file exists */
if (isDir) {
/* path exists */
return dirPath;
}
else {
NSLog(#"Directory does not exist");
return nil;
}
}
else {
/* file does not exist */
return nil;
}
}
return dirPath;
}
- (void)createSubDirectoryAtLocationToApplicationDirectory:(NSString*)SubDirectoryName {
NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager*fm = [NSFileManager defaultManager];
NSURL* dirPath = nil;
// Find the application support directory in the home directory.
NSArray* appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
inDomains:NSUserDomainMask];
if ([appSupportDir count] > 0)
{
// Append the bundle ID and the location-Foldername to the URL for the Application Support directory
dirPath = [[[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:appBundleID] URLByAppendingPathComponent:SubDirectoryName];
// If the directory does not exist, this method creates it.
// This method call works in OS X 10.7 and later only.
NSError* theError = nil;
if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError]) {
// Handle the error.
NSLog(#"%#", theError.localizedDescription);
}
else {
// Mark the directory as excluded from iCloud backups
if (![dirPath setResourceValue:#YES
forKey:NSURLIsExcludedFromBackupKey
error:&theError]) {
NSLog(#"Error excluding %# from iCloud backup %#", [dirPath lastPathComponent], theError.localizedDescription);
}
else {
// NSLog(#"Location Directory excluded from iClud backups");
}
}
}
}
There was previously a bug in Realm where new realm files would have their schema version set to 0 instead of the current schema version, which would trigger a migration in your case.
A fix for this was pushed to the master branch of Realm last week: https://github.com/realm/realm-cocoa/pull/1142
Building Realm from master should address the issue you're having. Realm v0.88.0 will be released shortly with this fix.
...hhm - seems that another method messed up !
The below code shows this method that loads data from a realm-file into a realm-wrapper-object.
Coming back to the original problem (location2/location2.realm file creating migraton-block):
Unfortunately, I was not aware that calling this "loadData_..."-method needed to be called with caution ! If it is called twice - once to location1/location1.realm and then a second time (to location2/location2.realm) - that is when things get messed up !
I tried to create a "wrapper" that loads and saves Realm-objects. But it seems more difficult with Realm than originally expected. Thanks for any comment on this !!
- (void) loadData_at_TopoNr_from_LocationRLM :(NSNumber *)TopoNr :(NSString *)folderName :(NSString *)fileName {
// realm-object calling "get_TopoResultRLM_FilePath" must be of same object-type, otherwise block-migration call !
RLMRealm *realm = [RLMRealm realmWithPath:[self get_TopoResultRLM_FilePath :folderName :fileName]];
RLMResults *resTopoResult = [RLMTopoResult allObjectsInRealm:realm];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"TopoNrRLM == %d", [TopoNr intValue]];
RLMResults *resultTopoResult = [resTopoResult objectsWithPredicate:predicate1];
if ([resultTopoResult count] <= 1) {
if ([resultTopoResult count] == 1) {
// found one object
// data loading
self.TopoNrRLM = [resultTopoResult.firstObject TopoNrRLM];
self.nameAnamneserRLM = [resultTopoResult.firstObject nameAnamneserRLM];
self.anamneseDateRLM = [resultTopoResult.firstObject anamneseDateRLM];
self.NumberOfCriteriaRLM = [resultTopoResult.firstObject NumberOfCriteriaRLM];
self.BestMatchMethodRLM = [resultTopoResult.firstObject BestMatchMethodRLM];
self.RealmFrameworkVersionRLM = [resultTopoResult.firstObject RealmFrameworkVersionRLM];
self.BoundaryConditionVerionRLM = [resultTopoResult.firstObject BoundaryConditionVerionRLM];
self.CriteriaRLM = [resultTopoResult.firstObject CriteriaRLM];
self.imageNameRLM = [resultTopoResult.firstObject imageNameRLM];
self.imageDataRLM = [resultTopoResult.firstObject imageDataRLM];
}
else { ....
Here is the property definition of the wrapper-object-class :
// GUIData-RLM
#property (nonatomic) RLMGUIData *GUIDataRLM;
// Location-RLM
#property (nonatomic) RLMTopoResult *LocationRLM;
Here is the object creation and call of that loadData_at...-method :
RLMTopoResult *LocationRealm = [[RLMTopoResult alloc] init];
[self setLocationRLM:LocationRealm];
[LocationRealm loadData_at_TopoNr_from_LocationRLM :[NSNumber numberWithInt:[GUIDataRealm TopoNrRLM]] :[GUIDataRealm locationFolderNameRLM] :[NSString stringWithFormat:#"%#%s", [GUIDataRealm locationFolderNameRLM], ".realm"]];

NSArrayM setObject:atIndex:]: object cannot be nil

Having a little issue with a bit of code, returning the error listed above after running its respective action:
- (IBAction)uploadData:(id)sender {
NSMutableArray *uploadArray = [[NSMutableArray alloc]init];
[uploadArray addObject:#"hire.csv"];
[uploadArray addObject:#"equipment.csv"];
[uploadArray addObject:#"signature.png"];
NSString * docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString * proof1 = [docPath stringByAppendingPathComponent:#"proof1.png"];
if([[NSFileManager defaultManager] fileExistsAtPath: proof1])
{
[uploadArray addObject:#"proof1.png"];
}
NSString * proof2 = [docPath stringByAppendingPathComponent:#"proof2.png"];
if([[NSFileManager defaultManager] fileExistsAtPath: proof2])
{
[uploadArray addObject:#"proof2.png"];
}
NSString * proof3 = [docPath stringByAppendingPathComponent:#"proof3.png"];
if([[NSFileManager defaultManager] fileExistsAtPath: proof3])
{
[uploadArray addObject:#"proof3.png"];
}
int arrayCount = [uploadArray count];
int i = 0;
NSString *arrayString;
for (i = 0; i < arrayCount; i++)
{
uploadArray[i] = arrayString;
if(arrayString != nil)
{
NSString * uploadString = [docPath stringByAppendingPathComponent:arrayString];
[self upload:uploadString ftpUrl:#"ftp.xxxxxxxx.com/xx/xx" ftpUsr:#"xxx" ftpPass:#"xxx"];
}
NSLog(uploadArray[i]);
}
}
Now, if I disable everything in the for loop except for the NSLog() I get no error, and it returns the correct list of objects in the array.
This to me suggests that none of the objects should return nil, surely?
Could anyone help me spot what I'm doing wrong? (probably quite a lot as im pretty new to this stuff)
As your error clearly stats, you are adding a nil object to an array and this is not allowed.
In the below code you have not assigned anything to arrayString making it nil. Then you try to add it to your array.
NSString *arrayString;
for (i = 0; i < arrayCount; i++)
{
uploadArray[i] = arrayString;
From the looks of your code you are trying to add every element form your array to your string. You are doing this the wrong way around. You need a NSMutableString and do something like:
[arrayString appendString: uploadArray[i]];

Not receiving notification dispatch_group_notify

I am currently using a dispatch_group to get notify when all concurrent tasks are done. I am offloading some heavy tasks on one concurrent queue within the [TWReaderDocument documentFileURL:url withCompletionBlock:] class method.
I have implemented the following code but never received any notification. I don't see what i am potentially doing wrong in the below code:
dispatch_group_t readingGroup = dispatch_group_create();
NSFileManager* manager = [NSFileManager defaultManager];
NSString *docsDir = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Data"];
NSDirectoryEnumerator *dirEnumerator = [manager enumeratorAtURL:[NSURL fileURLWithPath:docsDir]
includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLNameKey,
NSURLIsDirectoryKey,nil]
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:nil];
// An array to store the all the enumerated file names in
NSMutableArray *arrayFiles;
// Enumerate the dirEnumerator results, each value is stored in allURLs
for (NSURL *url in dirEnumerator) {
// Retrieve the file name. From NSURLNameKey, cached during the enumeration.
NSString *fileName;
[url getResourceValue:&fileName forKey:NSURLNameKey error:NULL];
// Retrieve whether a directory. From NSURLIsDirectoryKey, also cached during the enumeration.
NSNumber *isDirectory;
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:NULL];
if (![isDirectory boolValue]) {
dispatch_group_enter(readingGroup);
TWReaderDocument* doc = [TWReaderDocument documentFileURL:url withCompletionBlock:^(BOOL success) {
dispatch_group_leave(readingGroup);
}];
[arrayFiles addObject:doc];
}
else if ([[[fileName componentsSeparatedByString:#"_" ] objectAtIndex:0] isEqualToString:#"XXXXXX"]) {
TreeItem* treeItem = [[TreeItem alloc] init];
arrayFiles = [NSMutableArray arrayWithCapacity:10];
treeItem.child = arrayFiles;
treeItem.nodeName = [[fileName componentsSeparatedByString:#"_" ] lastObject];
[self addItem:treeItem];
}
}
dispatch_group_notify(readingGroup, dispatch_get_main_queue(), ^{ // 4
NSLog(#"All concurrent tasks completed");
});
Does the dispatch_group_enter and dispatch_group_leave have to be executed on the same thread?
EDIT
The code snippet of my factory method might help aswell:
+ (TWReaderDocument *)documentFileURL:(NSURL *)url withCompletionBlock:(readingCompletionBlock)completionBlock{
TWReaderDocument * twDoc = [[TWReaderDocument alloc] init];
twDoc.status = ReaderDocCreated;
twDoc.doc = [ReaderDocument withDocumentFilePath:[url path] withURL:url withLoadingCompletionBLock:^(BOOL completed) {
twDoc.status = completed ? ReaderDocReady : ReaderDocFailed;
completionBlock(completed);
}];
return twDoc;
}
TWReaderDocument is a wrapper class that call internally the following methods of a third-party library (it is a PDF reader)
+ (ReaderDocument *)withDocumentFilePath:(NSString *)filePath withURL:(NSURL*)url withLoadingCompletionBLock:(readingCompletionBlock)completionBlock{
ReaderDocument *document = [[ReaderDocument alloc] initWithFilePath:filePath withURL:url withLoadingCompletionBLock:[completionBlock copy]];
return document;
}
- (id)initWithFilePath:(NSString *)fullFilePath withURL:(NSURL*)url withLoadingCompletionBLock:(readingCompletionBlock)completionBlock {
id object = nil; // ReaderDocument object;
if ([ReaderDocument isPDF:fullFilePath] == YES) // File must exist
{
if ((self = [super init])) // Initialize superclass object first
{
_fileName = [ReaderDocument relativeApplicationFilePath:fullFilePath]; // File name
dispatch_async([ReaderDocument concurrentLoadingQueue], ^{
self.guid = [ReaderDocument GUID]; // Create a document GUID
self.password = nil; // Keep copy of any document password
self.bookmarks = [NSMutableIndexSet indexSet]; // Bookmarked pages index set
self.pageNumber = [NSNumber numberWithInteger:1]; // Start on page 1
CFURLRef docURLRef = (__bridge CFURLRef)url;// CFURLRef from NSURL
self.fileURL = url;
CGPDFDocumentRef thePDFDocRef = CGPDFDocumentCreateX(docURLRef, self.password);
BOOL success;
if (thePDFDocRef != NULL) // Get the number of pages in the document
{
NSInteger pageCount = CGPDFDocumentGetNumberOfPages(thePDFDocRef);
self.pageCount = [NSNumber numberWithInteger:pageCount];
CGPDFDocumentRelease(thePDFDocRef); // Cleanup
success = YES;
}
else // Cupertino, we have a problem with the document
{
// NSAssert(NO, #"CGPDFDocumentRef == NULL");
success = NO;
}
NSFileManager *fileManager = [NSFileManager new]; // File manager instance
self.lastOpen = [NSDate dateWithTimeIntervalSinceReferenceDate:0.0]; // Last opened
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:fullFilePath error:NULL];
self.fileDate = [fileAttributes objectForKey:NSFileModificationDate]; // File date
self.fileSize = [fileAttributes objectForKey:NSFileSize]; // File size (bytes)
completionBlock(success);
});
//[self saveReaderDocument]; // Save the ReaderDocument object
object = self; // Return initialized ReaderDocument object
}
}
return object;
}
It's hard to say what's going on here without knowing more about TWReaderDocument, but I have a suspicion...
First off, no, dispatch_group_enter and dispatch_group_leave do not have to be executed on the same thread. Definitely not.
My best guess based on the info here would be that for some input, [TWReaderDocument documentFileURL:withCompletionBlock:] is returning nil. You might try this instead:
if (![isDirectory boolValue]) {
dispatch_group_enter(readingGroup);
TWReaderDocument* doc = [TWReaderDocument documentFileURL:url withCompletionBlock:^(BOOL success) {
dispatch_group_leave(readingGroup);
}];
// If the doc wasn't created, leave might never be called.
if (nil == doc) {
dispatch_group_leave(readingGroup);
}
[arrayFiles addObject:doc];
}
Give that a try.
EDIT:
It's exactly as I expected. There are cases in which this factory method will not call the completion. For instance:
if ([ReaderDocument isPDF:fullFilePath] == YES) // File must exist
If -isPDF: returns NO the completionBlock will never be called, and the returned value will be nil.
Incidentally, you should never compare something == YES. (anything non-zero is equivalent to YES, but YES is defined as 1. Just do if ([ReaderDocument isPDF:fullFilePath]). It's equivalent, and safer.

How to store a CLLocation object using NSKeyedArchiver?

I am slightly confused why the following doesn't work. Can someone enlighten me?
I have one function that returns a filePath:
- (NSString *) lastLocationPersistenceFilePath {
NSString *filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:#"last_location"];
return filePath;
}
Then, in a method triggered by a button, I attempt to save a CLLocation object like so:
// Store this location so it can persist:
BOOL success = [NSKeyedArchiver archiveRootObject:_startLocation toFile:[self lastLocationPersistenceFilePath]];
if (!success) {
NSLog(#"Could not persist location for some reason!");
} else {
NSLog(#"New location has been stored.");
}
In my viewDidLoad:, I attempt to load it:
- (void)viewDidLoad
{
[super viewDidLoad];
// Retrieve last location:
CLLocation *decodedLocation = [NSKeyedUnarchiver unarchiveObjectWithFile:[self lastLocationPersistenceFilePath]];
if (decodedLocation) {
_startLocation = decodedLocation;
} else {
NSLog(#"Decoding failed.");
}
}
The archiving fails which, of course, means I can't decode anything either. I feel like I am missing something obvious/trivial... any pointers?
Simply, it is not possible to write to the the app's resource directory. Instead write to the app's document directory.
Code example"
- (NSString *) lastLocationPersistenceFilePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths firstObject];
NSString *filePath = [documentDirectory stringByAppendingPathComponent:#"last_location"];
return filePath;
}

Objective C memory management - "pointer being freed was not allocated" errors

I'm trying to learn objective-c (I'm very new to that) and I have issues with memory management...
I'm developing an iPad app that uses TouchXML.
I've created my class that extends CXMLDocument and does some initialisation by reading some contents and saving into properties.
Here is my code (SimpleManifest.h):
#interface SimpleManifest : CXMLDocument {
CXMLNode *_defaultOrganization;
NSString *_title;
NSDictionary *dictionary;
}
#property (readonly) CXMLNode *defaultOrganization;
#property (readonly) NSString* title;
- (id) initWithPath:(NSString *)path options:(NSUInteger)options error:(NSError **)error;
#end
(SimpleManifest.m):
#import "SimpleManifest.h"
#import "CXMLNode_XPathExtensions.h"
#implementation SimpleManifest
- (id) initWithPath:(NSString *)path options:(NSUInteger)options error:(NSError **)error
{
/*
NSURL *theURL = [[[NSURL alloc] initFileURLWithPath:path] autorelease];
self = [self initWithContentsOfURL:theURL options:options error:error];
*/
NSData *data = [NSData dataWithContentsOfFile:path];
NSString *s = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
self = [self initWithXMLString:s options:options error:error];
if (self==nil) return nil;
// load main props
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"http://www.imsglobal.org/xsd/imscp_v1p1", #"imscp",
#"http://ltsc.ieee.org/xsd/LOM", #"lom", nil];
// defualt organization
#try {
CXMLNode *orgsElem = [[[self childAtIndex:0] nodesForXPath:#"//imscp:organizations" namespaceMappings:dictionary error:nil] objectAtIndex:0];
NSString *xpath = [NSString stringWithFormat:#"//imscp:organization[#identifier='%#']", [[orgsElem attributeForName:#"default"] stringValue]];
_defaultOrganization = [[[self childAtIndex:0] nodesForXPath:xpath namespaceMappings:dictionary error:nil] objectAtIndex:0];
/*
NSArray *nodes = [[self childAtIndex:0] nodesForXPath:#"//imscp:organizations" namespaceMappings:dictionary error:nil];
NSString *xpath = [NSString stringWithFormat:#"//imscp:organization[#identifier='%#']", [[[nodes objectAtIndex:0] attributeForName:#"default"] stringValue]];
_defaultOrganization = [[[self childAtIndex:0] nodesForXPath:xpath namespaceMappings:dictionary error:nil] objectAtIndex:0];
*/
CXMLNode *titleElem = [[[self childAtIndex:0]
nodesForXPath:#"//lom:general/lom:title/lom:string"
namespaceMappings:dictionary
error:nil] objectAtIndex:0];
_title = [[titleElem stringValue] copy];
} #catch (NSException * e){
self = nil;
return nil;
}
return self;
}
#end
Later on in another class I do:
- (BOOL) isValidSCORMLesson:(NSString*) path {
NSString *manifPath = [path stringByAppendingPathComponent:#"imsmanifest.xml"];
if (![[NSFileManager defaultManager] fileExistsAtPath: manifPath isDirectory: NO])
return NO;
SimpleManifest *manifest = [[[SimpleManifest alloc] initWithPath:manifPath options:0 error:nil] autorelease];
NSLog(#"%#", manifest.defaultOrganization);
NSLog(#"%#", manifest.title);
return (manifest!=nil);
}
It gives me tons of "pointer being freed was not allocated" errors...
The thing changes if I comment out the NSLog calls above or just log the manifest.title property.
Project is not using ARC, so I'm sure I'm doing something wrong with memory management.
Can someone please help me understand where I'm doing wrong? Thanks!
There isn't anything obviously wrong with that code that would cause malloc errors. Best guess is that there is a bug in the CXMLDocument class/library or some mistake in the way you are using it.
Note that a "pointer being freed was not allocated" means that someone called free() (or dealloc, effectively) on a pointer to a piece of memory that was not allocated in the first place. It usually gives you a breakpoint you can set that will then give you a backtrace of exactly where it happened.
Some comments:
(1) Do not #try/#catch in that fashion. Just don't catch at all. The pattern you are using will hide any errors. Exceptions are not meant to be recoverable in iOS/Cocoa.
(2) You can create an NSString instance directly from a file; no need to load via NSData first.
(3) You should use ARC.

Resources