Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > Mobile Development > BOOK: Beginning iOS 4 Application Development
Password Reminder
Register
| FAQ | Members List | Search | Today's Posts | Mark Forums Read
BOOK: Beginning iOS 4 Application Development
This is the forum to discuss the Wrox book Beginning iOS 4 Application Development by Wei-Meng Lee; ISBN: 978-0-470-91802-9
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Beginning iOS 4 Application Development section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old February 28th, 2011, 01:25 PM
Authorized User
Points: 49, Level: 1
Points: 49, Level: 1 Points: 49, Level: 1 Points: 49, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Feb 2011
Posts: 13
Thanks: 5
Thanked 0 Times in 0 Posts
Default Ch 6, Text re NSNotificationCenter question

In the text explaining the last Try It Out, "Shirfting Views" in Ch 6, Keyboard Inputs, there is something I find puzzling. (p176-178)
There are two methods messaging the NSNotificationCenter, viewWillAppear: and viewWillDisappear:.
The first reads:
Code:
//---before the View window appears---
-(void) viewWillAppear:(BOOL)animated {
	//---registers the notifications for keyboard---
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:self.view.window];
	
	[[NSNotificationCenter defaultCenter] 
	 addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
In the text, the author states:
"Finally, before the View window disappears, you remove the notifications that you set earlier:"
and then lists the 2nd method:
Code:
//---before the View window diappears---
-(void) viewWillDisappear:(BOOL)animated {
	//---remove the notifications for keyboard---
	[[NSNotificationCenter defaultCenter] 
	 removeObserver:self name:UIKeyboardWillShowNotification object:nil];
	
	[[NSNotificationCenter defaultCenter] 
	 removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
Note that the name values in the 2nd do not match those in the first. Given the explanatory statement, I would think that they should.
Is this, as I suspect, an errata, or is there something about NSNotificationCenter, or the code or the statement, I'm not understanding?
The code does work, so it certainly could be my newbness!
Reply With Quote
  #2 (permalink)  
Old February 28th, 2011, 03:04 PM
Friend of Wrox
Points: 1,671, Level: 16
Points: 1,671, Level: 16 Points: 1,671, Level: 16 Points: 1,671, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

You are correct the book is wrong. The reason it still works should pretty apparent. The observer to the notification is added and never removed. What is removed was never added.

Check the following with the added lines to illustrate:

Code:
//---when the keyboard appears---
-(void) keyboardDidShow:(NSNotification *) notification {
	
	NSLog(@"The notification name is %@",[notification name]);
	if (keyboardIsShown) return;
	
    NSDictionary* info = [notification userInfo];
	
	//---obtain the size of the keyboard---
	NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];	
	CGRect keyboardRect = [self.view convertRect:[aValue CGRectValue] fromView:nil];

	NSLog(@"%f", [aValue CGRectValue].size.height);

	NSLog(@"%f", keyboardRect.size.height);
	
    //---resize the scroll view (with keyboard)---
    CGRect viewFrame = [scrollView frame];
    viewFrame.size.height -= keyboardRect.size.height;
    scrollView.frame = viewFrame;
	
    //---scroll to the current text field---
    CGRect textFieldRect = [currentTextField frame];
    [scrollView scrollRectToVisible:textFieldRect animated:YES];
		
    keyboardIsShown = YES;
}

//---when the keyboard disappears---
-(void) keyboardDidHide:(NSNotification *) notification {
	NSDictionary* info = [notification userInfo];
	
	NSLog(@"The notification name is %@",[notification name]);
	
	//---obtain the size of the keyboard---
    NSValue* aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
	CGRect keyboardRect = [self.view convertRect:[aValue CGRectValue] fromView:nil];
	    
    //---resize the scroll view back to the original size (without keyboard)---
    CGRect viewFrame = [scrollView frame];
    viewFrame.size.height += keyboardRect.size.height;
    scrollView.frame = viewFrame;
	
    keyboardIsShown = NO;
}

-(void) viewWillAppear:(BOOL)animated {    
    //---registers the notifications for keyboard---
	
	static BOOL FirstTime = YES;
	if (FirstTime) {
		NSLog(@"Registering the observer");
    [[NSNotificationCenter defaultCenter] addObserver:self 
											 selector:@selector(keyboardDidShow:) 
												 name:UIKeyboardDidShowNotification 
											   object:self.view.window]; 
    
    [[NSNotificationCenter defaultCenter]	 addObserver:self
											  selector:@selector(keyboardDidHide:)
												  name:UIKeyboardDidHideNotification
												object:nil];
		FirstTime = NO;
	}
}
Bob
Reply With Quote
The Following User Says Thank You to thepianoguy For This Useful Post:
gNotapipe (March 1st, 2011)
  #3 (permalink)  
Old March 1st, 2011, 11:26 AM
Authorized User
Points: 49, Level: 1
Points: 49, Level: 1 Points: 49, Level: 1 Points: 49, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Feb 2011
Posts: 13
Thanks: 5
Thanked 0 Times in 0 Posts
Default

...& so the observer to the notification is simply over-written when used again, sure.

Thanks, Bob, for helping me polish a bit more roughness off my newbness.
Your examples of debugging techniques are invaluable.

Chet
Reply With Quote
  #4 (permalink)  
Old March 1st, 2011, 10:53 PM
Friend of Wrox
Points: 1,671, Level: 16
Points: 1,671, Level: 16 Points: 1,671, Level: 16 Points: 1,671, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

A follow up, since my answer is not fully accurate. (still exploring)
The code as written functions because the observer is added and never removed. Your response about the observer being overwritten is not correct. The -viewWillDisappear is never called, so no observers are ever removed until the program quits.
To illustrate the need to correctly pair notification names when adding and removing observers, I figured that the simplest thing to do would be to add a second view and log the behavior as the views were switched out since the documentation suggests that the -viewWillAppear and -viewWillDisappear will be called when this occurs. Things don't exactly work as expected. Stay tuned…
Bob
Reply With Quote
  #5 (permalink)  
Old March 2nd, 2011, 01:15 PM
Authorized User
Points: 49, Level: 1
Points: 49, Level: 1 Points: 49, Level: 1 Points: 49, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Feb 2011
Posts: 13
Thanks: 5
Thanked 0 Times in 0 Posts
Default

No? Would it be the case then that each time a text field is used or exited that a separate observer+notification is added for that object? --I guess I mean observer & name:UIKeyboardDidShowNotification when a text field is entered & the name:UIKeyboardDidHideNotification for that observer when the keyboard is dismissed.--

-viewWillDisappear is never called? So it's simply that the program exits?
Is the keyboard a view? I would think it would be, but, to be honest, I haven't tried to find out (yet).
Interesting.
Staying tuned...
Reply With Quote
  #6 (permalink)  
Old March 2nd, 2011, 02:00 PM
Friend of Wrox
Points: 1,671, Level: 16
Points: 1,671, Level: 16 Points: 1,671, Level: 16 Points: 1,671, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

The keyboard is not a treated as a view (as far as I can tell). I made a similar assumption that that was the view appearing and disappearing, and that the scrollView, being the delegate of the textView received messages as a result of this. In retrospect, not great reasoning on my part.(The method would probably had a signature like -keyboardViewDidShow if it was) It is the scrollView itself that receives these notifications and responds with the methods assigned to the particular notification when registering. The notifications are sent whether there are observers or not. Once registered an object will receive the notifications it is registered for until it removes itself as an observer. It is sort of like "If a tree falls in a forest…" You only hear it if you are set up to listen for it.

What is going on in the program is the following
-viewWillAppear is called and the scrollView is registered as an observer to the -UIKeyboardDidShow and -UIKeyboardDidHide notifications. -viewDidLoad is called after this. The keyboard shows and hides automatically as the textField becomes and relinquishes FirstResponder status. The scrollView receives the notifications from this and adjusts its view accordingly. The concept behind the program relinquishing observer status when the scrollView hides makes sense, since it will receive the notifications whether it is visible or not (showing and hiding the keyboard even though not visible). So offscreen - relinquish, return - reestablish.
-viewDidLoad is called only when the view is initialized, so the idea of using -viewWillAppear is that it is called each time the view returns. The issue arises - do
-viewWillAppear and -viewWillDisappear actually get called after the view is hidden? The answer is - it depends. If you add a secondViewController.view as a subView to the scrollView, it does not (There is a way to call it directly, but it is a one way street, try to call from the subView and design and encapsulation problems start to pop up and the idea of loose coupling goes out the window) Dismissing the subView and returning to the original view does not call -viewWillAppear even though the original view is no longer hidden.
I will be doing examples that makes use navigation and tabbar controllers to verify that things behave as expected when assigned to a main controller. (From some internet research, the calling of these delegate methods is tied into to an objects location on the stack)
More to come…
Bob
Reply With Quote
The Following User Says Thank You to thepianoguy For This Useful Post:
gNotapipe (March 4th, 2011)
  #7 (permalink)  
Old March 4th, 2011, 10:27 PM
Authorized User
Points: 49, Level: 1
Points: 49, Level: 1 Points: 49, Level: 1 Points: 49, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Feb 2011
Posts: 13
Thanks: 5
Thanked 0 Times in 0 Posts
Default

So the notifications are firing away like gangbusters all the time. That's interesting.

Re "...when the scrollView hides...", isn't the scrollView always visible?

Thanks for your detailed discussion. Although I think I've followed you in a general sense, I suspect I'll understand this in much greater depth after I've worked through more of the book & apple docs. It will be interesting to reread your post later on. (Oh! that's what Bob was saying....) :)
Reply With Quote
  #8 (permalink)  
