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

more iphone 3 development phần 10 potx

64 238 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 64
Dung lượng 10,36 MB

Nội dung

CHAPTER 15: Debugging 497 Xcode rather than typing GDB commands directly, but for a few of the more important tasks, we’ll show you how to do them using the debugger console as well. Figure 15–1. The debugger window is actually an interface to the command-line program GDB, which is the debugger used by Xcode Breakpoints Probably the most important debugging tool in your arsenal is the breakpoint. A breakpoint is an instruction to the debugger to pause execution of your application at a specific place in your code and wait for you. By pausing, but not stopping, the execution of your program, you can do things like look at the value of variables and step through lines of code one at a time. A breakpoint can also be set up so that instead of pausing the program’s execution, a command or script gets executed and then the program resumes execution. We’ll look at both types of breakpoints in this chapter, but you’ll probably use the former a lot more than the latter. The most common breakpoint type that you’ll set in Xcode is the line number breakpoint. This type of breakpoint allows you to specify that the debugger should stop at a specific line of code in a specific file. To set a line number breakpoint in Xcode, you just click in the space to the left of the source code file in the editing pane. Let’s do that now so you can see how it works. Single-click RootViewController.m. Look for the method called viewDidLoad. It should be one of the first, if not the first method in the file. On the left side of the editing pane, you should see a column with numbers, as in Figure 15–2. This is called the gutter, and it’s one way to set line number breakpoints. CHAPTER 15: Debugging 498 Figure 15–2. To the left of the editing pane is a column that usually shows line numbers. This is where you set breakpoints TIP: If you don’t see line numbers or the gutter, open Xcode’s preferences and go to the Text Editing section. The first two check boxes in that section are Show gutter and Show line numbers. It’s much easier to set breakpoints if you can see the gutter and the line numbers. Regardless of whether you have Show Gutter checked, the gutter will appear while debugging. Look for the first line of code in viewDidLoad, which should be a call to super. In Figure 15–2, this line of code is at line 22, though it may be a different line number for you. Single-click in the gutter to the left of that line, and a little arrow should appear in the gutter pointing at the line of code (Figure 15–3). You now have a breakpoint set in the RootViewController.m file, at a specific line number. CHAPTER 15: Debugging 499 Figure 15–3. When a line number breakpoint is set, it will appear in the gutter next to the line of code where it will pause the program’s execution You can also remove breakpoints by dragging them off of the gutter, and move them by dragging them to a new location on the gutter. You can temporarily disable existing breakpoints by single-clicking them, which will cause them to change from a darker color to a lighter color. To re-enable a disabled breakpoint, you just click it again to change it back to the darker color. Before we talk about all the things you can do with breakpoints, let’s try out the basic functionality. Select Build and Debug – Breakpoints On from the Build menu or press Y to build and run the application with GDB attached. The program will start to launch normally, then before the view gets fully shown, you’re going to be brought back to Xcode, and the project window will come forward, showing the line of code about to be executed and its associated breakpoint. NOTE: In the toolbar at the top of the debug and project windows is an icon labeled Breakpoints. As its name implies, clicking that icon toggles between breakpoints on or breakpoints off. This allows you to enable or disable all your breakpoints without losing them. Note that Build and Debug – Breakpoints On forces this setting to on and then launches the debugger. The Build and Debug menu item launches the debugger with or without breakpoints, depending on this setting. CHAPTER 15: Debugging 500 Let’s bring the debugger into the mix. Select Debugger from the Run menu, or type Y to bring up the debugger window (Figure 15–4). At the bottom of the debugger and most other Xcode windows, you’ll see a message along the lines of: GDB: Stopped at breakpoint 1 (hit count : 1)- '-viewDidLoad - Line 22' That’s Xcode passing along a message from the debugger, telling us that execution has paused at line 22 of RootViewController.m. That bottom portion of the window (you’ll find it in the project and console windows as well) is called the c, and it’s a good idea to keep an eye on it while debugging, as it will tell you the last status message from the debugger. Figure 15–4. Xcode’s debugger window comes forward when the application stops at a breakpoint The Debugger Editing Pane The bottom pane of the debugger window is an editing pane, just like the one in your project. You can edit your project’s source code here. But notice that there’s also a red arrow and a highlighted line in the source. That’s our visual indication that we are currently stopped and using the debugger. The program is still running, but it’s paused so we can see what’s going on. This red arrow and highlighted line will start at a breakpoint, but as you’ll see in a few minutes, you can continue the execution of the program one command at a time. CHAPTER 15: Debugging 501 The Stack Trace The upper-left pane of the debugger window is called the stack trace, and it shows the method and function calls that got us here. The call immediately previous to the call to viewDidLoad was a call to the view accessor method on an instance of UIViewController. You might be confused to see an instance of UIViewController in the stack trace. Don’t be. Since we didn’t override view, the UIViewController version of view was called and, therefore, that version of view was placed in the stack trace. When a class doesn’t override a method implemented by its superclass, the superclass’s version of the method shows up in the stack trace. In this case, that call to view was actually made on RootViewController, even though the stack trace is reporting it’s being called on UIViewController. That’s because the stack trace is showing you not what the object instance is, but where the code that was called exists, and the accessor method view exists on UIViewController. The method before that was the method contentScrollView, also on an instance of UIViewController. The methods before that in the stack trace all have underlines at the beginning of their names, which tells us that those are Apple’s super-secret internal methods that we don’t have access to and should never, ever call. Methods in the stack trace that are listed in black are ones for which we have access to the source code. Generally, these will be methods we’ve written, or at least that are contained in our project. Methods in the stack trace that are in gray are ones that are contained in frameworks or libraries that we’ve linked against and for which we don’t have access to the source code. At our current breakpoint, only the method we’re in is our own, the rest are gray, meaning we didn’t write those methods. If you click on a black row in the stack trace, the editing pane will show you the source code for that method. If you click on a gray row, then it will just show you the disassembly (the assembly language representation of machine code) for the listed method. You can step through disassembly, but unless you understand assembly language for the processor being used, it probably won’t make much sense. NOTE: The disassembly you see will look very different when running on the device and when running in the simulator. In the simulator, you’re looking at Intel X86 assembly, but when working on a device, you’re looking at ARM assembly. A discussion of assembly language is way beyond the scope of this chapter, but you can find out more about ARM assembly by reading http://www.arm.com/miscPDFs/9658.pdf and you can learn more about Intel assembly by going to http://www.intel.com/products/processor/manuals/index.htm. Although simpler bugs are often self-contained with a single-method, more complex bugs rarely are, and being able to track the flow of method and function calls that led up to a problem can be incredibly useful. CHAPTER 15: Debugging 502 The Variable List The upper-right pane of the debugger window is the variable list, and it displays all of the variables that are currently in scope. A variable is in scope if it is an argument or local variable from the current method, or is an instance variable from the object that contains the method. In fact, if you look at the variable list, you’ll see that they’re divided by type. NOTE: The variable list will also let you change a variable's value. If you double-click any value, it will become editable, and when you press return to commit your change, the underlying variable will also change in the application. Global variables are also in scope for any function or method, but they are treated a little differently. By default, no global variables are included in the variable list. The reason for this is that there are potentially an awful lot of global variables spread throughout the various frameworks that you might link into your program. Even if your program doesn’t explicitly declare any global variables, there could still be dozens, maybe even hundreds, of global variables, most of which you’ll never care about. As a result, global variables are opt-in. You have to specifically tell Xcode you want to see a specific global variable in the list. If you click the disclosure triangle next to the Globals row in the variable list, instead of revealing a list of variables, it will pop up a new window (Figure 15–5). Figure 15–5. Globals are opt-in. You select them from this window, either by browsing a specific framework or library, or by using the search field. This window is showing you a list of all the frameworks and libraries that are available to your application. If a framework hasn’t been loaded or doesn’t contain any global variables, that framework will have an empty list of global variables. Among the list of CHAPTER 15: Debugging 503 libraries and frameworks is one with the same name as our application. In our case, that would be a listing for a framework called DebugMe. That is where you would find any global variables declared in our application. When a global variable exists, it will be listed and will contain a checkbox to the left of it. If you check the box, the selected global variable will become visible in the variable list. After the global variables are a number of other sections for processor registers. Registers are small amounts of storage on the processor that you can access very quickly. Unless you’re hand-coding assembly, you won’t generally be using registers directly. If you understand the architecture of the processors on your devices, these can yield some useful information, but generally you won’t need these until you get to the point where you’re doing some pretty advanced work, far beyond the scope of this chapter. The Debugging Controls In the toolbar of the debugger window, you’ll see several buttons that you can use to control the execution of your program when stopped at a breakpoint (Figure 15–5). Figure 15–6. The debugging controls give you control over the execution of the program The leftmost button, when pressed, will restart your program. This is functionally equivalent to quitting your program and then re-launching using the debugger. This button doesn’t cause your application to be rebuilt, so changes you’ve made to your code since the last time you built won’t be included. The Continue button resumes execution of your program. It will pick up right where it left off and continue executing as normal unless another breakpoint or an error condition is encountered. The Step Over and Step Into buttons will allow you to execute a single line of code at a time. The difference between the two is that Step Over will fire any method or function call as a single line of code, skipping to the next line of code in the current method or function, while Step Into will go to the first line of code in the method or function that’s called and stop there. When you use Step Into, the method you were in gets pushed down one in the stack trace, and the called method becomes the top method in the stack trace. When your program is stopped at a line of code that isn’t a function or method call, these two buttons function identically. The Step Out button finishes execution of the current method and returns to the method that called it. This effectively pops the current method off the stack trace’s stack (you didn’t think that name was accidental did you?) and the method that called this method becomes the top of the stack trace. That might be a little clearer if we try it out. Stop your program. Note that even though your program might be paused at a breakpoint, it is still executing. To stop it, click on CHAPTER 15: Debugging 504 the stop sign in the toolbar at the top of the debugger window or select Stop from the Run menu. We’re going to add some code that might make the use of Step Over, Step Into, and Step Out a little clearer. NESTED CALLS Nested method calls like this combine two commands in the same line of code: [[NSArray alloc] initWithObject:@"Hello"]; If you nest several methods together, you will skip over several actual commands with a single click of the Step Over button, making it impossible to set a breakpoint between the different nested statements. This is the primary reason that we avoid excessive nesting of message calls. Other than the standard nesting of alloc and init methods, we generally prefer not to nest messages. Dot notation has changed that somewhat. Remember, dot notation is just shorthand for calling a method, so this line of code is also two commands: [self.tableView reloadData]; Before the call to reloadData, there is a call to the accessor method tableView. If it makes sense to use an accessor, we will often use dot notation right in the message call rather than using two separate lines of code, but be careful. It’s easy to forget that dot notation results in a method call, so you can inadvertently create code that is hard to debug by nesting several method calls on one line of code. Trying Out the Debug Controls In Xcode, the file RootViewController.m should still be showing in the editor pane. Note that you can go back to the project window to edit your source code, but you can also do that in the debugger window. Makes no never mind to us. If you don’t see RootViewController.m, go back to the project window and single-click on RootViewController.m in the Groups & Files pane. Now, add the following two methods immediately before viewDidLoad. - (float)processBar:(float)inBar { float newBar = inBar * 2.0; return newBar; } - (NSInteger)processFoo:(NSInteger)inFoo { NSInteger newFoo = inFoo * 2; return newFoo; } And insert the following lines of code into the existing viewDidLoad method: - (void)viewDidLoad { [super viewDidLoad]; NSInteger foo = 25; float bar = 374.3494; NSLog(@"foo: %d, bar: %f", foo, bar); CHAPTER 15: Debugging 505 foo = [self processFoo:foo]; bar = [self processBar:bar]; NSLog(@"foo: %d, bar: %f", foo, bar); // Set up the edit and add buttons. self.navigationItem.leftBarButtonItem = self.editButtonItem; Your breakpoint should still be set at the first line of the method. Xcode does a pretty good job of moving breakpoints around when you insert or delete text from above or below it. Even though we just added two methods above our breakpoint and the method now starts at a new line number, the breakpoint is still set to the correct line of code, which is nice. If the breakpoint somehow got moved, no worries; we’re going to move it anyway. Click and drag the breakpoint down until it’s lined up with the line of code that reads: NSInteger foo = 25; Now, choose Build and Debug from the Build menu to compile the changes and launch the program again. If the debugger window is not showing, bring it to the front. You should see the breakpoint at the first new line of code we added to viewDidLoad. The first two lines of code are just declaring variables and assigning values to them. These lines don’t call any methods or functions, so the Step Over and Step Into buttons will function identically here. To test that out, click the Step Over button to cause the next line of code to execute, then click Step Into to cause the second new line of code to execute. Before using any more of the debugger controls, check out the variable list (Figure 15– 7). The two variables we just declared are in the variable list under the Local heading with their current values. Also, notice that the value for bar is red. That means it was just assigned or changed by the last command that executed. NOTE: As you are probably aware, numbers are represented in memory as sums of powers of 2 or powers of ½ for fractional parts. This means that some numbers will end up stored in memory with values slightly different than the value specified in the source code. Though we set bar to a value 374.3494, the closest representation was 374.349396. Close enough, right? CHAPTER 15: Debugging 506 Figure 15–7. When a variable was changed by the last command that fired, it will turn red in the variable list There’s another way you can see the value of a variable. If you move your cursor so it’s above the word foo anywhere it exists in the editor pane, a little box will pop up similar to a tooltip that will tell you the variable’s current value and type (Figure 15–8). Figure 15–8. Hovering your mouse over a variable in the editing pane will tell you both the variable’s datatype and its current value The next line of code is just a log statement, so click the Step Over button again to let it fire. The next two lines of code each call a method. We’re going to step into one and step over the other. Click the Step Into button now. The red arrow and highlighted line of code should just have moved to the first line of the processFoo method. If you look at the stack trace now, you’ll see that viewDidLoad is no longer the first row in the stack. It has been superseded by processFoo. Instead of one black row in the stack trace, there are now two, because we wrote both processFoo and viewDidLoad. You can step through the lines of this method if you like. When you’re ready to move back to viewDidLoad, click the Step Out button. That will return you to viewDidLoad. processFoo will get popped off of the stack trace’s stack, and the red indicator and highlight will be at the line of code after the call to processFoo. [...]... declarations, 33 1– 33 3 designing interface, 33 3 33 5 implementing stubs, 33 5 applicationMusicPlayer method MPMusicPlayerController, 419 applications, localizing, 100 applicationWillResignActive method, 240 applicationWillTerminate, 23 24 archiving objects, 235 – 236 ARM assembly, 501 arrays contentsForTransfer method, 2 93 531 532 Index controlling table structure with, 87– 90 creating, 99 100 creating... connections, debugging, 525 music playing application, 428– 430 setting up application skeleton, 33 1– 33 3 StalledViewController, 454 action methods action declarations, application skeleton, 33 3 MapMeViewController, 38 4 RequestTypes application, 35 3 Activity Indicator View, 33 4 addAnnotation method, 37 1 addAnnotations method, 37 1 addAttachmentData method, 39 5 addDependency method, 476 addOperation method, 478... 4 13 alert views, 152, 245, 265, 266, 268 alertView:clickedButtonAtIndex method, 154 alertView:didDismissButtonWithIndex method, 76, 78 amAcceptingConnections variable, 234 AND operator see bitwise AND (&) operator annotation object, MapKit, 37 0 writing MapMe class, 37 8 38 0 annotation view, MapKit, 36 2, 37 0 MapMeViewController, 38 8, 38 9 providing map view with, 37 2 annotations, MapKit, 36 1, 36 9 37 3... 89 populating, 99 101 removing, 1 93 subarrays, 88 artwork, retrieving media items, iPod library, 4 13 aspect ratio accommodating, 36 7 coordinate regions, map view, 36 5 assembly language, 501 assign keyword, 297 asynchronous data retrieval, 34 4 35 0 adding to WebWorks, 34 6 35 0 NSURLConnection delegate methods, 34 5 34 6 atomicity and thread safety, 472–4 73 attachments, adding to e-mail, 39 5 attribute controllers... removing, 37 1 annotation object, 37 0 annotation view, 37 0 MapMeViewController, 38 8 providing map view with annotation views, 37 2 selecting annotations, 37 2 API documentation, 91 Apple documentation, 528 Apple mailing lists, 528 application architecture, 43 application delegate adding to, 45–46 modifying interface, 44–45 application music player controller, 419 application skeleton, setting up, 33 1– 33 6 action... your iPhone apps a snap And If All Else Fails… Drop Dave and Jeff an e-mail: daveandjeff@iphonedevbook.com Farewell We sure are glad you came along on this journey with us We wish you the best of luck, and hope that you enjoy programming the iPhone as much as we do Index ■A abstract entities, 53 accessors, 147 virtual accessors, 151 action declaration MailPic application, 39 7 MapMe application, 37 5... 115–117 string, 112–115 using, 118–120 attribute types Transient, 137 attributes, 19–20 adding to data model, 140–1 43 adding to entities, 54, 59–60 adding validation to, 142–1 43 calculated, 151 default values, 137 , 146–147 displaying new, 161–1 63 editing, 55 formatting, 92–94 name, 54 read-only, 146, 166 setting type, 58–59 transformable, 138 , 142, 146, 147, 155, 156, 161, 167 types, 56–59 view-only, 165–166... 110 111 batch object fixing Stalled application with timer, 460–462 beginGeneratingPlaybackNotifications method, 4 23 Beginning iPhone 3 Development (Apress), 2 beginSeekingBackward method, 421 beginSeekingForward method, 421 Berkeley sockets API online network play, 271 big-endian byte ordering, 279 Binary datatype, 57–58 bit fields (bit flags), 409 bitwise AND (&) operator comparing mediaType, 410. .. including some who work at Apple, contribute to this site by answering questions and posting sample code Blogs Check out these blogs: http://iphonedevelopment.blogspot.com/: Jeff’s iPhone development blog Jeff posts sample code, tutorials, and other information of interest to iPhone developers http://davemark.com/: Dave’s little spot in the sun Not at all technical, just full of whimsical ephemera that catches... particularly true of iPhone development technologies The programming language and frameworks we’ve been working with in this book are the end result of well over 20 years of evolution And Apple engineers are always feverishly working on that Next Cool New Thing™ Despite being much more mature than it was just a year ago, the iPhone platform has still just begun to blossom There is so much more to come By . than the value specified in the source code. Though we set bar to a value 37 4 .34 94, the closest representation was 37 4 .34 939 6. Close enough, right? CHAPTER 15: Debugging 506 Figure 15–7. When. beyond the scope of this chapter, but you can find out more about ARM assembly by reading http://www.arm.com/miscPDFs/9658.pdf and you can learn more about Intel assembly by going to http://www.intel.com/products/processor/manuals/index.htm viewDidLoad method: - (void)viewDidLoad { [super viewDidLoad]; NSInteger foo = 25; float bar = 37 4 .34 94; NSLog(@"foo: %d, bar: %f", foo, bar); CHAPTER 15: Debugging 505 foo =

Ngày đăng: 12/08/2014, 21:20

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN