Spritekit get back to rootViewController - ios

I am currently learning with SpriteKit. I have a background music player instance at main ViewController. However, when I tried to access back to it from SKScene class, I cannot stop/change the player.
ViewController *vc = (ViewController *) self.view.window.rootViewController;
AVAudioPlayer *player = vc.backgroundMusicPlayer;
[player stop]; //nothing happened
I am new to iOS dev, what is the way for managing SpriteKit background music player? Thanks!

I would recommend using a background music player singleton, e.g.
BackgroundMusicPlayer.h
#interface BackgroundMusicPlayer : NSObject
+ (instancetype)sharedPlayer;
#property (nonatomic, strong) AVAudioPlayer *audioPlayer;
#end
BackgroundMusicPlayer.m
#implementation BackgroundMusicPlayer
+ (instancetype)sharedPlayer
{
static BackgroundMusicPlayer *sharedPlayer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPlayer = [self new];
});
return sharedPlayer;
}
#end
Then you can access your audio player from anywhere by calling [[BackgroundMusicPlayer sharedPlayer] audioPlayer].

Related

How to play an video in an AVPlayer using the videoID for the searched item?

I built an iOS app for showing the video for the searched item, the problem occurred is as follows:
I used the YouTube data api and extracted the videoId.
I am not able to add this to an AVPlayer (but when YouTube player used I was able to add the videoId, for example like this:
[self.playerView loadWithVideoId:self.strngvideoId];
[self.view addSubview:_playerView];
I want to use only AVPlayer and no other players, how can fix this issue?
I want to pass the videoId in the AVPlayer and play the video.
If you want to play the video you have to use AVPlayerViewController.First import AVKit framework in your project.Below code works perfectly.
In ViewController.h I imported the AVKit framework.Before that we need to add in Target->BuildPhases->Link Binary With Libraries
ViewController.h
#import <UIKit/UIKit.h>
#import <AVKit/AVKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) AVPlayerViewController *playerViewController;
- (IBAction)actionPlayVideo:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController (){
NSURL *vedioURL;
}
#end
#implementation ViewController
#synthesize playerViewController;
- (IBAction)actionPlayVideo:(id)sender{
vedioURL =[NSURL fileURLWithPath:strngvideoId];
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:vedioURL];
AVPlayer* playVideo = [[AVPlayer alloc] initWithPlayerItem:playerItem];
playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.player = playVideo;
playerViewController.player.volume = 0;
playerViewController.view.frame = self.view.bounds;
[self.view addSubview:playerViewController.view];
[playVideo play];
}
Playing Video

iOS. SpriteKit: How to use the same emitter in all game scenes