Old March 7th, 2011, 03:34 PM
Friend of Wrox
Points: 1,671, Level: 16
Points: 1,671, Level: 16 Points: 1,671, Level: 16 Points: 1,671, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

Followup on various points.

In the NotificationCenter when adding and removing an object as an observer, -addObserver and -removeObserver notifications should always be paired (the same name). If the names are mismatched then the observer is added and never removed. The documentation underscores the need to remove observers before the observer or any observed objects are deallocated. So the book is incorrect when using DidShow and DidHide when adding and WillShow and WillHide when removing. As a side note, if you observe the visual result, in the book's example, the animation is better if WillShow is used. As noted previously, adding the observer in -viewWillAppear and removing the observer in -viewWillDisappear is done since these methods are usually called automatically when the view comes into view, and is removed. A key point is that these methods must be called directly under some circumstances. If a main controller is used (TabBar, Navigation, SplitView) then these methods are called automatically as delegate methods when the view is added (pushed) and removed (popped) from the stack. On the other hand, if a view is added as a subview to an existing view the -viewWillAppear method should be called directly by the class allocating the instance of the subview. When removing itself the subview should call the -viewWillDisappear on itself.

To demonstrate this I have applied a variant of the ScrollerView example from the book to various mutliple view scenarios within a TabBar example.
1. FirstViewController assigned to Tab 1 adds the ScrollerView as a subview to itself. When adding theScrollerView subview, FirstViewController must call
-viewWillDisappear
on itself as ScrollerView appears, and -viewWillAppear on the ScrollerView instance it creates. When the ScrollerView subview removes itself it calls -viewWillDisappear on itself (ScrollerView) and sends a notification to FirstViewController to call -viewWillAppear on itself (FirstView). If these direct calls are omitted (or commented out in my project example), the methods are not called. The other situation that is taken into account is switching tabs while the subview is still visible. Switching views in the TabBar calls -viewWillDisappear on the viewController in the tab that it is leaving (FirstViewController in this case). FirstView has no need for the message and should forward it. In the example, the message is passed on to the subview, since that view is in front. When the tab is returned to (Tab 1 in this case), -viewWillAppear is called on FirstViewController which again, must pass it on to its subview.
2. SecondViewController is the basic implementation from the book. As you can see, the -viewWillAppear and -viewWillDisappear methods are called automatically when the tab selection changes.
3. Tab number 3 installs a navigationController into the 3rd tab. Again, the -viewWillAppear and -viewWillDisappear methods are called automatically, as you drill down from and return to the RootController.

