How do I detect QTMovie stop playing? - macos

I have done the following - once played a QTMovie (on Mountain Lion) and wanted to get notification when a movie ended. But the notification never got called! Can anybody tell me what have I done wrong?
- (void)playMovie:(QTMovie *)movie {
[self.movieView.movie stop];
if (movie) {
self.movieView.movie = movie;
[movie gotoBeginning];
[movie play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopMovie:) name:QTMovieDidEndNotification object:self];
}
}
- (void)stopMovie:(NSNotification *)notification {
NSLog(#"stop movie!");
[[NSNotificationCenter defaultCenter] removeObserver:self name:QTMovieDidEndNotification object:nil];
}

Try changing to the following (note the object parameter):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(stopMovie:)
name:QTMovieDidEndNotification
object:movie];

Related

iOS8 : When Keyboard appear and press Back button, at that time next view appear very slow

I have ViewController (v2) with the UITextView . I pushed that view from the viewController (V1).
On V2 When I tap on textview and keyboard appear after that tap on back button and move on V1.
I repeat this process 15 to 20 time and notice that my app's performance become very slow.
Issue is Keyboard take long time to disappear when I tap on Back button :
I am using following line of code :
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willShowKeyboard:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
- (IBAction)back:(id)sender
{
[self.navigationController popViewControllerAnimated:NO];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[noteView becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[noteView resignFirstResponder];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[super viewWillDisappear:animated];
}
- (void)willShowKeyboard:(NSNotification *)notification
{
[UIView setAnimationsEnabled:NO];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[UIView setAnimationsEnabled:NO];
}
- (void)keyboardDidHide:(NSNotification *)notification
{
[UIView setAnimationsEnabled:NO];
}
It is simple one line code to dismiss keyboard when user press back button
- (IBAction)back:(id)sender
{
[self.view endEditing:YES];
[self.navigationController popViewControllerAnimated:NO];
}

Is there a change to the behaviour of UIKeyboardWillShowNotification in iOS 8?

I have had a simple UIView block animation that handles animating a group of text fields into view when the keyboard will show (and animate them back when the keyboard hides). This has worked fine in iOS 6 & 7, but now I'm getting incorrect behavior, and it all points to some change in UIKeyboardWillShowNotification.
I set up an isolated project to test this further on a single text field, with two buttons that call exactly the same methods that are fired for the keyboard's WillShow and WillHide notifications. See the results in this video:
Video example
This seems like a bug to me, or it might be a change to the behavior of this notification. Does anyone know if this is intended and/or what can be done about it?
Here is the relevant code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
self.textField.frame = CGRectOffset(self.textField.frame, 0.f, _destY - _origY);
}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
self.textField.frame = CGRectOffset(self.textField.frame, 0.f, _origY - _destY);
}];
}

NSNotification EXC_BAD_ACCESS

Here is the error I am getting
Thread 1:EXC_BAD_ACCESS (code=2, address=0xb7ffffc)
On this line
[[NSNotificationCenter defaultCenter] postNotificationName:AsyncImageLoadDidFinish
object:target
userInfo:[[userInfo copy] autorelease]];
In the AsyncImageView.m file.
The error stops the code but if I continue in debugger it freezes Xcode and shuts it down. How can I fix this issue?
In init you need to register, and in dealloc you need to un register!
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:AsyncImageLoadDidFinish object:nil];
OR
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Try the code below, it should be okay:
NSDictionary * userInfo = [NSDictionary dictionaryWithObjectsAndKeys:..., nil];
[[NSNotificationCenter defaultCenter] postNotificationName:AsyncImageLoadDidFinish
object:target
userInfo:userInfo];
or:
NSDictionary * userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:..., nil];
[[NSNotificationCenter defaultCenter] postNotificationName:AsyncImageLoadDidFinish
object:target
userInfo:userInfo];
[userInfo release];

Will NSNotificationCenter call back method be called in main thread or background thread?

