Song doesn't play when method called from another class - ios

I'm trying to play a song in my application. When the the code to play a song is put right away in the controller it runs good.
But when i put the code in a class, call the class then call the method to play the song, nothing happens ? If someone have a clue please feel free to help.
here is the code to play a song
-(void)randomSound{
NSLog(#"sound");
NSString * path;
NSError * err;
NSString *name;
NSArray *names = [[NSArray alloc] initWithObjects:#"1up.wav", #"mario02.dsp.wav", #"mario04.dsp.wav", #"mario06.dsp.wav", #"mrf.dsp.wav", nil];
name = [names randomObject];
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSURL * url = [NSURL fileURLWithPath:path];
self.snd = [[AVAudioPlayer alloc] initWithContentsOfURL:url
error:&err] ;
if (! self.snd) {
NSLog(#"data named '%#' had error %#", name, [err localizedDescription]);
} else {
NSLog(#"playing");
[self.snd prepareToPlay];
[self.snd play];
}
} else {
NSLog(#"data file '%#' doesn't exist at '%#'", name, path);
}
}
The way i call the method
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"YAHOO"])
{
YahooViewController *YH = [[YahooViewController alloc] init];
[YH randomSound];
}
The random method in case someone would like to know whats in it
-(id)randomObject {
NSUInteger myCount = [self count];
if (myCount)
return [self objectAtIndex:arc4random_uniform(myCount)];
else
return nil;
}

After discussion in comments it was identified the issue was URL encoding.
Check out this question / answer which will show you how to URLEncode a string:
How do I URL encode a string

Related

NSDirectoryEnumerator iterated element can't compare suffix

I am using NSDirectoryEnmerator to find all file with a suffix of png and jpg with following code:
NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtURL:containerURL includingPropertiesForKeys:[NSArray array] options:0 errorHandler:^BOOL(NSURL *url, NSError *error) {
// handle error
return NO;
}];
NSString *fileOrDirectory = nil;
while ((fileOrDirectory = [directoryEnumerator nextObject])) {
if([fileOrDirectory hasSuffix:#".jpg"] || [fileOrDirectory hasSuffix:#".png"]){
NSLog(#" find a image file %#", fileOrDirectory );
}
}
But there is an error said that NSURL don't have a method hasSuffix
What happened and how to make this work? what does the type of the iterated elements exactly? the above code was frequently suggested by posts and was presumed to be a NSString but it can't work
The enumeratorAtURL method works with NSURL objects rather than strings (which the exception reason clearly reveals), you can simply compare the pathExtension:
if ([fileOrDirectory.pathExtension isEqualToString:#"jpg"] ||
[fileOrDirectory.pathExtension isEqualToString:#"png"]) { ...

edit core data model objects in a loop

I am trying to edit existing objects in Core Data storage. When i edit each object's attribute without a loop this works fine, but when I try to do it in a for loop, only my last object gets new attributes.
Here is the code I use to edit objects without a loop. This code works fine):
NSFetchRequest *songsRefreshRequest = [[NSFetchRequest alloc] initWithEntityName:#"Music"];
songsRefreshRequest.predicate = nil;
songsRefreshRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(localizedStandardCompare:)]];
NSError *frError;
NSArray *fetchedSongs = [self.context executeFetchRequest:songsRefreshRequest error:&frError];
fetchedSongs ? : NSLog(#"Error in fetch while refreshing songs: %#", [frError localizedDescription]);
NSString *song1path = [[NSBundle mainBundle] pathForResource:#"Beautiful-birds-song-in-the-morning" ofType:#"mp3"];
NSString *song2path = [[NSBundle mainBundle] pathForResource:#"Birds-singing-relaxation" ofType:#"mp3"];
NSString *song3path = [[NSBundle mainBundle] pathForResource:#"Morning Melody" ofType:#"mp3"];
Music *song1 = (Music *) [fetchedSongs objectAtIndex:0];
Music *song2 = (Music *) [fetchedSongs objectAtIndex:1];
Music *song3 = (Music *) [fetchedSongs objectAtIndex:2];
song1.name = #"Beautiful-birds-song-in-the-morning";
song2.name = #"Birds-singing-relaxation";
song3.name = #"Morning Melody";
song1.path = song1path;
song2.path = song2path;
song3.path = song3path;
Here is the code I use to edit song's attributes in a loop (code below somehow edit a path for only the last object (song3 in my case), other object's path attribute becomes NULL. And I can't figure out why):
for (Music *iterSong in fetchedSongs){
NSString *iterSongName = [iterSong valueForKey:#"name"];
iterSong.path = [[NSBundle mainBundle] pathForResource: iterSongName ofType:#"mp3"];
}
I have already tried to change for each to for (int i=0; i<[fetchedSongs count]; i++) this didn't help. Cycle repeats as many times as many songs are in the model and only changes the last song's path. Appreciate any help, thanks in advance!
P.S. The whole loop code:
for (Music *iterSong in fetchedSongs){
//Music *iterSong = (Music*) [fetchedSongs objectAtIndex:i];
NSLog(#"inerSong.name = %#", iterSong.name);
NSLog(#"inerSong.oldPath = %#", iterSong.path);
NSString *iterSongName = [iterSong valueForKey:#"name"];
NSString *iterSongPath = [[NSBundle mainBundle] pathForResource: iterSongName ofType:#"mp3"];
NSLog(#"iterSongPath (string) = %#", iterSongPath);
iterSong.path = iterSongPath;
NSLog(#"iterSong.newPath = %#", iterSong.path);
}
if ([self.context hasChanges]){
NSError *error;
if (![self.context save:&error]){
NSLog(#"error while saving context after refreshing song paths: %#", [error localizedDescription]);
}
}
First, I assume you run that loop inside the NSManagedObjectContext performBlock method. Second, you need to save your changes to your NSManagedObjects context after you edit your objects.
Objective-C:
NSError *error = nil;
if ([[self managedObjectContext] save:&error] == NO) {
NSAssert(NO, #"Error saving context: %#\n%#", [error localizedDescription], [error userInfo]);
}
Swift:
do {
try managedObjectContext.save()
} catch {
fatalError("Failure to save context: \(error)")
}
Problem solved this way:
I removed all the hyphens from files' names. And the code started to work fine with the same loop. Also I converted files from mp3 to wav. But I suppose that problem existed because file can't include hyphen in its name.
Thanks everyone who answered!

how to add json file in ActionRequestHandler safari extinction

I am develop a add blocker app, so i want to add json file in my ActionRequestHandler class from document directory. In ActionRequestHandler class already have code that add blockerList.json which is in main bundle
actually main problem is this if i edit in blockerList.json then its not editable because of permission because this file is in main bundle so aap don't provide on editing in any file.So i generate a new file in document directory which is editable but i cant add it in safari extention. here is my code
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
NSItemProvider *attachment;
NSString *contentOfURL;
NSString *documentsFilePath = [self grabFilePath:#"Block.json"];
NSURL *documentsURL = [NSURL fileURLWithPath:documentsFilePath];
if ([documentsFilePath length] != 0) {
NSError *error;
// NSURL *url = [NSURL URLWithString:APP_DEFAULT_BLOCKS_URL];//[[NSURL alloc] initWithString:APP_DEFAULT_BLOCKS_URL]
contentOfURL = [NSString stringWithContentsOfURL:documentsURL encoding:NSUTF8StringEncoding error:&error];
if (error)
NSLog(#"Error reading remote json file: %#", error.localizedDescription);
}
if (contentOfURL != (id)[NSNull null] && contentOfURL.length != 0) {
attachment = [[NSItemProvider alloc] initWithItem:contentOfURL typeIdentifier:#"public.json"];
} else {
NSLog(#"URL not defined or accessible - using local JSON");
attachment = [[NSItemProvider alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"blockerList" withExtension:#"json"]];
}
NSExtensionItem *item = [[NSExtensionItem alloc] init];
item.attachments = #[attachment];
[context completeRequestReturningItems:#[item] completionHandler:nil];
}
- (NSString *)grabFilePath:(NSString *)fileName {
NSString *filePath = [[NSString alloc]initWithFormat:#"Documents/%#", fileName];
NSString *documentsFilePath = [NSHomeDirectory()stringByAppendingPathComponent:filePath];
return documentsFilePath;
}

Attempt to rename file in Documents directory has error "file:/..."

Below is the code I have written to change the name of any file stored in an iOS device "Documents" directory.
When renaming the file using this code, the prefix resolves to...
"file:/localhost/private/var/mobile/Applications/.../Documents/"
instead of the correctly formatted...
"file://localhost/private/var/mobile/Applications/.../Documents/"
I am losing a slash, and so the rename method fails!!!
I have rewritten this for both NSString and NSURL formats, and both methods present the identical error. I have tested this using the iOS Simulator and on device, and both tests present the identical error.
I suspect I am overlooking something simple, but cannot figure what it is - any help please?
- (void)alterFileNameOrExtension {
NSError *errorMove = nil;
NSError __autoreleasing *error = nil;
//note below - entity attribute document.dStringURL has a data type NSString
NSString *file = [document.dStringURL lastPathComponent];
NSString *fileName = [file stringByDeletingPathExtension];
NSString *fileExtension = [file pathExtension];
NSString *fileNameNew = nil;
//note below - self.tempFileComponent, self.tempFileName & self.tempFileExtension
//note below - are set in the (IBAction) method textFieldDidEndEditing:
//note below - self.tempFileComponent determines whether the user is attempting to change the file name or the file extension
if (self.tempFileComponent == 1) {
fileNameNew = [[self.tempFileName stringByAppendingPathExtension:fileExtension] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
} else if (self.tempFileComponent == 2) {
fileNameNew = [fileName stringByAppendingPathExtension:self.tempFileExtension];
} else {
NSLog(#"%# - %# - attempt to determine tempFileComponent has (possible undefined) E~R~R~O~R: %#_", self.className, NSStringFromSelector(_cmd), error.localizedDescription);
}
NSString *filePath = [document.dStringURL stringByDeletingLastPathComponent];
NSString *filePathNew = [filePath stringByAppendingPathComponent:fileNameNew];
BOOL move = [[NSFileManager defaultManager] moveItemAtPath:document.dStringURL toPath:filePathNew error:&errorMove];
if (!move) {
//handle error
} else {
//complete process
}
}
#
With assistance from #Mario, I have adjusted my code and include the working version below for the benefit of others...
#
NSError *errorMove = nil;
NSError __autoreleasing *error = nil;
NSString *file = [document.dStringURL lastPathComponent];
NSString *fileName = [file stringByDeletingPathExtension];
NSString *fileExtension = [file pathExtension];
NSString *fileNameNew = nil;
if (self.tempFileComponent == 1) {
fileNameNew = [self.tempFileName stringByAppendingPathExtension:fileExtension];
} else if (self.tempFileComponent == 2) {
fileNameNew = [fileName stringByAppendingPathExtension:self.tempFileExtension];
} else {
NSLog(#"%# - %# - attempt to determine tempFileComponent has (possible undefined) E~R~R~O~R: %#_", self.className, NSStringFromSelector(_cmd), error.localizedDescription);
}
NSURL *fileURLOld = [NSURL URLWithString:document.dStringURL];
NSURL *fileURLPrefix = [fileURLOld URLByDeletingLastPathComponent];
NSURL *fileURLNew = [fileURLPrefix URLByAppendingPathComponent:fileNameNew];
BOOL move = [[NSFileManager defaultManager] moveItemAtURL:fileURLOld toURL:fileURLNew error:&errorMove];
if (!move) {
//handle error
} else {
//complete process
}
The NSString path manipulation methods like stringByAppendingPathComponent expects file paths not URLs. It will remove double slashes as this is not a valid file path (although it is a valid URL).

Import .ics File and show in Calendar or UITableView

I retrieve an .ics file from a certain url. I'd like to present the information of this file in a calendar and/or list view in my own app. I had a look at iCal4Objc("https://github.com/cybergarage/iCal4ObjC") and parsed the information like this:
-(NSMutableArray *)getPlanFromURL:(NSURL *)url {
NSMutableArray *planEntries = [[NSMutableArray alloc]init];
NSString *storePath = [self loadICSAndReturnPathFromURL:url];
CGICalendar *parserCalendar = [[CGICalendar alloc]initWithPath:storePath];
for(CGICalendarObject *planObject in [parserCalendar objects]) {
for(CGICalendarComponent *component in [planObject components]) {
for (CGICalendarProperty *icalProp in [component properties]) {
NSString *icalPropName = [icalProp name];
NSLog(#"%#",icalPropName);
if([icalPropName isEqualToString:SUMMARY]) {
[self.summaryArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:LOCATION]) {
[self.locationArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:CATEGORIES]) {
[self.categoryArray addObject:[icalProp value]];
}
else if([icalPropName isEqualToString:DTSTART]) {
[self.startArray addObject:[icalProp dateValue]];
}
else if([icalPropName isEqualToString:DTEND]) {
[self.endArray addObject:[icalProp dateValue]];
}
}
}
}
for(int i = 0;i<[self.summaryArray count];i++) {
DECalEntry *entry = [[DECalEntry alloc]init];
entry.summary = [self.summaryArray objectAtIndex:i];
entry.roomInformation = [self.locationArray objectAtIndex:i];
entry.category = [self.categoryArray objectAtIndex:i];
entry.startDate = [self.startArray objectAtIndex:i];
entry.endDate = [self.endArray objectAtIndex:i];
if ([entry.category isEqualToString:#"Prüfung"]) {
entry.isExam = true;
}
else entry.isExam = false;
[planEntries addObject:entry];
}
return planEntries;
}
-(NSString *)loadICSAndReturnPathFromURL:(NSURL *)url {
NSURLRequest * urlRequest = [NSURLRequest requestWithURL:url];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
if (error == nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *storePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory, #"planData.ics"];
[data writeToFile:storePath atomically:YES];
return storePath;
}
NSLog(#"Error: %#",[error localizedDescription]);
return nil;
}
Since this is not very clean and it would be a pain to also implement UITableView and a calendar view to illustrate the parsed data i asked me whether there exists a framework that one of you knows which already can handle .ics files and shows them accordingly.
If you have an idea how to solve this issue less complicated and/or with less effort i would be really grateful.
Also have a look at my comment. At the moment the rrule property is not considered at all. But this is very important since it shows me if a event is repeated, until it is repeated and so on...
Nevermind i got it working myself by parsing the rrule property like i did it with the other properties and constructed a method which creates the right amount of objects i need by following the information that this property contains. Well i just think this was the only way because apparently the is no framework for importing and parsing .ics files. When i finish my project i might give it a shot for people who might face this one day.
To my knowledge there is no framework or control provided by Apple that displays .ics files, but once you construct an EKEvent, there is:
https://developer.apple.com/library/ios/documentation/EventKitUI/Reference/EKEventEditViewControllerClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40009571
Specifically, you want to take a look at EventKitUI.framework.

Resources