how to play an MP3 when a UIButton is tapped? - ios4

Can anyone please give me sample code of how sound is played with a UIButton being tapped?
I would like to play an MP3 file using AVAudioPlayer

something like this should get you started. Add this to your view controller, then hook up the button to the playAudio action in interface builder.
in your header .h
#import <AVFoundation/AVFoundation.h>
#interface ClassName {
...
AVAudioPlayer *audioPlayer;
}
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;
- (IBAction) playAudio;
in your .m
#synthesize audioPlayer;
- (IBAction) playAudio {
NSURL *url = [[NSBundle mainBundle] URLForResource:#"audio" withExtension: #"m4a"];
if (!url){NSLog(#"file not found"); return;}
NSError *error;
self.audioPlayer = [[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error] autorelease];
[audioPlayer play]
}

//ViewController.h ,write below code
#interface ViewController : UIViewController<AVAudioRecorderDelegate,AVAudioPlayerDelegate>
//assign property to player
#property(nonatomic,retain) AVAudioPlayer *player;
//then write in ViewController.m file in ViewDidLoad Method
NSError *soundError;
NSString *path=[[NSBundle mainBundle]pathForResource:#"soundFileName" ofType:#"mp3"]; //.mp3 file for player
NSURL *file=[[NSURL alloc]initFileURLWithPath:path]; //path
_player=[[AVAudioPlayer alloc]initWithContentsOfURL:file error:&soundError]; //player Object
if(_player == nil)
{
NSLog(#"player is empty because of %#",soundError);
}
else
{
[_player play];
_player.volume=1.0;
[_player setDelegate:self];
}
// for stop player you can use
// [_player stop]; //uncomment this line when you wants to stop it.

Related

Child context changes are propagated to other child context (same hierarchy level) without merge

I am implementing CoreData stack according to
https://stackoverflow.com/a/24663533 (option A from image) but it works in an unexpected way.
I have rootContext (NSPrivateQueueConcurrencyType), it has 2 children: uiContext (NSMainQueueConcurrencyType) for objects fetching and syncContext (NSPrivateQueueConcurrencyType) for asynchronous data editing.
As I thought, when I save something in syncContext in performBlock (background queue), changes will be propagated to rootContext, but uiContext will not be changed until I observe NSManagedObjectContextDidSaveNotification and merge changes from notification. But changes are reflected immediately after syncContext save.
My first question is: why is uiContext updated without manual merge?
My second question: why is rootContext modified on background (not on main thread) after syncContext save? Some time ago I asked question about "CoreData could not fulfill a fault" problem with MagicalRecord 'CoreData could not fulfill a fault' error with MagicalRecord but I didn't receive answer, so I decided to find solution without external libraries.
It seems, that main thread is reading object properties and the same object is deleted on background whilst operators on main thread still don't return control.
Here is my source code:
#import <CoreData/CoreData.h>
#import "DataLayer.h"
#import "Person.h"
#interface DataLayer ()
#property (nonatomic, strong) NSManagedObjectModel *model;
#property (nonatomic, strong) NSPersistentStoreCoordinator *coordinator;
#property (nonatomic, strong) NSManagedObjectContext *rootContext;
#property (nonatomic, strong) NSManagedObjectContext *uiContext;
#property (nonatomic, strong) NSManagedObjectContext *syncContext;
#end
#implementation DataLayer
+ (void)load
{
[self instance];
}
+ (DataLayer *)instance
{
static DataLayer *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[DataLayer alloc] init];
});
return instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self initModel];
[self initCoordinator];
[self initContexts];
[self observeContextSaveNotification];
[self startTesting];
}
return self;
}
- (void)initModel
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Model" withExtension:#"momd"];
self.model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
- (void)initCoordinator
{
NSURL *directory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [directory URLByAppendingPathComponent:#"Model.sqlite"];
NSError *error = nil;
self.coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model];
if (![self.coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
- (void)initContexts
{
self.rootContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.rootContext.persistentStoreCoordinator = self.coordinator;
self.uiContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.uiContext.parentContext = self.rootContext;
self.syncContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.syncContext.parentContext = self.rootContext;
}
- (void)observeContextSaveNotification
{
// [[NSNotificationCenter defaultCenter] addObserver:self
// selector:#selector(onManagedObjectContextDidSaveNotification:)
// name:NSManagedObjectContextDidSaveNotification
// object:nil];
}
- (void)onManagedObjectContextDidSaveNotification:(NSNotification *)notification
{
// NSManagedObjectContext *context = notification.object;
// if (context != self.uiContext) {
// [self.uiContext mergeChangesFromContextDidSaveNotification:notification];
// }
}
- (void)startTesting
{
NSArray *personsBeforeSave = [self fetchEntities:#"Person" fromContext:self.uiContext];
NSLog(#"Before save: %i persons in syncContext", [personsBeforeSave count]); // Before save: 0 persons in syncContext
[self.syncContext performBlock:^{
Person *person = [NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:self.syncContext];
person.firstName = #"Alexander";
NSError *error = nil;
[self.syncContext save:&error];
if (error) {
NSLog(#"Error during save: %#", error);
}
NSArray *personsAfterSaveFromBackground = [self fetchEntities:#"Person" fromContext:self.rootContext];
NSLog(#"After save from background: %i persons in rootContext", [personsAfterSaveFromBackground count]); // After save from background: 1 persons in rootContext
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *personsAfterSaveFromMain = [self fetchEntities:#"Person" fromContext:self.uiContext];
NSLog(#"After save from main: %i persons in uiContext", [personsAfterSaveFromMain count]); // After save from main: 1 persons in uiContext
});
}];
}
- (NSArray *)fetchEntities:(NSString *)entity fromContext:(NSManagedObjectContext *)context
{
NSError *error = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entity];
NSArray *result = [context executeFetchRequest:request error:&error];
if (error) {
NSLog(#"Error during fetch %#: %#", entity, error);
return nil;
}
return result;
}
#end
They are not being merged into the UI context. You are manually fetching them.
When you save in the syncContext, the data gets pushed up into the rootContext. The data is NOT merged into the uiContext. However, when you perform the fetch, the fetch pulls data down from the parent context.
You can get the objects in a context with registeredObjects.

Not accessing value from Object

I have a NSObject called GettingHere which has a NSString *content.
I then have a UIViewController on which I create a button programatically as follows (this button working as intended):
byAirButton = [UIButton buttonWithType:UIButtonTypeCustom];
byAirButton.tag = 1;
byAirButton.frame = CGRectMake(25, 140, 280.f, 40.f);
UIImage *airButton = [UIImage imageNamed:#"gettingHereByAirButton.png"];
[byAirButton setBackgroundImage:airButton forState:UIControlStateNormal];
[self.view addSubview:byAirButton];
[byAirButton addTarget:self action:#selector(byAirButtonClicked) forControlEvents:UIControlEventTouchUpInside];
For the action:#selector(byAirButtonClicked), I do the following. gettingHere is an instance of the GettingHere object.
- (void) byAirButtonClicked
{
gettingHere.content = #"This is how to get here by Air";
NSLog(#"Content: %#", gettingHere.content);
[self performSegueWithIdentifier:#"gettingHereSegue" sender:self];
}
The idea is to set the content for my GettingHere object and then just call that from the next view (GettingHereViewController) when the user clicks the byAirButton.
This NSLog shows that content is being set.
In my prepareForSegue, I do the following:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"gettingHereSegue"])
{
NSLog(#"Content to be passed: %#", gettingHere.content);
GettingHereViewController *vc = (GettingHereViewController *)segue.destinationViewController;
vc.gettingHere.content = gettingHere.content;
}
}
The segue works fine, but the NSLog shows my gettingHere object values as being (null).
Can anyone tell me where I am going wrong please? I have stepped through it several times but can't figure out where I am going wrong.
EDIT: Here is how I instantiate the GettingHere Object.
In the SubNavViewController.h
#import "GettingHereContent.h"
#interface SubNavViewController : UIViewController
#property GettingHereContent *gettingHere;
In the SubNavViewController.m
#import "SubNavViewController.h"
#import "GettingHereViewController.h"
#import "GettingHereContent.h"
#interface SubNavViewController ()
#end
#implementation SubNavViewController
#synthesize gettingHere;
And here is how I create the GettingHere Object:
GettingHere.h
#import <Foundation/Foundation.h>
#interface GettingHereContent : NSObject
#property (nonatomic, strong) NSString *content;
#end
GettingHere.m
#import "GettingHereContent.h"
#implementation GettingHereContent
#synthesize content;
#end
You never alloc init your gettingHere property. Try this in your init method of your VC
gettingHere = [[GettingHereContent alloc] init];
Also don't forget to release it: answer from here: alloc + init with synthesized property - does it cause retain count to increase by two?
#interface Foo : Bar {
SomeClass* bla;
}
#property (nonatomic, retain) SomeClass* bla;
#end
#implementation Foo
#synthesize bla;
-(id)init {
...
bla = [[SomeClass alloc] init];
...
}
-(void)dealloc {
[bla release];
...
[super dealloc];
}

I can't seem to get audio to work in my app? I'm using AVAudio framework

Help guys :) I've tried absolutely everything to get the audio with AVAudioPlayer to work in my app. For some reason it will not play on the iPhone simulator. The code is as follows-
#import "ViewController.h"
#import "AVFoundation/AVFoundation.h"
#interface ViewController ()
{
AVAudioPlayer *avPlayer;
}
#end
#implementation ViewController
#synthesize myProgressView;
#synthesize sliderVolumeOutlet;
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *stringPath = [[NSBundle mainBundle]pathForResource:#"audioapp" ofType:#"mp3"];
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
[avPlayer setNumberOfLoops:1];
[avPlayer setVolume:self.sliderVolumeOutlet.value];
[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(updateProgress) userInfo:nil repeats:YES];
}
The song itself is in the project file, I really don't know what I'm doing wrong.
Check for the error and try it
-(IBAction) playAudio{
NSError *error;
NSURL *url = [NSURL fileURLWithPath:self.audioName];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.delegate = self;
if (error)
NSLog(#"Error: %#", [error localizedDescription]);
else
[audioPlayer play];
}

Pass a UIWebView request using prepareForSegue

I 'm new to IOS and Objective C.
The scenario is I have 2 buttons, which open (with segue) 2 view controllers containing a UIWebview.
I thought is better to do it with 1 UIWebView so I tried to pass the request object of the webvew and use only one webview controller.
so I got the wwwBtn (UIButton that opens a site) and fbBtn (UIButton that goes to a Facebook URL) my viewController and the wwwWebViewController which contains th UIWebView.
Here is how I did it.
The viewController.h file :
#interface ViewController : UIViewController {
UIButton *wwwBtn;
UIButton *fbButton;
}
#property (retain, nonatomic) IBOutlet UIButton *wwwBtn;
#property (retain, nonatomic) IBOutlet UIButton *fbBtn;
The ViewController.m file :
#import "ViewController.h"
#import "wwwWebViewController.h"
#implementation ViewController
#synthesize wwwBtn;
#synthesize fbBtn;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"web"]) {
NSString *urlstr=#"http ://www.google.com";
wwwWebViewController *vc = [segue destinationViewController];
vc.urlStr = urlstr;
} else if ([[segue identifier] isEqualToString:#"fb"]) {
NSString *urlstr = #"http://www.facebook.com";
wwwWebViewController *vc = [segue destinationViewController];
vc.urlStr = urlstr;
}
}
the wwwWebViewController.h file :
#interface wwwWebViewController : UIViewController {
UIWebView *webView;
}
#property (retain, nonatomic) IBOutlet UIWebView *webView;
The wwwWebViewController.m file :
- (void)viewDidLoad
{
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
[super viewDidLoad];
}
Do as the following, you will assign this class to the destination UIViewControllers that you will need to pass the NSString *urlstr to them:
WebViewController.h
#interface WebViewController : UIViewController {
NSString *urlstr;
}
#property (strong, nonatomic) IBOutlet UIWebView *WebView;
#property (strong, nonatomic) NSString *urlstr;
WebViewController.m
#implementation WebViewController
#synthesize WebView;
#synthesize urlstr;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSURL *url = [NSURL URLWithString:urlstr];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.WebView loadRequest:requestObj];
}
Now it's time to create two segues from my main storyboard class InfoViewController to the destination class WebViewController, in my case I've created three segues but only two are using the WebViewController class.
You've also to give the segues a spacial Identifier for each to target them programmatically in the main class InfoViewController.
let's check out how the InfoViewController : UITableViewController will look like:
InfoViewController.m
#import "InfoViewController.h"
#import "WebViewController.h"
#interface InfoViewController ()
#end
#implementation InfoViewController
#synthesize AboutCell = _AboutCell;
#synthesize CGCell = _CGCell;
#synthesize FTACell = _FTACell;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *AboutCellClicked = [self.tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *CGCellClicked = [self.tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *FTACellClicked = [self.tableView cellForRowAtIndexPath:indexPath];
if (AboutCellClicked == _AboutCell) {
[self performSegueWithIdentifier:#"AboutPush" sender:self];
} else if (CGCellClicked == _CGCell) {
[self performSegueWithIdentifier:#"CGPush" sender:self];
} else if (FTACellClicked == _FTACell) {
[self performSegueWithIdentifier:#"FTAPush" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
WebViewController *webController = [[WebViewController alloc] init];
if ([[segue identifier] isEqualToString:#"CGPush"]) {
NSString *urlstr=#"http://www.google.com";
webController = [segue destinationViewController];
webController.urlstr = urlstr;
} else if ([[segue identifier] isEqualToString:#"FTAPush"]) {
NSString *urlstr=#"http://www.yahoo.com";
webController = [segue destinationViewController];
webController.urlstr = urlstr;
}
}
#end
I hope this will solve your problem, If you have any question do not hesitate to ask.

navigationItem not showing on popoverController

The navigationbar is failing to appear, works fine in a UITableView, but fails inside a popoverController
Initiate a popover popoverController in UIViewController
-(IBAction) btnShowMovies:(id) sender {
if (self.popoverController == nil) {
teamAController *movies =
[[teamAController alloc]
initWithNibName:#"teamAController"
bundle:[NSBundle mainBundle]];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:movies];
popover.delegate = self;
[movies release];
self.popoverController = popover;
[popover release];
}
CGRect popoverRect = [self.view convertRect:[btn frame]
fromView:[btn superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 100);
[self.popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
}
teamAController.h
#interface teamAController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *tableView;
NSArray *theArray;
}
#property (nonatomic, retain) NSArray *theArray;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
-(void) createArray;
teamAController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title= #"FooBarExtreme";
self.contentSizeForViewInPopover = CGSizeMake(250.0, 300.0);
[self createArray];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
Everything works, I have lovely table with images etc, correct sized and placed popover just no title bar..... ?
I found the solution/problem by following the tutorial at http://mobiforge.com/designing/story/using-popoverview-ipad-app-development.
Worth noting that I found this the most comprehensive one on creating uiPopoverController with uiNavigationBar elements from UIButtons.
The issue is that the popover itself belongs to the view that calls it. The content is derived from the xlib/view you load into it. But not the titlebar. You call that in the parent view view.
This code is in the main view and is called from the UIButton
// BookMarksViewController is the class that contains the code/xib for the popover's content
// Of overarching importance is creating it as a UITableViewController
if (self.popoverController == nil) {
BookMarksViewController *bookMarksViewController =
[[BookMarksViewController alloc]
initWithNibName:#"BookMarksViewController"
bundle:[NSBundle mainBundle]];
// Here's the rub: because in effect this view is controlling the popover
// we have to assign nav bar stuff here. Sigh.
bookMarksViewController.navigationItem.title = #"Territories";
UINavigationController *navController =
[[UINavigationController alloc]
initWithRootViewController:bookMarksViewController];
bookMarksViewController.contentSizeForViewInPopover = CGSizeMake(320, 400);
UIPopoverController *popover =
[[UIPopoverController alloc]
initWithContentViewController:navController];
popover.delegate = self;
[bookMarksViewController release];
[navController release];
self.popoverController = popover;
[popover release];
}
CGRect sourceRect = [self.view convertRect:[btn frame] fromView:[btn superview]];
[self.popoverController presentPopoverFromRect:sourceRect
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

Resources