Tải bản đầy đủ - 0 (trang)
We need a view...but not necessarily a new view

We need a view...but not necessarily a new view

Tải bản đầy đủ - 0trang

plists and modal views



The View Controller defines the behavior

for the view

From the user’s perspective, we’ll have three views: the table view, the

detailed view, and the new drink view. But, since we’re reusing the .xib

to create the “new” view, all we need is a new view controller class that

supports adding a drink. That means there isn’t any Interface Builder

work to do at all!



e

When we instantiate th

ller, we tell

ro

nt

Co

iew

DrinkDetailV

cific nib.

it to initialize with a spe



Back button



d

view we neee

w

e

n

e

h

t

’s

h

t

Here

It will look

to createw. e can reuse the nib.

same, so



is

We need th



now...



Name: Name of the drik

Ingredients:



Back button

Name:

Ingredients:



These are the

ingredients. Like

grenadine, vodka, etc.



Directions:



Directions:

These are the directions,

mix, pour over ice, then

layer the rest.



DrinkDetailViewController.xib

DrinkDetailViewController.m



fines the

The ViewController de

in this case,

behavior for the view—

drink

populating the fields with

information.



I and

The nib defines the GU

the

loo

since both views will k

same, we can reuse it.



AddDrinkViewController.m



Separating the UI from behavior

helps you reuse your view.



Reusing both the .xib file and the detail view

controller is also an option. But where could we run

into problems with that approach?



you are here 4  229

www.it-ebooks.info



keeping track of outlets and actions



A nib file contains the UI components and

connections...

One way we could reuse the nib is to create a new ViewController and pass it

the DrinkDetailViewController.xib file when we initialize it. There are a few

challenges with that, though. Remember, we don’t just use Interface Builder to

lay out the interface; we use it to wire up the components to the class that will

load the nib.



d

information eannib...

ut

o

y

la

ew

vi

e

h

h

T

stored in t

connections are



e fields

troller has thed up to

n

o

C

w

ie

V

e

h

T

hat get wir

and methods tts in the nib.

the componen



DetailDrinkViewController

IBOutlet UITextField *nameTextField;

...

- (void) viewWillAppear: (BOOL) animated;



...



...and information about the nib’s File’s Owner

The nib doesn’t actually contain the ViewController class it’s setup to be wired

to. Instead, it does this through the nib’s File’s Owner. When you pass the nib to

the view controller, it will deserialize the nib and begin making connections to

the outlet names stored in the nib file. This means that if we want to pass that

nib into another, new view controller, we need to make sure we have the same

outlets with the same names, the same actions, etc.







Reusing our nib gets us what we need for this app, but

it’s not for every app out there.



Because of the way DrinkMixer is built, we can just subclass our

detailed view to get what we need. That works great for this app,

but be careful doing this in more complex apps, because your code

can get difficult to maintain. Often, it’s better to just bite the bullet and build a

new view...and sometimes you’ll realize they shouldn’t even look the same.



230   Chapter 5

www.it-ebooks.info



plists and modal views



You can subclass and extend view controllers

like any other class

Instead of reusing just the nib and having to recreate all the outlets and actions,

we can just subclass the DetailedViewController and add the behavior we

need. Our AddDrinkViewController is the same as a DetailedViewController;

it just has the ability to create and save an entirely new drink. Everything else—

showing the name, showing the description, etc.—are all exactly the same as the

DetailedViewController.



DetailDrinkViewController

ive-C

ct

je

b

O

in

s

ld

fie

By default, ed

can get to IBOutlet UITextField *nameTextField;

e

w

so

,

t

ec

t

...

are pro

bclass.

them in our su

- (void) viewWillAppear: (BOOL) animated;





er

kViewControsll(yet)

Our AddDrianny

ld

new fie

won’t need ill inherit the

because it wViewController’s

DetailDrink

fields...



...



Back button

Name:

Ingredients:



Directions:



AddDrinkViewController

- (void) viewWillAppear: (BOOL) animated;



...



...but we will need to chan

little behavior, so we’ll ne ge a

override a couple of methed to

ods.



When we create an Controller,

AddDrinkDetailViewlass, the

it will ask its superc roller, to load

DrinkDetailViewContController.xib.

the DrinkDetailView



First, we need to create the new

View Controller.

you are here 4  231

www.it-ebooks.info



when to reuse



Q:



I still don’t get it about the new

view controller without a new nib.



A:



There’s nothing in that nib that you

couldn’t create in normal Objective-C by

hand. As you’ve likely discovered with

Interface Builder, nibs are generally a lot

easier to work with than trying to lay out

your view using code, so when you create

a new view, you typically create a nib to go

with it. But really, you could build an entire

application without a single nib.

In our case, we’re going to do something

somewhere in the middle: we’re going