My code is just play a downloaded mp4 files and register the view controller to observe the notification of end of player.
It works pretty good in not only iOS5 but also iOS4.
But I just want to know for sure that whether the call back method by NotificationCenter will be called in background thread or main thread.
(loadMoviePlayerStateChanged:(NSNotification*)notification is call back method in my code)
Do anyone know exactly about this?
- (void) playMovie:(NSURL *)fileURL {
MPMoviePlayerViewController *MPVC = [[MPMoviePlayerViewController alloc] initWithContentURL:fileURL];
self.mMPVC = MPVC;
self.mMPVC.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loadMoviePlayerStateChanged:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.mMPVC.moviePlayer];
[MPVC.moviePlayer prepareToPlay];
[MPVC release];
}
- (void) loadMoviePlayerStateChanged:(NSNotification*)notification {
int loadState = self.mMPVC.moviePlayer.loadState;
if(loadState & MPMovieLoadStateUnknown) {
IGLog(#"The load state is not known at this time.");
return;
}
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.mMPVC.moviePlayer];
[self.mMPVC.view setFrame:self.view.bounds];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.mMPVC.moviePlayer];
/* if I do not use performSelectorOnMainThread method to add subview to UIViewController`s view,
the view of MPMoviePlayerViewController would not be removed from superview normally */
[self.view performSelectorOnMainThread:#selector(addSubview:)
withObject:self.mMPVC.view
waitUntilDone:YES];
[self.mMPVC.moviePlayer play];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
[self.mMPVC.moviePlayer stop];
[self.mMPVC.moviePlayer.view removeFromSuperview];
NSString* dstFilePath = [[_mPopupVC.mSelectedMovie decryptionFilePath] stringByAppendingPathExtension:#"mp4"];
[[NSFileManager defaultManager] removeItemAtPath:dstFilePath error:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.mMPVC.moviePlayer];
}
I got an answer for my question in apple developer site, the answer is,
"notifications safely thread themselves and perform their selectors on the main thread.
however, your problem is that you should not be adding and removing the player view like that, use the presentModalVideo methods provided as a category in your view controller class."
and I solved the problem that i had. code is below..
- (void) playMovie
{
/*
*create and initialize MPMoviePlayerViewController with specified url and retain it
*/
MPMoviePlayerViewController *MPVC = [[MPMoviePlayerViewController alloc] initWithContentURL:vodWebURL];
self.mMPVC = MPVC;
[MPVC release];
self.mMPVC.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
self.mMPVC.moviePlayer.shouldAutoplay = NO;
[self.mMPVC.moviePlayer prepareToPlay];
/*
*register movie player to NSNotificationCenter
*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loadMoviePlayerStateChanged:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.mMPVC.moviePlayer];
}
- (void) loadMoviePlayerStateChanged:(NSNotification*)notification
{
/*
*do your work for the state of the movie player
*/
int loadState = self.mMPVC.moviePlayer.loadState;
if(loadState & MPMovieLoadStateUnknown) {
NSLog(#"The load state is not known at this time.");
return;
} else if(loadState & MPMovieLoadStatePlayable) {
NSLog(#"MPMovieLoadStatePlayable : The buffer has enough data that playback can begin, but it may run out of data before playback finishes.");
} else if(loadState & MPMovieLoadStatePlaythroughOK) {
NSLog(#"MPMovieLoadStatePlaythroughOK : Enough data has been buffered for playback to continue uninterrupted.");
} else if(loadState & MPMovieLoadStateStalled) {
NSLog(#"MPMovieLoadStateStalled : The buffering of data has stalled.");
}
/*
*set frame of the view of MPMoviePlayerViewController and add it
*call play method
*/
[self.mMPVC.view setFrame:self.view.superview.bounds];
[self.view.superview addSubview:self.mMPVC.view];
[self.mMPVC.moviePlayer play];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:self.mMPVC.moviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.mMPVC.moviePlayer];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification
{
/*
*remove the view of MPMoviePlayerViewController
*release MPMoviePlayerViewController
*/
[self.mMPVC.moviePlayer stop];
[self.mMPVC.moviePlayer.view removeFromSuperview];
self.mMPVC = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.mMPVC.moviePlayer];
}

Drawing NSControl when the windows is key or not

I have a NSControl subview and I want to change the drawing when the control is not on a keyWindow. The problem is that I don't see any property that reflects that state (tried enabled property but that was not it).
In simple terms, can I differentiate between these two states?
You can use NSWindow's keyWindow property, and if you want to check to see if your control is the first responder for keyboard events also test [[self window] firstResponder] == self. I don't believe keyWindow supports KVO, but there is a NSWindowDidBecomeKeyNotification and NSWindowDidResignKeyNotification you can listen for. For instance,
- (id)initWithFrame:(NSRect)frameRect;
{
if ( self = [super initWithFrame:frameRect] )
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(display) name:NSWindowDidResignKeyNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(display) name:NSWindowDidBecomeKeyNotification object:nil];
}
return self;
}
- (void)drawRect:(NSRect)aRect;
{
if ( [[self window] isKeyWindow] )
{
// one way...
}
else
{
// another way!
}
}
- (void)dealloc;
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil];
[super dealloc];
}

Resources