Custom Segue doesn't Play Sound - objective-c

I made a custom segue and I want it to play sound when changing views. Unfortunately, it doesn't. Method playSound works fine when I use it in View Controller. But i don't want to export it in every View Controller i need. How can i improve my code and why segue doesn't want to play sound?
#import "CustomSegue.h"
#import AVFoundation;
#interface CustomSegue()
#property (nonatomic, strong) AVAudioPlayer *player;
#end
#implementation CustomSegue
#synthesize player;
- (void) perform
{
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
[UIView transitionWithView:src.navigationController.view duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[src.navigationController pushViewController:dst animated:NO];
}
completion:NULL];
[self playSound];
}
- (void) playSound
{
int r = arc4random_uniform(7) + 1;
NSURL *soundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%i", r] ofType:#"caf"]];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUrl error:nil];
[self.player prepareToPlay];
[self.player play];
}

I bet your custom segue is released (by ARC) before the sound has a chance to play, and your audio player is released with it. The Life Cycle of a Segue is such that it is deallocated immediately after -performis executed.
What you need to do is keep the audio player around for a longer time. One way to do this is to add a (strong) reference to your AVAudioPlayer from an object that is not going to be deallocated for at least as long as the sound will play. For example, place the player in your app delegate, which sticks around as long as the app is running.
Try moving the player property and the -playsound method into your app delegate. The property should look something like:
#property (strong, nonatomic) AVAudioPlayer *player;
Then, in this segue, in place of [self playsound]; make a call to the app delegate with something like:
MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate];
[appDelegate playsound];

Related

AVPlayer plays sound but view is not shown in mac application