I'm using SpriteKit and Xcode 6 to develop a game. I have a single sks file that I want to use in all game scenes. If I add the emitter into each scene after I present it, the emitter stops in the old scene and stars new in the new scene, because it is created in each scene.
Therefore I tried to use a singleton class for creating the emitter only once and using it in all game scenes. I created a super class for all game scenes and create the emitter in that super class for all child scenes. But, what I tried to get with this steps is not working. the emitter still stops and starts new in every new scene, because it still created new in each scene.
How can I use the same emitter bei creating it only once and use it in all my game scenes whithout stoping and new starting the emitter?
Here my code. What I'm missing?
P.S. The same technique is working well with an audio player! http://www.galloway.me.uk/tutorials/singleton-classes/
//MyEmitterNode.h
#import <SpriteKit/SpriteKit.h>
#interface MyEmitterNode : SKEmitterNode
+(instancetype)sharedEmitterNode;
- (void)addEmitterNodeIntoScene:(SKScene *)scene;
#end
//--
//MyEmitterNode.m
#import "MyEmitterNode.h"
#interface MyEmitterNode ()
#property (strong, nonatomic) SKEmitterNode *mEmitterNode;
#end
#implementation MyEmitterNode
+ (instancetype)sharedEmitterNode {
static MyEmitterNode *sharedEmitterNode = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedEmitterNode = [[self alloc] init];
});
return sharedEmitterNode;
}
- (void)addEmitterNodeIntoScene:(SKScene *)scene {
self.mEmitterNode = [NSKeyedUnarchiver unarchiveObjectWithFile:[[NSBundle mainBundle] pathForResource:#"MyParticle" ofType:#"sks"]];
[scene addChild:self.mEmitterNode];
}
#end
// -- MyScene: super classe for all game scenes
//MyScene.m
- (void)didMoveToView:(SKView *)view {
[[MyEmitterNode sharedEmitterNode] addEmitterNodeIntoScene:self];
}
// -- MyFirstScene: child class from MyScene
//MyFirstScene.m
- (void)didMoveToView:(SKView *)view {
[super didMoveToView:view];
// do other stuff
}
// -- MySecondScene: child class from MyScene
//MySecondScene.m
- (void)didMoveToView:(SKView *)view {
[super didMoveToView:view];
// do other stuff
}

Singleton not persisting across viewcontrollers/spritekit scene

This is a SpriteKit game.
I am using a singleton to store a single 'Show' object to be accessible throughout the game. The 'Show' class has an NSString property 'showTitle'.
In ViewController1, I set the 'Show' property of the singleton. To test.. I then printed out a string property of 'Show' (showTitle) from the singleton and it prints the string correctly.
After segueing to ViewController2, I again print out the same string property of 'Show' (showTitle) from the singleton and it again prints the string correctly.
THEN, the spritekit scene is initialized from ViewController2. I attempt to print the same string property
of 'Show' from the singleton, and it prints null instead of the string. I went further and segued to ViewController3, tried to print the showTitle from the singleton..... NULL.
Why am I able to access the 'Show' property of the singleton in ViewControllers 1 & 2, but not from within the sprite kit scene or ViewController3. Where am I going wrong?
ShowSingleton.h
#import <Foundation/Foundation.h>
#import "Show.h"
#interface ShowSingleton : NSObject
#property (nonatomic, strong) Show* currentShow;
+(ShowSingleton *)singleton;
#end
ShowSingleton.m
#import "ShowSingleton.h"
#implementation ShowSingleton
#synthesize currentShow;
+(ShowSingleton *)singleton {
static dispatch_once_t pred;
static ShowSingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[ShowSingleton alloc] init];
});
return shared; }
#end
ViewController1:
- (IBAction)openShow:(UIButton*)sender
{
//showsarray is an array of 'Show' objects retrieved through core data in another class
[ShowSingleton singleton].currentShow = [showsarray objectAtIndex:sender.tag];
NSLog(#"Opened show: %#", [ShowSingleton singleton].currentShow.showTitle);
//The above line correctly prints the selected showTitle from the singleton
}
After openShow: completes, a segue opens ViewController2. ViewController2 initializes the SpriteKit scene.
ViewController2:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
SKView * skView = (SKView *)self.view;
if (!skView.scene)
{
skView.showsFPS = YES;
skView.showsNodeCount = YES;
SKScene * scene = [iMarchMyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
[skView presentScene:scene];
}
}
- (void)viewDidLoad
{
//The following line correctly prints the showTitle from ViewController2
NSLog(#"processing show: %#", [ShowSingleton singleton].currentShow.showTitle);
}
myScene.m:
-(id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
if ([ShowSingleton singleton].currentShow)
{
//This always gets called, which tells me the object exists, but null is printed for showTitle
NSLog(#"show title from scene: %#", [ShowSingleton singleton].currentShow.showTitle);
}
}
return self;
}
Consider using this singleton implementation:
// ShowSingleton.h
#import <Foundation/Foundation.h>
#import "Show.h"
#interface ShowSingleton : NSObject
+ (instancetype)singleton;
#end
// ShowSingleton.m
#import "ShowSingleton.h"
#implementation ShowSingleton
+ (instancetype)singleton {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#end
ShowSingleton *shared is scoped to the method, not the class.
Try declaring it as a class property of your AppDelegate, and then override the getter with something like this:
#property (strong, nonatomic) Show *currentShow;
and then override the getter as:
+(Show*)currentShow
{
static id _currentShow = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
currentShow = [showsarray objectAtIndex:sender.tag]; //probably not this, not sure where in your app flow this info is ready...
});
return _currentShow;
}
Now you can leverage the proper singleton UIApplicationDelegate that Apple provided, and end up with an unchanging instance of Show that is accessible anywhere in your app by calling (YourApplicationClass*)[[UIApplication sharedApplication] currentShow]
Keep in mind that dispatch_once is tied to the App Lifecycle. It will be purged when and only when the app terminates, which may be while your app is in the background.
Singleton's are fiddly to implement correctly, and even more difficult to know when their use is actually warranted, so you may want to take a look at NSUserDefaults to see if it has something you could bend to your purposes instead.

iOS: AVAudioPlayer can it only play one file?

It´s only possible to give the AVAudioPlayer an URL of the file to play via it´s init method.
And as I understand it if one want´s to play another file, the old instance needs to be stopped from playing, and a new instance of AVAudioPlayer initialized with the URL to the new audiofile to play.
But this is making it hard cause I have a navigation controller, and when the user leaves the player screen the sound should keep playing, and it does. But when the user selects a new audio file to play from the tableview a new instance of the viewController and AVAudioPlayer is initalized and I have no way of stopping the old from playing. How do I get this working?
You can do something like this
In your v1AppDelegate.h file add,
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#interface v1AppDelegate : UIResponder <UIApplicationDelegate>
{
AVAudioPlayer *myAudioPlayer;
}
#property (nonatomic, retain) AVAudioPlayer *myAudioPlayer;
#property (strong, nonatomic) UIWindow *window;
#end
Now in your v1AppDelegate.m file add this
#import "v1AppDelegate.h"
#import <AVFoundation/AVFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#implementation v1AppDelegate
#synthesize window = _window;
#synthesize myAudioPlayer;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//start a background sound
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"Startsound" ofType: #"m4a"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath ];
myAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
myAudioPlayer.numberOfLoops = -1; //infinite loop
[myAudioPlayer play];
// Override point for customization after application launch.
return YES;
}
If you wish to stop or start this music from anywhere else in your code then simply add this
#import "v1AppDelegate.h"
- (IBAction)stopMusic
{
v1AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.myAudioPlayer stop];
}
- (IBAction)startMusic
{
v1AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.myAudioPlayer play];
}

