ChromeCast delegates are not called when the app is in the background - ios

I am working on an application in which I will connect to the T.V using ChromeCast device, to achieve this I have used GoogleCast FrameWork in my project,
I am facing a problem when my app goes to background
Am writing piece code in this method for calling a method to mute the audio
- (void)applicationDidEnterBackground:(UIApplication *)application {
HomeViewController *lHomeViewController = [[HomeViewController alloc] init];
_mediaControlChannel = [[GCKMediaControlChannel alloc] init];
[lHomeViewController muteAudio];
}
It calls the method in the home view controller, where in which I wrote the below code
-(void) muteAudio {
[self.deviceManager setMuted:YES];
}
But the audio is not muted and it is not calling the below delegate method.
- (void)mediaControlChannelDidUpdateStatus:(GCKMediaControlChannel *)mediaControlChannel
Please suggest me

You are creating a new instance of the HomeViewController in the applicationDidEnterBackground app delegate method. You need to send the muteAudio message to the running instance of HomeViewController.
For this, the best solution would be to use NSNotificationCenter.
In your HomeViewController's viewDidLoad or viewWillAppear method, use the following line:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(muteAudio)
name: UIApplicationDidEnterBackgroundNotification
object: nil];
This will automatically call the muteAudio method when the application enters background.
Read more about NSNotificationCenter here.
Read more about the application status notifications here.

Related

How to use a function from the view controller in the app delegate?

I have an app that is connected to a device by Bluetooth.
I want the app to send a command that indicates that the app is going to close in the app delegate method : (void)applicationWillTerminate:(UIApplication *)application {
One word: NSNotificationCenter
I'm not sure what you need to set the data to because you can't pass the data seamlessly via NSNotificationCenter; however you were going to figure that out in your UIApplicationDelegate anyway, so why can't you do it in the view controller directly.
In your case there is no need to do anything in your application delegate, because this notification allows your view controller to act as a mini app delegate (in that you can get termination status and so on).
Therefore...
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(TXdata:) name:UIApplicationWillTerminateNotification object:nil];
}
- (void)TXdata:(NSString *) data {
NSString *newData = data;
if (newData == nil) {
newData = ... // Figure out what your data should be here.
}
//do whatever with your data here.
}
I quote:
UIApplicationWillTerminateNotification
Posted when the app is about to terminate.
This notification is associated with the delegate applicationWillTerminate: method. This notification does not contain a userInfo dictionary.
You should create a class separate from the view controller and app delegate to handle the BLE communication. That way, the view controller and the app delegate can both have access and provide a better "separation of concerns" for your app. This new class might work well as a singleton.

Save UITableView property when applicationDidEnterBackground and load back it applicationDidBecomeActive in iOS