All this can be tracked through the NSLog statements.

The link to the project.
https://files.me.com/thepianoguy88/wednub


In addition, to get a sense of how many notifications are constantly being passed around, uncomment
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listNotifications:) name:nil object:nil];
in in the TabBar delegate and check the console as you run the program. You can envision it somewhat like Twitter. All types of messages are constantly being posted, but you only receive the ones you follow.

Finally, the UIKeyboard is a view. More on that later.

Bob

Last edited by thepianoguy; March 7th, 2011 at 03:38 PM..
Reply With Quote
  #9 (permalink)  
Old March 7th, 2011, 11:00 PM
Authorized User
Points: 49, Level: 1
Points: 49, Level: 1 Points: 49, Level: 1 Points: 49, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Feb 2011
Posts: 13
Thanks: 5
Thanked 0 Times in 0 Posts
Default

Hi Bob,
I must pretty much echo my last comment. I believe I'm following what you're saying, though, again, I think it will have much more meaning for me when I'm more advanced, have a greater familiarity w/ the overall environment & can more readily place things in context. I am trying to balance the work-through-the-steps learning of the book w/ reading enough but not too much of the documentation along the way. One of the things which I feel could be better in this book is if it were to point out more specifically in its text which methods are being written from scratch & which are a utilization of the platform. One can work it out by digging back through & checking w/ the option+mouseOver of course, but I think many beginners will not think of this. Further, I think it's rather a missed opportunity--an elucidation of the reasoning behind added methods could help greatly w/ learning. OTOH, there's only so much one can include, :)