to create a new view but reuse the UI

information from another view.



Q:



So why the “Watch it” warning

about reusing the nib? Is this a good idea

or not?



A:



Unfortunately, the answer is: it

depends. For DrinkMixer, we can reuse

our DetailDrinkView and its nib since we

want the layouts to look the same and the

DetailDrinkView doesn’t really do anything

specific. However, in a more complex

application, you might run into problems

where you’re constantly fighting between the

two view controllers or you have to expose

so much information to the subclass that

your code becomes unmaintainable. This

isn’t a problem unique to iOS development;

you always have to be careful when you start

subclassing things.



For our app, subclassing works fine, and

you’ll see it in some of Apple’s example

applications, too (which is part of the reason

we included it here). But it’s equally likely

that in some other application you’ll want

views to be similar, but not quite exactly the

same. In those cases, create a new view

controller and nib.



232   Chapter 5

www.it-ebooks.info



Q:



Do you usually have all your

table cell initialization code in

cellForRowAtIndexPath?



A:



It depends on how complex your table

view and cells are. If your cell configuration

is simple, sure. As you get more complicated

table views (in particular, grouped table

views with different kinds of cells), it gets

unwieldy. Instead, consider creating helper

methods that can configure a particular kind

of cell.



Another really important thing to keep

straight is resetting a cell back to defaults.

Your cellForRowAtIndexPath should always

reset a cell back to default values before

using it—you just don’t know where it’s been.

Obviously, you can factor that code out into

a helper method too, but don’t forget to do it!



plists and modal views



Use Xcode to create a View Controller without a nib

What we’ll do is create a new ViewController in Xcode that

doesn’t have its own nib, and then tweak it to inherit from the

DrinkDetailViewController. This new view will get all of the fields,

behavior (which we’ll change), and the nib we need.



Get into Xcode and create the AddDrinkViewController files.



Create a new UIViewController subclass named

AddDrinkViewController without a nib using the New File

dialog box.



Watch the options in the

new file creation...You don’t

want a xib with the view.



Open up the new AddDrinkViewController.h file and change it to inherit

from DrinkDetailViewController instead of the UIViewController. Don’t

forget to import the DrinkDetailViewController.h file.



new behavior

We’ll add the minute...

we need in a



you are here 4  233

www.it-ebooks.info



inherit the drink detail view controller



Get into Xcode and create the

AddDrinkViewController files.



In the New File dialog box, you need to create new

UIViewController subclass files. Be sure to uncheck the

With XIB for user interface box, since we don’t

need that .xib file.



In order to use the DrinkDetailViewController,

we need to import the header so the compiler

knows what we’re talking about.



#import



#import “DrinkDetailViewController.h”



@interface AddDrinkViewController : DrinkDetailViewController{

}



@end



By default, our View

Controller inherited from

UIViewController. Change that to

DrinkDetailViewController here.



The AddDrinkViewController.m file can

stay exactly as it is generated by Xcode.



Q:



Wait, why aren’t we just passing

the nib into the AddDrinkViewController?

Why all this subclassing stuff?



A:



We could do that, but the problem

is we’re not just dealing with GUI

layout. We have text fields and labels

in there that need to get populated. Our

DetailedDrinkViewController already has

outlets for all the fields we need, plus it

has the functionality to populate them with

a drink before it’s shown. We’d have to

reimplement that in our new view controller if

we didn’t subclass.



Q:



Is this some kind of contrived

Head First example, or should I really be

paying attention?



A:



You should be paying attention. This

pattern shows up pretty often and a lot of

Apple’s example applications use it. It’s

very common, particularly in table-driven

applications, to have one view that just

displays the data and another to edit it when

the user puts the table in editing mode (we’ll

talk about that more later). Sometimes you

should use totally different views; sometimes

you can reuse one you have.



234   Chapter 5

www.it-ebooks.info



AddDrinkViewController.h



Q:



You mentioned that fields are

protected by default. What if I wanted

private fields in my class?



A:



It’s easy—just put @private (or

@public for public fields) in your interface

definition before you declare the fields. If

you don’t put an access specifier there,

Objective-C defaults to protected for fields.



plists and modal views



Jim: Now we have an AddDrinkViewController class, so all we

have to do is push it on the stack like we did with the detail view,

right?



Joe



Frank



Joe: That makes sense—we used the Navigation Controller to

drill down into the data just by pushing a detailed view on the

stack...

Frank: Adding a new drink to our list is a little different,

though.

Jim: Why?

Frank: Well, adding a new drink is really a sub-task.

Joe: Huh?

Frank: The users are stepping out of the usual browsing drinks

workflow to create a new drink.

Joe: Oh, that’s true. Now they’re typing, not reading and

mixing a drink.



Jim