I'd like to play local movie in AVPlayer on macintosh app. I've created simple code but movie doesn't want to show played movie. It plays sound of the movie but there is no view visible. What am I missing?
It's my first playing simple app.
My code:
#implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSView *containerView = [[NSView alloc] initWithFrame:CGRectMake(0.0f, 0, 390.0f, 400.0f)];
NSString *videoPath = [[NSBundle mainBundle] pathForResource: #"Fatality.mp4" ofType:nil];
NSLog(#"%#", videoPath);
NSURL *fileURL = [NSURL fileURLWithPath:videoPath];
self.player = [AVPlayer playerWithURL:fileURL];
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
layer.frame = CGRectMake(0, 0, 1024, 768);
[self.view.layer addSublayer: layer];
[self.player play];
}
#end
And AppDelegate:
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (nonatomic,strong) IBOutlet MasterViewController *masterViewController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
self.masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
// 2. Add the view controller to the Window's content view
[self.window.contentView addSubview:self.masterViewController.view];
self.masterViewController.view.frame = ((NSView*)self.window.contentView).bounds;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#end
You have to add your containerView as a subview of the master view controllers view
[self.view addSubView:containerView];
A trick I often do while debugging is to set the background colour of a view I am interested in to something bright (red, yellow, cyan....) and then make sure that the view shows up where I expect it to be.

Activity Indicator problems? (SVProgress HUD)

I am trying to load a UIWebview and am trying to implement the SVProgress HUD when the webview is loading and then dismissing it when its loaded.I have almost completed it however when it loads the progress hud shows for a second and then dosent show and then shows for a second and so fourth, like its blinking I'm kinda stuck, check out my code.
In my .h:
#import <UIKit/UIKit.h>
#import "SVProgressHUD.h"
#interface ViewController2 : UIViewController <UIWebViewDelegate> {
//Instantiated the timer varibale inside the interface.
NSTimer *timer1;
IBOutlet UIWebView *webView;
}
//Instantiate the webview ans NSString link.
#property(nonatomic,retain) UIWebView *webView;
#property (strong, nonatomic) NSString *link;
and in my .m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
#synthesize webView;
- (void)viewDidLoad
{
[super viewDidLoad];
//Getting the link from the NSString called "link" and putting in the request.
NSString *link = [NSString stringWithString:self.link];
NSURL *URL = [NSURL URLWithString:link];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[webView loadRequest:request];
//Set the time for the loagind modal view.
timer1 = [NSTimer scheduledTimerWithTimeInterval:(1.0/2.0) target:self selector:#selector(loading) userInfo:nil repeats:YES];
//Webview Properties
//Webview's name is web, which was instantianted in the propeties section.
webView.ScalesPageToFit = true;
webView.backgroundColor = [UIColor pomegranateColor];
}
//When the UIWebview is loading present "Fetching Homework" alert, thanks to SVProgressHUD
-(void)loading {
if(!webView.loading)
[SVProgressHUD dismiss];
else
[SVProgressHUD showWithStatus:#"Loading Homework"];
}
I think that it could just be the timer, but I'm not sure, anyhelp would be greatly appreciated.
Thanks in advance.
You should use the web view delegate to know when the page ends loading instead of using a timer to check it each 0.5 seconds. Try it this way:
Begin the SVProgressHUD when inits the page loading
[SVProgressHUD showWithStatus:#"Loading Homework"];
Then remove it when the page finish loading.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[SVProgressHUD dismiss];
}
Don't forget that you also have to set your webview delegate as this:
webView.delegate = self;

Unrecognized Selector in AVplayer setNumberOfLoops Method

When calling the numberOfLoops method like so:
[_player setNumberOfLoops:-1];
I get the following error:
-[AVPlayer setNumberOfLoops:]: unrecognized selector sent to instance 0x7d52d30
How can this be fixed?
Code:
Header:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController {
}
#property (strong, nonatomic) AVAudioPlayer *player;
- (IBAction)playMusic:(id)sender;
#end
Implementation:
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)playMusic:(id)sender {
_player = [AVPlayer playerWithURL:[NSURL URLWithString:#"http://urlpath.wav"]];
[_player setNumberOfLoops:-1];
[_player prepareToPlay];
[_player play];
}
#end
Thank you for your time,
Yoni201.
You've created an instance of AVPlayer, not an instance of AVAudioPlayer. It looks like you want to be creating an AVAudioPlayer instead (as is indicated by your choice of that class for the actual player property on your class. AVAudioPlayer actually has the numberOfLoops property, while AVPlayer does not. For more information, see the documentation for AVAudioPlayer and AVPlayer.
AVPlayer doesn't have a numberOfLoops property. That is a property of `AVAudioPlayer. Don't ignore compiler warnings when you build your app.
Also, you defined _player to be an AVAudioPlayer but you alloc/init AVPlayer.
Change your code to:
NSError *error = nil;
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://urlpath.wav"] error:&error];
if (player) {
[player setNumberOfLoops:-1];
[player prepareToPlay];
[player play];
self.player = player;
} else {
NSLog(#"Error create audio player: %#", error);
}
I think that the method you are calling doesn't exist (acceosing to your error).
Try: _player.numberOfLoops=-1

How Do I Update UIWebView After viewDidLoad?

This is my first iOS app, so I am probably missing something very simple. Please be kind. I have been tearing my hair out and I could really use some help.
Overview Of App
Basically, this is a single page application that just loads a UIWebView. I have an external accessory (bluetooth barcode scanner) that I connect and basically what I want to do is when the the app receives a scan, I want to call a method in my ViewController and update the UIWebView accordingly.
What Is Working
I am able to connect the scanner, load the first view, which loads the initial webpage, scan a barcode and call the method in my controller.
My Problem
I can't seem to figure out how to update the UIWebView from the method in my controller. It logs the url string to my debugger area, but never actually updates the webview. I am pretty sure I have some delegation wrong or something with my webview instance. There must be some glue code here that I am missing.
My Code HelloWorldViewController.h
#import <UIKit/UIKit.h>
#import "KScan.h"
#interface HelloWorldViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIWebView *page;
IBOutlet UILabel *myLabel;
Boolean IsFirstTime;
KScan *kscan;
}
- (void)setFirstTime;
- (void)DisplayConnectionStatus;
- (void)DisplayMessage:(char *)Message;
- (void)newBarcodeScanned:(NSString *)barcode;
- (void)loadBarcodePage:(NSString *)barcode;
#property (nonatomic, retain) KScan *kscan;
#property (nonatomic, retain) UIWebView *page;
#property (nonatomic, retain) UILabel *myLabel;
#end
My Code HelloWorldViewController.m
#import "HelloWorldViewController.h"
#import "common.h"
#implementation HelloWorldViewController
#synthesize myLabel;
#synthesize page;
#synthesize kscan;
- (void)setFirstTime
{
IsFirstTime = true;
}
- (void)viewDidLoad
{
self.kscan = [[KScan alloc] init];
[super viewDidLoad];
page.scrollView.bounces = NO;
//page.delegate = self;
[page loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://192.168.0.187:3000"]]];
}
- (void) newBarcodeScanned:(NSString *)barcode
{
NSLog(#"%s[%#]",__FUNCTION__, barcode);
[self loadBarcodePage:barcode];
}
- (void)loadBarcodePage:(NSString *)barcode
{
NSLog(#"%s",__FUNCTION__);
NSString *url = [[NSString alloc] initWithFormat:#"http://www.google.com/%#", barcode];
NSLog(#"%#", url);
[page loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
}
- (void)viewDidUnload
{
[myLabel release];
myLabel = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
- (void)dealloc {
[page release];
[kscan release];
[myLabel release];
[super dealloc];
}
#end
Basically, I am just trying to load google.com into my page webview when scanning a barcode. My log statements are being logged with the correct URL, but this line of code doesn't work.
[page loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
I am not getting any errors and my xCode debugging skills are not the greatest.
Any help would be greatly appreciated!
It looks like your webview is never allocated, or added to your main view. You are probably talking to a nil instance.
Unless your web view comes from a XIB file (which I doubt since it is not declared as an IBOutlet in your heder file) try adding something like this to your viewDidLoad:
self.page = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.page];

iOS 5 movie player

Hi everyone i got a problem to play a video in iOS 5. When I'm building the program i get a warning "local declaration of hides instance variables" and when i run the program and tap the button i get a "SIGABRT". And i don't know what to do, all the help i can get is aprriciated!!
Thx in advance
MY .h file
#import <MediaPlayer/MediaPlayer.h>
#interface MainViewController : UIViewController {
MPMoviePlayerController *moviePlayer;
}
-(IBAction)Video:(id)sender;
#end
MY .m file
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
-(IBAction)Video:(id)sender {
MPMoviePlayerController *moviePlayer;
NSString *path = [[NSBundle mainBundle] pathForResource:#"big-buck-bunny-clip" ofType:#"m4v"];
NSURL *videoURL = [NSURL fileURLWithPath:path];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[moviePlayer setControlStyle:MPMovieControlStyleDefault];
[moviePlayer.view setFrame: self.view.bounds];
[self.view addSubview: moviePlayer.view];
[moviePlayer prepareToPlay];
[moviePlayer play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
local declaration of hides instance variables
remove the first line of your -(IBAction)Video:(id)sender method.
MPMoviePlayerController *moviePlayer; //this line;
because you already have declared such variable in your .h file.
Means you declared the same variable names two times, one in .h file and another in .m file.