AVAudioPlayer returns nil at random - objective-c

I have the following lines in my code:
NSString *soundPath = [[NSBundle mainBundle] pathForResource:[[soundString componentsSeparatedByString:#"."]objectAtIndex:0] ofType:#"wav"];
NSURL *soundURL_ = [NSURL fileURLWithPath:soundPath];
av_player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL_ error:nil];
These lines are in a class calles AnimatableObject which i use about 10 to 30 times in one ViewController.
It all works perfectly the first few times the ViewControllers get initialized and loaded. But after switching the ViewControllers some time my app crashes because the following line (which had worked all the times before) returns nil right now.
av_player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL_ error:nil];
I checked if soundPath or soundURL_ are nil. But they are ok. Exactly the same value like all the times before when it worked.
So now I ask myself how can it happen, that it works a lot of times and than returns nil?
In the same app, without closing and starting it again. And all I do is switching between viewControllers.
I first thought it is an memory issue, but i don't get any memory warnings.
I really have no idea why this is happening.
Any help would be appreciated.
Thx in advance,
Maverick.
--------Edit--------
I now found out that i get the following error:
ImageIO: CGImageRead_mapData 'open' failed '/var/mobile/Applications/F3186E1A-BBC2-47A6-8EF6-90F73C9BD566/huckla_zoo.app/Weiter.png'
error = 24 (Too many open files)
so i realize that i cannot open a soundfile when i get this error.
Only thing i wonder now is:
How can i close file-handles?
I don't load the images via [UIImage imageNamed:] but with
[UIImage imageWithContentsOfFile:filename];
I also have implemented a MutableDictionary as image cache which gets emptied, when memory issues occur.
Is there any other option for me to close my file-handles?

TRY THIS,
NSString* URL = [YOUR_URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

From the error, it sounds like you've opened a lot of files, and forgotten to close them. Are you releasing file objects when you're done? How many files are you working with?

Related

NSString's initWithContentsOfFile is failing to load any file bigger than 40kb, why and what is the solution?

I want to load a file into an NSString variable and am using NSString's initWithContentsOfFile to do so. However any file that is larger than 40kb the method fails and nil is returned to my variable. Here is the code I am using:
NSString *fileContents;
fileContents = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
I'm guessing it is failing due to memory shortage but surely it can handle a file as small as 40kb?!
After printing the error and discovering I was receiving Cocoa error code 261 I was quickly able to discover with a quick Google that my problem was that it was the NSStringEncoding argument that was causing a problem. I changed from NSUTF8StringEncoding to NSASCIIStringEncoding and my problem is fixed.

Objective-C thread safe code to prevent a crash

I got an iPhone crash report with a SIGSEGV and I think I've narrowed down the possible cause and a solution.
Since crashes caused by threads are hard to debug I can't repro this problem, but could use some help with my hypothesis - is it sound?
My code uses ASIHttpRequest to download a set of files using an ASINetWorkQueue. Here is a simplified sample
//initialize download queue and do this code block in a loop for each file
NSURL *fileURL = [NSURL URLWithString:...
__block ASIHTTPRequest *fileRequest = [ASIHTTPRequest requestWithURL:fileURL];
[fileRequest setCompletionBlock:^{
//do some stuff
}];
[fileRequest setFailedBlock:^{
NSString *someError = [NSString stringWithFormat:...
[self someErrorMethod:someError];
}];
[downloadQueue addOperation:...
-(void)someErrorMethod(NSString *errorMessage) {
DDLogWarn(errorMessage);
if ([self downloadQueue]) {
for (ASIHTTPRequest *request in [[self downloadQueue] operations]) {
[request clearDelegatesAndCancel];
}
[[self downloadQueue] reset];
}
}
The top 2 lines of the crash report are
libobjc.A.dylib 0x31846fbc objc_msgSend + 15
MyApp 0x0002cab5 -[Myapp someErrorMethod:] (MyApp.m:)
My thinking for why this happened
A file download fails and the failed block is called
It goes through every request and clears delegates and cancels them and then resets the queue
However, while it is till running, another file download fails and enters the failed block callback
However, since it has now been cancelled, its failed block has been released
When the code tries to log the error message, its memory has been released and unpredictable results follow
Does this make sense? Since I am newish to Objective-C, is my analysis correct or am I missing something obvious?
I am thinking of using a lock to make the errorMethod thread safe with the hope that it will fix this issue. Does that sound like the right solution based on the code above?
Thanks
This doesn't sound likely. ASIHttpRequest likely performs all of its callbacks on the same thread (I'm fairly certain on this one).
If I had to guess, your error is more likely in this line:
DDLogWarn(errorMessage);
The first parameter to DDLogWarn is a format, not a string. This will likely crash in any case that errorMessage includes a %. What you meant is:
DDLogWarn(#"%#", errorMessage);
Since DDLogWarn() is a varags method, it will start substituting the (random) values it finds on the stack for any % substitutions in the string. It will read the stack until you run out of % substitutions. If any of the % substitutions are pointer-based (like %s or %#), then it will follow the pointer to a random location.
SEG_ACCERR means that you've requested a piece of memory you don't own. SEG_MAPERR means you've requested a piece of memory that is not mapped. Either is an expected result of following a totally random pointer.

fetching data from URL in objective c

I am making iPad application, in which, I am fetching data from a URL. Sometimes, I retrieved Null instead.
In my URL i am passing my id dynamically, for eg: in this code i passed id = PNB,
here is the code snippet:
NSMutableString*str;
NSString *urlAddress = #”http://ipad.idealake.com/stockquote.aspx?id=PNB”;
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
str=[NSMutableString alloc] initWithContentsOfURL:url]; //(here compiler shows me warning initWithContentsOfURL is deprected)
NSLog(#"str=%#",str);
When I do NSLog of str, it shows me null value,
output: str=null
However, when I pass id=SUNPHARMA or id=AMBUJA it shows me proper output but when i pass id=TCS or id=LT it again shows me null value in my str. What went wrong?
you have to trim your id , and try...
The reason for getting nil is probably because the id argument is sometimes wrong (TCS or LT). Double check them, the URL probably hasn't any information to give in response.
About the warning, as stated in the doc, the initWithContentsOfURL: method is deprecated since iOS 2.0, you are encouraged to use initWithContentsOfURL:encoding:error: instead.
PLease use ASIHTTPRequest LIB to solve all your problem. They do download data to memory or directly to a file on disk, cache responses and download progress indicators for operation queues. http://allseeing-i.com/ASIHTTPRequest/

NSXMLElement, without an NSXMLDocument

I have an NSXMLElement that is a copy from somewhere else in my code. After it's been used, it no longer is connected to an NSXMLDocument. It's (what I believe to be) not linked to anything.
If I NSLog the NSXMLElement, I am given the contents. I can see it.
But, if I try to use nodesForXPath, it returns nothing. It's blank. It cannot find anything (unless I just search for *, in which case it returns everything with /t/t/n/t/t).
Now, if I make that NSXMLElement the root of a NEW NSXMLDocument, and then search the new document, I can search the XPath perfectly!
I am trying to understand the logic there. I have been reading the documentation, but I haven't found anything that explains what is happening here (or at least, I have no understood it if I did find it in the documentation).
I would really appreciate someone helping me understand exactly why this is happening, and whether or not I need to use this NSXMLDocument.
Here is my code:
(element is an NSXMLElement coming from an NSArray of stored NSXMLElements. They are copies from a document used in another method)
NSArray* scene = [element nodesForXPath:#"scene[1]" error:nil];
NSLog(#"scene: %#", [[scene objectAtIndex:0] stringValue]);
But if I do this, I get a result:
NSXMLDocument* docElement = [[NSXMLDocument alloc] initWithRootElement:element];
NSArray* scene = [docElement nodesForXPath:#"scene[1]" error:nil];
NSLog(#"scene: %#", [[scene objectAtIndex:0] stringValue]);
It's probably because the xpath context used by libxml2 holds a reference to the document. If there is no document, it probably doesn't know how to operate. The behavior if you search for * may just be a special-case because it knows it has to return everything so it doesn't even try to search.

-[NSCFNumber count]: unrecognized selector

I've got some Core Data code that follows Apple's sample code precisely (the Fetching Attribute Values that Satisfy a Given Function example). I'm using it to get the max value of a field, so I can then increment it when I insert the next object of that entity type.
I couldn't get the code to work at all, until I switched my Store Type from NSXMLStoreType to NSSQLiteStoreType, then all of a sudden everything seemed to be working. However, that's not the case. I noticed that it would always return the same value, even when I inserted objects with a higher one. But, after I quit and reopened (and thus the data was persisted and read back in), it would update with the new inserts.
So then I started committing and saving after each insert. After the first "autosave" though, I get the error below (twice in a row):
-[NSCFNumber count]: unrecognized selector sent to instance 0x100506a20
This occurs (two times in a rows) when I execute the fetch request once:
NSArray *objects = [context executeFetchRequest:request error:&error];
Update
I ran my code through the Zombies instrument, and was able to take a look at the object which is getting the error. The call that runs malloc to allocate it is: -[NSUserDefaults(NSUserDefaults) initWithUser:]. Since I don't have any of my own defaults set, I don't know what object this could be.
Update 2
I searched through all of my code for "release" and commented out every release or autorelease that the static analyzer didn't complain about. I still got the errors. I even went so far as to comment out every last release/autorelease in my code, and still got it. Now I'm fairly certain my own code isn't over-releasing.
Update 3
This post seems to be having the same problem, but his solution doesn't make sense. He changed the result type from NSDictionaryResultType to NSManagedObjectResultType, which produces an incorrect result. Instead of getting back a single value (the max that I'm looking for, that returns back every object of my entity class in the managed object context.
Here are the top-most levels of the stack trace (when I have it break on the exception, the first time):
#0 0x7fff802e00da in objc_exception_throw
#1 0x7fff837d6110 in -[NSObject(NSObject) doesNotRecognizeSelector:]
#2 0x7fff8374e91f in ___forwarding___
#3 0x7fff8374aa68 in __forwarding_prep_0___
#4 0x7fff801ef636 in +[_NSPredicateUtilities max:]
#5 0x7fff800d4a22 in -[NSFunctionExpression expressionValueWithObject:context:]
#6 0x7fff865f2e21 in -[NSMappedObjectStore executeFetchRequest:withContext:]
#7 0x7fff865f2580 in -[NSMappedObjectStore executeRequest:withContext:]
I've seen this question on numerous forums elsewhere on the web, but no one has offered a workable solution. By popular request, I added my own code below. To explain slightly, my entity's name is Box and the property I'm trying to get the value of is "sortOrder", an Int 32 attribute.
NSManagedObjectContext *context = [MyLibrary managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Box"
inManagedObjectContext:context]];
// Specify that the request should return dictionaries.
[request setResultType:NSDictionaryResultType];
// Create an expression for the key path.
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"sortOrder"];
// Create an expression to represent the function you want to apply
NSExpression *expression = [NSExpression expressionForFunction:#"max:"
arguments:[NSArray arrayWithObject:keyPathExpression]];
// Create an expression description using the minExpression and returning a date.
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
// The name is the key that will be used in the dictionary for the return value.
[expressionDescription setName:#"maxSort"];
[expressionDescription setExpression:expression];
[expressionDescription setExpressionResultType:NSInteger32AttributeType];
// Set the request's properties to fetch just the property represented by the expressions.
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
// Execute the fetch.
NSError *error;
NSNumber *requestedValue = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
NSLog( #"objects: %#", objects );
if (objects != nil && [objects count] > 0) {
requestedValue = [[objects objectAtIndex:0] valueForKey:#"maxSort"];
} else {
[[NSApplication sharedApplication] presentError:error];
}
[expressionDescription release];
[request release];
NSLog( #"Max Sort Order: %#", requestedValue );
return requestedValue;
Apparently this is a known bug, that occurs when using an NSInMemoryStoreType data store. It seems it works fine using an NSSQLiteStoreType.
You can find the OpenRadar entry here
I filled a duplicate for this bug — I encourage people that encounter the same issue to do the same, to increase the likelihood this annoying behaviour gets documented (or even better, fixed).
When you have memory management issues (selectors being sent to the wrong instances is a sign of memory management issues), there are a number of things you can do:
Re-read the Cocoa memory management rules and make sure that you're following them.
Run the static analyser. This will often pick up places where you have neglected the memory management rules.
Try using NSZombieEnabled to find out whether [and when] you are sending messages to unallocated instances.
-[NSCFNumber count]: unrecognized selector sent to instance 0x100506a20 means, that you are calling count on a NSCFNumber object, but NSCFNumber doesnt have this method. So most likely count is send to a deallocated NSArray or NSSet object.
USE NSZombieEnabled = YES. It might tell you, what happens. Search SO for informations on how to set it.
This can also happen if a binding is not set correctly. For example, if you bind a matrix boolean value to "Content" instead of (or in addition to) "Selected Tag" in IB you can get this error.
If all else fails, disconnect all of your bindings and reconnect them one at a time to see which one is the culprit.
After experiencing exactly the same problem with exactly the same sample code, it finally worked for me after I put [request release] in.
You are using the key path: sortOrder in your path expression. At least for XML-Databases Core-Data cannot handle case-sensitive types. Change your path to sortorder (all lower-case)
You will probably stumble over further problems if you are using controller classes.