Frank: Right, so for times like this, it’s important to

communicate to the users that they have to complete the task.

Either by finishing the steps or—

Joe: —or by cancelling.

Frank: So, what kind of view is that?



Which of these views better communicates what the user

needs to do? Is one more ambiguous than the other?



you are here 4  235

www.it-ebooks.info



modal views are animated



Modal views focus the user on the task at hand...

When users navigate through your app, they are used to seeing views pushed and popped

as they move through the data. However, some tasks are different than the normal drilldown navigation and we really need to call the user’s attention to what’s going on. iOS

does this through modal views. These are normal views from your (the developer’s)

perspective, but feel different to the user in a few ways:



The modal view

going to cover upis

navigation contro the

l...

When you pus

using pushViewh a view onto the stack

navigation con Controller:animated:, the

from the side troller slides the view in

it) and creates(if you said to animate

button in the a Back navigation

nav bar.



he viewthe full

t

,

w

e

i

v

modal m and covers. Users

a

y

a

l

p

o

ou dism the bott vigation bavriew before

y

n

e

h

W in fro

he na

odal

ls ides —including t the new m application.

screento deal withue with the

have can contin

they



Modal views ha

either by savingve to be dismissed,

cancelling out of the changes or

the view.



... like adding or editing items

We’re going to use a modal view when users want to add a new drink

to DrinkMixer. They have to either save the added drink or discard

(cancel) it before they can return to the main DrinkMixer app. So we

want a view that encourages the user to make that choice.



236   Chapter 5

www.it-ebooks.info



plists and modal views



Any view can present a modal view

Up until now, we’ve presented new views using our Navigation Controller.

Things are a little different for modal views: any UIViewController can show

a modal view, then dismiss it when necessary. To display a modal view on

top of the current view, simply send the current view the presentModalView

Controller:animated: message. Since our RootViewController is the View

Controller that needs to show the modal view, we can just send this message

to ourselves, using self, like this:

[self presentModalViewController:addViewController animated:YES];



rd

self is the Objective-C keywotly

ren

cur

is

t

tha

for the object

to

executing the method. It’s similar

“this” in Java or C++.



ller

This is the View Controa modal

as

you want displayed new

view, in our case, the ller.

AddDrinkViewContro



n

If you say NO to animated, the

ing

say

By

the view just appears.

YES, we get the smooth slide in

from the bottom.



Update the RootViewController.m file to display our AddDrinkViewController

when the + button is tapped.



Import the AddDrinkViewController.h so the RootViewController knows what class

you’re talking about.



Change the addButtonPressed:sender: method to create an AddDrinkViewController,

and present it as a modal view. Be careful about your memory management—don’t

leak references to the controllers.



you are here 4  237

www.it-ebooks.info



create your modal view



Update the RootViewController.m file to display our AddDrinkViewController in

a UINavigationController when the + button is tapped.



#import “RootViewController.h”



y here—just

sa

o

t

h

c

u

m

t

No

ile.

import the f



#import “DrinkConstants.h”



#import “DrinkDetailViewController.h”



#import “AddDrinkViewController.h”



RootViewController.m



#pragma mark -



#pragma mark Actions



- (IBAction) addButtonPressed: (id) sender







NSLog(@”Add button pressed!”);



e

Controller just like th

iew

kV

rin

dD

Ad

e

th

lass.

e

at

su

Alloc

ller—remember, it’s a bc

ro

nt

Co

iew

kV

rin

dD

ile

ta

{ De

It uses the same nib, too.



AddDrinkViewController *addViewController = [[AddDrinkViewController

alloc] initWithNibName:@”DrinkDetailViewController” bundle:nil];













}



[self presentModalViewController:addViewController animated:YES];

[addViewController release];



Now we just need to show the mo

dal view—since

RootViewController is a ViewCont

just call presentModalViewContr roller, we

oller and iOS

handles the rest.



The RootViewController will retain a reference

View Controller when we present it. Don’t forg to the new

et to release

the reference to the View Controller!



238   Chapter 5

www.it-ebooks.info



RootViewController.m



plists and modal views



Test Drive



Now that the add view is fully implemented, build and run the project. Make sure

you try out all the functionality: scrolling, drilling down to details, and finally adding a

drink. You’ll see there’s still a little work left to be done...



Try clicking

around,

between

fields.







If your keyboard isn’t working, your

fields might still not be editable.



Back in Chapter 4, we had you make the fields

uneditable in the utilities panel. If your keyboard

isn’t appearing, try going back into Interface

Builder and checking that the fields are now editable.



Touch in the

title to bring

up the keyboard

and make sure it

works.



But what about

after you finish

typing?

you are here 4  239



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

We need a view...but not necessarily a new view

Tải bản đầy đủ ngay(0 tr)

×