I'm almost mixed on looking at your project; I think it's likely a bit much for me w/ how far along I am w/ iOS. Yet I don't want lose track of it & fail to come back to it. Hmm...

In any case, I look forward to your book... You are writing one, right?
;)
C.
Reply With Quote
  #10 (permalink)  
Old March 8th, 2011, 10:07 AM
Friend of Wrox
Points: 1,671, Level: 16
Points: 1,671, Level: 16 Points: 1,671, Level: 16 Points: 1,671, Level: 16
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
Default

Feel free to check it out at your own pace.
As far as the from scratch/preexisting method problem, I think for any object you are using it is valuable to browse its class reference. Be aware of its properties, constants, notifications and whether it has delegate methods. You don't need to have everything in your head obviously, but after a while you can start to predict (guess?) what methods probably exist for an object and even what the signature will most likely be. The big "How was I supposed to know about that method?" question was one of the big stumbling blocks for me when I began dabbling in Cocoa. Foundation oriented stuff was very similar to libraries in C and was obvious, but GUI interaction was a whole new ballgame, with its heavy reliance on delegates and notifications in order to maintain the loose coupling that is such an important conceptual backbone of the object oriented design philosophy of iOS and Cocoa. Then along came bindings…

The project that I set up is actually pretty straightforward and primarily utilizes things already covered in the book up to the ScrollerView example. I don't think you would have any problem following it. It is the ScrollerView example with the addObserver/removeObserver conflict corrected combined with the TabBar example. By adding a second view there is now a reason to actually implement the -viewDidAppear and -viewDidDisappear methods instead of just putting the notification registration code in the -viewDidLoad and -viewDidUnload methods. The SecondView in the project is the corrected ScrollerView from the book. By switching to the other tabs you can observe (in the console) the notifications being sent and the observers being added and removed in SecondView, something you can't do in the book's single view project. So if you "get" the project in the book this will make sense and you can see the mechanics in action. The ThirdView uses a NavigationController to show that the behavior is consistent with the TabBar. The only view that might require some thought is the FirstView. This was based on the author's approach to programmatically add a view in Chapter 3. This is included to demonstrate that views added directly as subviews and not through controllers behave differently in terms of what delegate messages they receive, and that some methods must be called directly.


New link, since there was a tiny bug in the project.
https://files.me.com/thepianoguy88/xg6nbp

Bob
Reply With Quote
The Following User Says Thank You to thepianoguy For This Useful Post:
gNotapipe (March 16th, 2011)
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Ch 11 Question tixrus BOOK: Beginning JavaScript and CSS Development with jQuery 0 April 11th, 2010 05:23 PM
Ch 2 example 2-5 question Bo BOOK: Beginning CSS: Cascading Style Sheets for Web Design ISBN: 978-0-7645-7642-3 3 August 16th, 2006 07:44 AM
new ch. 6 question Dennis Mollet BOOK: Beginning VB.NET Databases 2 August 16th, 2005 05:27 PM
CH 3 pg 96 Question mririe BOOK: Beginning PHP, Apache, MySQL Web Development ISBN: 978-0-7645-5744-6 8 August 25th, 2004 04:17 AM



All times are GMT -4. The time now is 08:09 AM.


Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.