Basically, I have a MainViewController that presents a MPMoviePlayerViewControllerExtended and I want to dismiss MPMoviePlayerViewControllerExtended when user taps the Home Button or Power Button.
I tried this in MPMoviePlayerControllerExtended.m:
-(void)viewWillDisappear {
[self dismissMoviePlayerViewControllerAnimated];
}
-(void)viewDidDisappear {
[self dismissMoviePlayerViewControllerAnimated];
}
But it doesn't work, apparently they aren't called when Home or Power button is pressed.
Any help is appreciated.
try adding :(BOOL)animated
-(void)viewWillDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
}
-(void)viewDidDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
}
Also probably want to include the
[super viewWillDisappear:animated]
and
[super viewDidDisappear:animated]
in those somewhere too
-(void)viewWillDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
[super viewWillDisappear:animated]
}
-(void)viewDidDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
[super viewDidDisappear:animated]
}
Since both methods aren't called, I had to use Notifications.
In MPMoviePlayerViewControllerExtended.m
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dismissModalViewControllerAnimated:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
Related
I want to hide my button in my Popover class, whenever my bool value in the other class is false, but the Problem is i don't get the "TRUE" value.
My First Class
-(void) hideButton{
finished = _secondVC.finished;
BOOL isRunning = !finished;
if(isRunning){
_deleteButton.hidden = YES;
}else if(finished){
_deleteButton.hidden = NO;
}
}
I call the method of hideButton in my ViewWillAppear function.
My Second Class
-(void) someAction{
if(something){
self.finished = YES;
}
EDIT:
Now, if i load the Popover and the NSNotification gets fired the button is enabled, but the Problem is, if i close and open the popover, my delete button is still disabled.
My PopOver Class
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(syncFinished){
_deleteButton.enabled = YES;
}else if(!syncFinished){
_deleteButton.enabled = NO;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(showButton)
name:#"syncFinish"
object:nil];
}
- (void) showButton{
syncFinished = YES;
_deleteButton.enabled = YES;
}
My Second Class
-(void) someAction{
if(something){
[[NSNotificationCenter defaultCenter] postNotificationName:#"syncFinish"
object:self];
}
you can't directly observe the value.
you could send a NSNotification when the action starts/finishes and observe for that in your first class to show/hide the button.
I solved This Problem with the NSUserDefaults. so I can set the bool if someAction is happening. And in every other class i can read the bool.
so in my Second Class:
-(void) someAction{
if(something){
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"syncFinish"];
} else {
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"syncFinish"];
}
In My Popover Class i say
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"syncFinish"]) {
_deleteButton.enabled = NO;
} else {
_deleteButton.enabled = YES;
}
}
In the Tasks sample app for the Dropbox Datastore API (found here) the observers are set up and discarded in viewWillAppear and viewWillDisappear, respectively:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
__weak TasksController *slf = self;
[self.accountManager addObserver:self block:^(DBAccount *account) {
[slf setupTasks];
}];
[self setupTasks];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.accountManager removeObserver:self];
if (_store) {
[_store removeObserver:self];
}
}
I am trying to set up global observers in a singleton class and am using init and dealloc since my class isn't a view controller.
//Custom init method to start up our Dropbox observer
- (id)init {
self = [super init];
if(!self) return nil;
[self startDatastore];
__weak typeof(self) weakSelf = self;
[self.store addObserver:self block:^{
[weakSelf getRemoteDropboxChanges];
}];
return self;
}
-(void)dealloc
{
//Stop listening for Dropbox changes
if(self.store) {
[self.store removeObserver:self];
}
}
...but alas, this doesn't work (the observer's block never fires). Can someone help me understand the difference?
Can you see the button in the bottom right of the iPad keyboard?
Well I want access to the event handler for that button, Because, I have some logic that I need to administer when specifically THAT button is pressed.
My attempted solution included using the UIKeyboardWillHideNotification notification like so:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(hideKeyboardTapped:)
name:UIKeyboardWillHideNotification
object:nil];
However this is called everytime the keyboard is dismissed, including when search cancel button is pressed, with a gesture tap on the background, etc; all of which have slightly different logic.
So I just need to have one set of logic for when that specific "hide keyboard" button is pressed.
The UIKeyboard is activated by a UISearchBar (for those of you who need extra info).
Any help would be greatly appreciated; and I'll answer any questions you may have.
There is not an official, Apple-sanctioned way to do this.
If you don't mind mucking around with private classes, which could get you rejected from the App Store, there is an unsupported method. Basically, you listen for changes to the keyboard's activeKey property, and if the new active key has a name of "Dismiss-Key", then the dismiss key was tapped:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"activeKey"])
{
id activeKey = [object valueForKey:keyPath];
NSString *keyName = [activeKey valueForKey:#"name"];
if ([keyName isEqualToString:#"Dismiss-Key"])
{
[self didTapDismissKey];
}
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardDidShow:(NSNotification *)notification
{
// Search for the UIKeyboardLayoutStar class, which seems to manage layout for the keyboard, and observe its activeKey property
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
[self traverseViewHierarchyWithView:topWindow block:^(UIView *view, BOOL *stop) {
if ([view isKindOfClass:NSClassFromString(#"UIKeyboardLayoutStar")])
{
[view addObserver:self forKeyPath:#"activeKey" options:0 context:NULL];
}
}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
// Don't forget to remove the controller as an observer!
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
[self traverseViewHierarchyWithView:topWindow block:^(UIView *view, BOOL *stop) {
if ([view isKindOfClass:NSClassFromString(#"UIKeyboardLayoutStar")])
{
[view removeObserver:self forKeyPath:#"activeKey"];
}
}];
}
- (BOOL)traverseViewHierarchyWithView:(UIView *)view block:(void (^)(UIView *, BOOL *))block
{
BOOL stop = NO;
block(view, &stop);
if (stop)
{
return YES;
}
for (UIView *subview in view.subviews)
{
if ([self traverseViewHierarchyWithView:subview block:block])
{
return YES;
}
}
return NO;
}
- (void)didTapDismissKey
{
NSLog(#"Dismiss key tapped");
}
Tested on the iOS 7 iPad simulator and it works.
I don't know if you can put a listener to a single button of the keyboard, but you can try to set some Booleans on the views, that can turn on/off the events that you want or don't want to handle (I would approach it like that), for example:
Add a custom notification observer/listener at the class where you
want to execute the method of the event.
Add the Apple default Keyboard Hide listener on the controller where the notification will be triggered.
Then, on the views that can trigger the event... Set the booleans to activate/deactivate the event action
#Some Other Class
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(doSomething)
name:#"doSomethingNotification"
object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"doSomethingNotification" object:nil];
}
#Trigger Class
-(void)viewWillAppear:(BOOL)animated{
self.isNotificationNeeded = NO;
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(onKeyboardHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
-(void)onKeyboardHide:(id)sender{
//When your event is Happening
if (self.isNotificationNeeded == YES) {
NSNotification *n = [NSNotification notificationWithName:#"doSomethingNotification" object:nil];
[[NSNotificationCenter defaultCenter] postNotification:n];
self.isNotificationNeeded = NO;
}
}
-(void)userClickedCancelButton{
//If this is a keyboard hide event that you don't want to trigger
self.isNotificationNeeded = NO;
}
//SearchBarDelegate
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
self.isNotificationNeeded = YES; //If your event can happen from here
return YES;
}
Why don´t work when I change the orientation of the simulator in xCode? I see equals the label on the ViewController all time and the NSLog doesn´t appear.
ViewController.m:
- (void)viewDidLoad
{
[self orientacionActual];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientacionActual)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIDeviceOrientation) orientacionActual
{
UIDeviceOrientation orientacionActual = [UIDevice currentDevice].orientation;
return orientacionActual;
}
- (void) cambiaOrientacion:(NSNotification *) notificación
{
if(UIDeviceOrientationIsLandscape([self orientacionActual]))
{
self.LabelEstoy.text = #"Landscape";
NSLog(#"Landscape");
} else if (UIDeviceOrientationIsPortrait([self orientacionActual]))
{
self.LabelEstoy.text = #"Portrait";
NSLog(#"Portrait");
}
}
Call UIApplicationDidChangeStatusBarOrientationNotification instead of device orientation changes. Also, I'm not sure what is your goal, but try to use this snippet:
Inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(cambiaOrientacion:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
and below:
- (void)cambiaOrientacion:(NSNotification *)notificacion
{
UIInterfaceOrientation orientation = [[[notification userInfo]
objectForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if (UIInterfaceOrientationIsLandscape(orientation))
{
self.LabelEstoy.text = #"Landscape";
NSLog(#"Landscape");
} else
{
self.LabelEstoy.text = #"Portrait";
NSLog(#"Portrait");
}
}
and orientacionActual method redudant in your code, and doesn't makes any sense.
Don't forget to add [[NSNotificationCenter defaultCenter] removeObserver:self] inside dealloc.
I added the following code to my appDelegate.m
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake )
{
// User was shaking the device. Post a notification named "shake".
[[NSNotificationCenter defaultCenter] postNotificationName:#"shake" object:self];
}
}
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
}
- (void)shakeSuccess
{
// do something...
}
and then I added :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// INIT THE BACKGROUND PATH STRING
[self refreshFields];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
***[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(shakeSuccess) name:#"shake" object:nil];***
return YES;
}
When I start my app on my iPhone, the method named "shakeSuccess" doesn't called.
What should I do to implement this function in my app?
any idea?
This might help you...
https://stackoverflow.com/a/2405692/796103
He says that you should set the UIApplication's applicationSupportsShakeToEdit to
YES. and override 3 methods in your VC:
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
The rest of your code is fine. (the -motionEnded:withEvent:)
You could do something like this...
Firstly...
Set the applicationSupportsShakeToEdit property in the App's Delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
application.applicationSupportsShakeToEdit = YES;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
Secondly...
Add/Override canBecomeFirstResponder, viewDidAppear: and viewWillDisappear: methods in your View Controller:
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
Thirdly...
Add the motionEnded method to your View Controller:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake)
{
// your code
}
}
That should work if the first answer did not and this is only quickly typed not tested:)
If you want to be able to detect the shake motion across the app, the best way is to override the class of your application with a custom class.
And then implement this in your custom application class
#implementation PSApplication
- (void)sendEvent:(UIEvent *)event
{
if ( event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake ) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"shakeNotification" object:nil];
}
[super sendEvent:event];
}
#end
I extended UIApplication class and added class reference to main:
MyApplication.h
#interface MyApplication : UIApplication
#end
MyApplication.m
#implementation MyApplication
- (void) sendEvent:(UIEvent *)event
{
if( event && (event.subtype==UIEventSubtypeMotionShake))
{
AppDelegate *objAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[objAppDelegate doWhatEver];
[super sendEvent:event];
}
else
{
[super sendEvent:event];
}
}
#end
And the last step in main.m
int main(int argc, char *argv[])
{
return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([AppDelegate class]));
}
This works in all cases.