ios single AVAudioPlayer

I'm working on an ios app with uitabviewcontroller that plays some music. I don't want each tab viewcontroller to create it's own audio player. I want to have one single audio player and have all the viewcontrollers share it.
so I have created a class called player, which would initiate avaudioplayer with the song url and plays the song,
#import <AVFoundation/AVFoundation.h>
#interface player : NSObject {
AVAudioPlayer *theMainAudio;
}
-(void)playSong:(NSString *)songName;
#end
I want to create only one instance of this class and all my viewcontrollers share it. I've tried creating it in my delegate,
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
player *theMainPlayer;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, retain) player *theMainPlayer;
#end
in .m file,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//some other stuff here....
theMainPlayer = [[player alloc]init];
return YES;
}
and then I called it in my viewcontrollers,
player myPlayer = ((AppDelegate *)[UIApplication sharedApplication].delegate).theMainPlayer;
but this didn't work.
can anyone tell me what's wrong with what I've done or if there is any other way to do what I want to do, which is to create a player object and share it among all of my viewcontrollers.
Thanks
create a singleton, in your player.m
#import "player.h"
#implementation player
static player *sharedInstance = nil;
+ (player *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
- (id)init
{
self = [super init];
if (self) {
// Work your initialising here as you normally would
}
return self;
}
-(void)playSong:(NSString *)songName
{
// do your stuff here
}
to use this class, just import the player.h
[[player sharedInstance] playSong:#"something"];
How did it go wrong? To me it seems the last line would cause compile error. You should add asterisk for class declaration :
player * myPlayer = ((AppDelegate *)[UIApplication sharedApplication].delegate).theMainPlayer;
Other than that, I didn't catch anything.
But I prefer using Singleton pattern for cases like this.
Reference :
http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/Singleton.html
http://www.galloway.me.uk/tutorials/singleton-classes/

Resources