1. Trang chủ
  2. » Công Nghệ Thông Tin

beginning iphone 3 development exploring the iphone sdk phần 3 doc

58 435 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 58
Dung lượng 3,76 MB

Nội dung

CHAPTER 4: More User Interface Fun90 UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure?" delegate:self cancelButtonTitle:@"No Way!" destructiveButtonTitle:@"Yes, I'm Sure!" otherButtonTitles:nil]; The initializer method took a number of parameters. Let’s look at each of them in turn. The first parameter is the title to be displayed. If you look at Figure 4-3, you can see how the title we’re supplying will be displayed at the top of the action sheet. The next argument is the delegate for the action sheet. The action sheet’s delegate will be notified when a button on that sheet has been tapped. More specifically, the delegate’s actionSheet:didDismissWithButtonIndex: method will be called. By passing self as the delegate parameter, we ensure that our version of actionSheet:didDismissWithButton Index: will be called. Next, we pass in the title for the button that users will tap to indicate they do not want to proceed. All action sheets should have a cancel button, though you can give it any title that is appropriate to your situation. You do not want to use an action sheet if there is no choice to be made. In situations where you want to notify the user without giving a choice of options, an alert sheet is more appropriate. We’ll see how to use alert sheets in a bit. The next parameter is the destructive button, and you can think of this as the “yes, please go ahead” button, though once again, you can assign any title to it that is appropriate to your situation. The last parameter allows us to specify any number of other buttons that we may want shown on the sheet. This final argument can take a variable number of values, which is one of the nice features of the Objective-C language. If we had wanted two more buttons on our action sheet, we could have done it like this: UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure?" delegate:self cancelButtonTitle:@"No Way!" destructiveButtonTitle:@"Yes, I'm Sure!" otherButtonTitles:@"Foo", @"Bar", nil]; This code would have resulted in an action sheet with four buttons. You can pass as many arguments as you want in the otherButtonTitles parameter, as long as you pass nil as the last one, but there is, of course, a practical limitation on how many buttons you can have based on the amount of screen space available. 24594ch04.indd 90 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun 91 After we create the action sheet, we tell it to show itself: [actionSheet showInView:self.view]; On an iPhone, action sheets always have a parent, which must be a view that is currently vis- ible to the user. In our case, we want the view that we designed in Interface Builder to be the parent, so we use self.view. Note the use of Objective-C dot notation. self.view is equiv- alent to saying [self view], using the accessor to return the value of our view property. Why didn’t we just use view, instead of self.view? view is a private instance variable and must be accessed via the accessor. Finally, when we’re all done, we release the action sheet. Don’t worry; it will stick around until the user has tapped a button. The Action Sheet Delegate and Creating an Alert Well, that wasn’t so hard, was it? In just a few lines of code, we showed an action sheet and required the user to make a decision. iPhone will even animate the sheet for us without requiring us to do any additional work. Now, we just need to find out which button the user tapped. The other method that we just implemented, actionSheet:didDismissWith ButtonIndex , is one of the UIActionSheetDelegate methods, and since we specified self as our action sheet’s delegate, this method will automatically get called by the alert sheet when a button is tapped. The argument buttonIndex will tell us which button was actually tapped. But, how do we know which button index refers to the cancel button and which one refers to the destruc- tive button? Well, fortunately, the delegate method receives a pointer to the UIActionSheet object that represents the sheet, and that action sheet object knows which button is the cancel button. We just need look at one of its properties, cancelButtonIndex: if (buttonIndex != [actionSheet cancelButtonIndex]) This line of code makes sure the user didn’t tap the cancel button. Since we only gave the user two options, we know that if they didn’t tap the cancel button, they must have tapped the destructive button, so it’s OK to proceed. Once we know the user didn’t cancel, the first thing we do is create a new string that will be displayed to the user. In a real application, here you would do whatever processing the user requested. We’re just going to pretend we did something, and notify the user using an alert. If the user has entered a name in the top text field, we’ll grab that, and we’ll use it in the mes- sage that we’re going to display in the alert. Otherwise, we’ll just craft a generic message to show: 24594ch04.indd 91 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun92 NSString *msg = nil; if (nameField.text.length > 0) msg = [[NSString alloc] initWithFormat: @"You can breathe easy, %@, everything went OK.", nameField.text]; else msg = @"You can breathe easy, everything went OK."; The next lines of code are going to look kind of familiar. Alerts and actions sheets are created and used in a very similar manner: UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Something was done" message:msg delegate:nil cancelButtonTitle:@"Phew!" otherButtonTitles:nil]; Again, we pass a title to be displayed, this time along with a more detailed message, which is that string we just created. Alerts have delegates too, and if we needed to know when the user had dismissed the alert or which button was tapped, we could specify self as the dele- gate here just as we did with the action sheet. If we had done that, we would now have to go conform our class to the UIAlertViewDelegate protocol also and implement one or more of the methods from that protocol. In this case, we’re just informing the user of something and only giving the user one button. We don’t really care when the button is tapped, and we already know which button will be tapped, so we just specify nil here to indicate that we don’t need to be pinged when the user is done with the alert. Alerts, unlike action sheets, are not tied to a particular view, so we just tell the alert to show itself without specifying a parent view. After that, it’s just a matter of some memory cleanup and we’re done. Go ahead and save, and then build, run, and try out the completed applica- tion. Spiffing Up the Button If you compare your running application to Figure 4-2, you might notice an interesting dif- ference. Your Do Something button doesn’t look like ours, and it doesn’t look like the button on the action sheet or those in other iPhone applications, does it? That default Round Rect Button doesn’t really look that spiffy, so let’s take care of that before we finish up the chapter. Most of the buttons you see on your iPhone are drawn using images. Don’t worry; you don’t have to create images in an image editor for every button. All you have to do is specify a kind of template image that the iPhone will use when drawing your buttons. 24594ch04.indd 92 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun 93 It’s important to keep in mind that your application is sandboxed. You can’t get to the tem- plate images that are used in other applications on your iPhone or the ones used by the iPhone OS, so you have to make sure that any images you need are in your application’s bundle. So, where can we get these image templates? Fortunately, Apple has provided a bunch for you. You can get them from the iPhone sample application called UICatalog, available at: http://developer.apple.com/iphone/library/samplecode/UICatalog/index.html Alternatively, you can simply copy them out of the 04 Control Fun folder from this book’s project archive. Yes, it is OK to use these images in your own applications; Apple’s sample code license specifically allows you to use and distribute them. So, from either the 04 Control Fun folder or the Images subfolder of the UICatalog project’s folder, add the two images named blueButton.png and whiteButton.png to your Xcode project. If you open one of these two images in Preview.app or in an image editing program, you’ll see that there’s not very much to them, and there’s a trick to using them for your buttons. Go back to Interface Builder, single-click the Do Something button, and press ⌘1 to open the attributes inspector. In the inspector, use the first pop-up menu to change the type from Rounded Rect to Custom. You’ll see in the inspector that you can specify an image for your button, but we’re not going to do that, because these image templates need to be handled a little differently. Save the nib, and go back to Xcode. The viewDidLoad Method UIViewController, our controller’s superclass, has a method called viewDidLoad that we can override if we need to modify any of the objects that were created from our nib. Because we can’t do what we want completely in Interface Builder, we’re going to take advantage of viewDidLoad. Go ahead and add the following method to your Control_FunViewController.m file. When you’re done, we’ll talk about what the method does. - (void)viewDidLoad { UIImage *buttonImageNormal = [UIImage imageNamed:@"whiteButton.png"]; UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0]; [doSomethingButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal]; UIImage *buttonImagePressed = [UIImage imageNamed:@"blueButton.png"]; UIImage *stretchableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0]; 24594ch04.indd 93 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun94 [doSomethingButton setBackgroundImage:stretchableButtonImagePressed forState:UIControlStateHighlighted]; } NOte The project template we used actually created a stub implementation of viewDidLoad but it’s com- mented out in the file. You can place the code above inside that stub, or simply re-type the method from scratch and delete the commented-out stub, whichever you prefer. This code sets the background image for the button based on those template images we added to our project. It specifies that, while being touched, the button should change from using the white image to the blue image. This short method introduces two new concepts: control states, and stretchable images. Let’s look at each of them in turn. Control States Every iPhone control has four possible control states and is always in one and only one of those states at any given moment. The most common state is the normal control state, which is the default state. It’s the state that controls are in when not in any of the other states. The highlighted state is the state a control is in when it’s currently being used. For a button, this would be while the user has a finger on the button. The disabled state is what controls are in when they’ve been turned off, which can be done by unchecking the Enabled checkbox in Interface Builder or setting the control’s enabled property to NO. The final state is selected, which only some controls support, and it is usually used to indicate that this control is turned on or selected. Selected is similar to highlighted, but controls can continue to be selected when the user is no longer directly using that control. Certain iPhone controls have attributes that can take on different values depending on their state. For example, by specifying one image for UIControlStateNormal and a different image for UIControlStateHighlighted, we are telling the iPhone to use one image when the user has a finger on the button and a different image the rest of the time. Stretchable Images Stretchable images are an interesting concept. A stretchable image is a resizable image that knows how to resize itself intelligently so that it maintains the correct appearance. For these button templates, we don’t want the edges to stretch evenly with the rest of the image. End caps are the parts of an image, measured in pixels, that should not be resized. We want the bevel around the edges to stay the same no matter what size we make the button, so we specify a left end cap size of 12. 24594ch04.indd 94 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun 95 Because we pass in the new stretchable image into our button rather than the image tem- plate, the iPhone knows how to draw the button properly at any size. We could now go in and change the size of the button in Interface Builder, and it would still be drawn correctly. If we had specified the button image right in Interface Builder, it would resize the entire image evenly, and our button would look weird at most sizes. tIP How did we know what value to use for the end caps? It’s simple really: we copied them from Apple’s sample code. Being a Good Memory Citizen Before we take our new button for a spin, there’s one more topic we’d like to discuss. With the release of iPhone SDK 3.0, Apple introduced a new method in UIViewController, which is the class from which all view controllers in Cocoa Touch descend, including Control_ FunViewController . This new method is called viewDidUnload, and it’s an important method in terms of keeping memory overhead down In Chapter 6, we’ll start talking about applications with multiple views. When you have multi- ple views, the iPhone OS will load and unload nib files to preserve memory. We’ll look at this process in-depth in Chapter 6 and throughout the rest of the book, and we don’t want you to worry too much about multiple views yet, but we do want to show you the correct way of implementing a view controller class. When a view gets unloaded, any object that your con- troller class has an outlet to can’t be flushed from memory because you have retained that object by specifying the retain keyword in the outlet’s property. Therefore, when your controller gets notified that its view has been unloaded, it is important to set all the controller’s outlet properties to nil so that memory can get freed up. Cocoa Touch will automatically re-connect your outlets when the nib file gets re-loaded, so there’s no danger with doing this, and by doing it, you will be a good memory citizen by not hog- ging memory you don’t need. Our Control Fun application is a single-view application, so viewDidUnload will never be called while the program is running. But, just because an application starts as a single-view application doesn’t mean it will always be one, so you should be a good memory citizen even when you know you can get away with not being one. Let’s be good memory citizens by adding the following method to Control_FunViewController.m to free up our outlets when our view gets unloaded: 24594ch04.indd 95 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun96 - (void)viewDidUnload { self.nameField = nil; self.numberField = nil; self.sliderLabel = nil; self.leftSwitch = nil; self.rightSwitch = nil; self.doSomethingButton = nil; [super viewDidUnload]; } Note the use of Objective-C dot notation once again. This time, since it is used as the left side of an assignment, the dot notation is equivalent to calling our mutator. For example, this line of code: self.nameField = nil; is equivalent to this line of code: [self setNameField:nil]; Think about what happens when our mutator does its thing. Remember, we synthesized our mutators using the retain keyword. First, our mutator retains the new object, then it releases the old object, and then it assigns the new object to its instance variable. In this case, the mutator retains nil, which doesn’t do anything. Next, the old object is released, which is exactly what we want to do, since that old object was retained when it was origi- nally connected. And, finally, nil is assigned to nameField. Pretty cool, eh? Once you’ve added that method, why don’t you save and go try it out? Everything should work exactly as it did earlier, but that button should look a lot more iPhone-like. You won’t see any difference in the way the application behaves as a result of adding the viewDidUnload method, but you can sleep soundly at night knowing you did the right thing. Good job, citizen! Crossing the Finish Line This was a big chapter. Conceptually, we didn’t hit you with too much new stuff, but we took you through the use of a good number of controls and showed you a lot of different imple- mentation details. You got a lot more practice with outlets and actions and saw how to use the hierarchical nature of views to your advantage. You learned about control states and stretchable images, and you also learned to use both action sheets and alerts. There’s a lot going on in this little application. Feel free to go back and play with it. Change values, experiment by adding and modifying code, and see what different settings in Inter- face Builder do. There’s no way we could take you through every permutation of every 24594ch04.indd 96 6/25/09 4:17:46 PM Download at Boykma.Com CHAPTER 4: More User Interface Fun 97 control available on an iPhone, but the application you just put together is a good starting point and covers a lot of the basics. In the next chapter, we’re going to look at what happens when the user rotates the iPhone from portrait to landscape or vice versa. You’re probably well aware that many iPhone appli- cations change their displays based on the way the user is holding the iPhone, and we’re going to show you how to do that in your own applications. 24594ch04.indd 97 6/25/09 4:17:46 PM Download at Boykma.Com 24594ch04.indd 98 6/25/09 4:17:46 PM Download at Boykma.Com Chapter 5 99 t Autorotation and Autosizing he iPhone is an amazing piece of engineering. Apple engineers found all kinds of ways to squeeze maximum functionality into a pocket-sized package. One example is the mechanism that allows applications to be used in either por- trait (tall and skinny) or landscape (short and wide) mode and to change that orientation at runtime if the phone is rotated. A prime example of this behav- ior, which is called autorotation, can be seen in iPhone’s web browser, Mobile Safari (see Figure 5-1). Figure 5-1. Like many iPhone applications, Mobile Safari changes its display based on how it is held, making the most of the available screen space. 24594ch05.indd 99 6/23/09 10:57:31 AM Download at Boykma.Com [...]... two, and then click the name of the icon After another second, the name will become editable, and you can type the new name Note that this trick works only in the icon view mode Name one view Portrait and the other Landscape Now, control-drag from the File’s Owner icon to the Portrait icon, and when the gray menu pops up, select the portrait outlet Then, control-drag from File’s Owner to the Landscape... inside the inner square represent the horizontal and vertical space inside the selected object Clicking either arrow will change it from solid to dashed or from dashed back to solid If the horizontal arrow is solid, the width of the object is free to change as the window resizes; if the horizontal arrow is dashed, the iPhone will try to keep the width of the object at its original value if possible The. .. if possible The same is true for the height of the object and the vertical arrow The four red “I” shapes outside the inner box represent the distance between the edge of the selected object and the same edge of the view that contains it If the “I” is dashed, the space is flexible, and if it’s solid red, the amount of space should be kept constant if possible Figure 5-4 The size inspector allows you to... left of the inner box) so they become dashed and look like the ones shown in Figure 5-6 With all the lines set to dashed, the size of the object will be kept the same, and it will float in the middle of the superview as the superview is resized Now, click the vertical arrow inside the box and the “I” shape both above and below the box so that your autosize attributes look like the ones shown in Figure... shows the part of the size inspector that controls an object’s autosize attributes The box on the left in Figure 5-5 is where we actually set the attributes; the box on the right is a little animation that will show us how the object will behave during a resize In the box on the left, the inner square represents the current object If a button is selected, the inner square represents that button The red... versions of the iPhone OS in your application Download at Boykma.Com 24594ch05.indd 108 6/ 23/ 09 10:57 :32 AM CHAPTER 5:  Autorotation and Autosizing 109 Add the following code, and then we’ll talk about what it’s doing: #import "AutosizeViewController.h" @implementation AutosizeViewController @synthesize button1; @synthesize button2; @synthesize button3; @synthesize button4; @synthesize button5; @synthesize... turning the iPhone into landscape mode Take a look at Figure 5 -3 Oh, dear Figure 5-2 Adding six numbered buttons to the interface Figure 5 -3 Well, that’s not very useful, is it? Download at Boykma.Com 24594ch05.indd 1 03 6/ 23/ 09 10:57 :31 AM 104 CHAPTER 5:  Autorotation and Autosizing Most controls default to a setting that has them stay where they are in relation to the left side and top of the screen There... Double-click the left button, and give it a title of Foo; then double-click the right one, and give it a title of Bar Control-drag from the File’s Owner icon to the Foo button, and assign it to the landscape ­ FooButton outlet; then do the same thing to assign the Bar button to the landscapeBar Button outlet Now, single-click the Foo button, and switch to the connections inspector by pressing ⌘2 Drag from the. .. Figure 6-1 The Stocks application that ships with iPhone has two views, one to display the data and another to configure the stock list There are also several tab bar applications that ship with the iPhone, such as the Phone application (see Figure 6-2) and the Clock application A tab bar application is a multiview application that displays a row of buttons, the tab bar, at the bottom of the screen... in the parent and keeps its size With this configuration, we are indicating that the vertical size of our object can change and that the distance from the top of our object to the top of the window and the Figure 5-7 This configuration distance from the bottom of our object to the bottom of allows the vertical size of our object the window should stay constant With this configuration, to change the . possible. The same is true for the height of the object and the vertical arrow. The four red “I” shapes outside the inner box represent the distance between the edge of the selected object and the. solid. If the horizontal arrow is solid, the width of the object is free to change as the window resizes; if the horizontal arrow is dashed, the iPhone will try to keep the width of the object. all the lines set to dashed, the size of the object will be kept the same, and it will float in the middle of the superview as the superview is resized. Now, click the vertical arrow inside the

Ngày đăng: 09/08/2014, 14:20