In my iOS application, I'm having a UITableView inside my UIViewController. After data loading completed to the UITableView, when I press the Home button of the iPhone, the application will enter to the background. It will execute following method.
- (void)applicationDidEnterBackground:(UIApplication *)application {
When I tap on the application icon and launch the app, it will call following methods in AppDelegate
- (void)applicationWillEnterForeground:(UIApplication *)application {
and
- (void)applicationDidBecomeActive:(UIApplication *)application {
but none UIViewController methods. Therefore what I did was, called a custom method created by myself which is located inside my UIViewController class like below. This code go inside applicationDidBecomeActive method.
MyViewController *tViewCont = [MyViewController alloc];
[tViewCont remindToPopulate];
I put a log message and confirmed that remindToPopulate method is executing. Inside that method I want to reload the UITableView.
But at this time the UITableView property that I've declared is set to nil. What is the proper way of saving that UITableView property and load it back with the latest data?
For that you can add notification for UIApplicationDidBecomeActiveNotification or UIApplicationWillEnterForegroundNotification in viewDidLoad in controller.
just add
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(yourmethod) name:UIApplicationDidBecomeActiveNotification object:nil];
and in yourmethod
-(void)yourmethod{
[yourtableview reloadData];
}
you can also add UIApplicationWillEnterForegroundNotification notification. add as per your need.

Change UILabel in View Controller from Singleton

I am very new to iOS development and I'm struggling to make an app which connects to BLE devices. As I have many view controllers I need to keep the peripheral always connected in all of them.
To achieve this, I implemented all the BLE connection methods in a Singleton. This works just great, I call the connect method from View Controller and the Singleton connects to the peripheral.
Now, the problem is I have a UILabel in my view controller which I would like to update with the connection state (scanning, connecting, connected, disconnected) from the Singleton.
So I tried to get instance from the View Controller and change the label directly like:
MainViewController *controller = [[MainViewController alloc] init];
controller.myLabel.text = #"TEST";
I also instantiated the view controller class like:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle: nil];
MainViewController *controller = (MainViewController*)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainVC"];
Then I tried to create a method in the main View Controller:
- (void) updateLabel:(NSString *) labelText{
NSLog(#"CALLED IN MAIN");
self.myLabel.text = labelText;
}
And call it from Singleton like:
MainViewController *controller = [[MainViewController alloc] init];
[controller updateLabel:#"TEST"]
Which was called properly (NSLog was shown) but the label was not updated.
I don't really know how to update my View Controller label from the Singleton. Don't know neither if the way I'm trying to do it is the right one or not.
Any advice or help would be much appreciated. Thanks.
----- UPDATE: -----
Thanks to Mundi and Nikita, I got a better way to implement what I need through NSNotification. For all those who need it here is how I do it:
In my View Controller in viewDidLoad I call:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateConnectionLabel:) name:#"connectionLabelNotification" object:nil];
Then in the same class I implement the notification observer method like:
- (void)updateConnectionLabel:(NSNotification *) notification {
if ([[notification name] isEqualToString:#"connectionLabelNotification"]) {
self.connectionLabel.text = notification.object; //The object is a NSString
}
}
Then in my Singleton, when I need I call:
[[NSNotificationCenter defaultCenter] postNotificationName:#"connectionLabelNotification" object:[NSString stringWithFormat:#"CONNECTED"]];
When the View Controller receives the notification from the Singleton it updates the label with the text I add on the notification object (in this case #"CONNECTED").
You need to use NSNotification.
Here is sample code:
in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(mySelector:)
name:DeviceStateChanged
object:nil];
in dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self
name:DeviceStateChanged
object:nil];
also add a method in ViewController:
- (void) mySelector:(NSNotification *) notification {
// action performed
}
in Sigleton
- (void) foo {
/// some actions
// device connected
[[NSNotificationCenter defaultCenter] postNotificationName:DeviceStateChanged object:self];
///
}
Recommendation: move notification name to your constants and use constant name. For naming convention look at Apple guidelines
The proper way to do this is via NSNotification. This communication device is meant for exactly this kind of situation. It broadcast a message without caring whether the potential receiver is available.
In your view controllers, you call NSNotificationCenter's addObserver / removeObserver when they appear / disappear. You post the notification via postNotification:.

Check instance of UIAlertView when going in background

I have referred the following links for this issue, but neither of the solutions worked for me:
Link 1
Link 2
I think these solutions don't work for iOS7.
So now how would I be able to find out whether there is any UIAlertView open, when my application enters in background state.
I want to dismiss the UIAlertView before going into the background.
Remove alert in applicationDidEnterBackground
Add this line in your class
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(enteredBackground:)
name:UIApplicationDidEnterBackgroundNotification
object: nil];
And implement method as well
- (void)enteredBackground:(UIApplication *)application
{
if (mainAlertView && mainAlertView.isVisible)
[mainAlertView dismissWithClickedButtonIndex:0 animated:NO];
}
You get a notification when the app is send to background, so detect that notification in the class that displays the alert view and remove it, that's all
have you checked UIAlertView property #property(nonatomic, readonly, getter=isVisible) BOOL visible Also while going in the background you get a notification in - (void )applicationDidEnterBackground: you can check there and remove all alertviews if any

iOS: Refresh Data When App is Brought to Foreground

I'm getting data off the server via JSON and displaying it on Labels.
I've added that method in viewDidLoad.
I want to refresh the data when the user opens the app again. Currently, even if I kill the app in the simulator and start the app again, it doesn't refresh.
I tried the viewDidAppear method, but it isn't being executed for some reason.
-(void)viewDidAppear{
NSLog(#"Called viewDidAppear");
}
This is never called. I tried to minimize the app but it didn't work.
You can listen for notifications and respond appropriately. Try using these and decide what works for your intended workflow.
UIApplicationDidBecomeActiveNotification
UIApplicationWillEnterForegroundNotification
You can use respond to the notification like this.
[[NSNotificationCenter defaultCenter] addObserverForName: UIApplicationDidBecomeActiveNotification object: nil queue: [NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
// LOAD JSON
}];
I followed this tutorial - http://leejon.es/notifying-a-viewcontroller-with-uiapplicationdidbecomeactivenotification/
First, attach to the notification in the viewWillAppear method of the target view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector( appActivated: )
name: UIApplicationDidBecomeActiveNotification
object: nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self ];
}
- (void)appActivated:(NSNotification *)note
{
[self update];
}
The viewDidAppear: method takes a bool parameter wether the view was displayed with an animation which you are missing. Also you have to call the implementation of the superclass:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear: animated];
NSLog(#"Called viewDidAppear");
}
In your app delegate implementation, there is a method called:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
This method is called each time the app is launched, so I think it fits your needs. If you place your code here, it should work.
Also, be aware you should not perform a synchronous call here, because you will delay the app launch.
EDIT:
This method will be only called when the app launches. You could place your code inside a method, and call it from application didFinishLaunchingWithOptions, and then also call it from the method:
- (void)applicationWillEnterForeground:(UIApplication *)application;
This method will be called when the application enters the foreground, but not after the first launch, so beware.
I also think you should check the UIApplicationDelegate methods from apple developer page: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html
Also, check out the application state changes:
http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

Resources