Safari and Web • iOS, OS X • 41:19
The Web Inspector from Safari on OS X is now available for websites and UIWebViews on iOS, and it has a sleek new interface. See how to connect the Web Inspector to your iPhone or iPad to develop, debug, profile, and optimize the web content on your site or in your native app. Get an overview of what the Web Inspector can do, discover new features, and learn best practices to utilize this set of tools efficiently.
Speaker: Tim Hatcher
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Welcome to Debugging UIWebViews and Websites in iOS Safari. I'm Tim Hatcher. I work on the Safari team, and I hope you're as excited as I am to be here talking about developer tools for iOS. How many of you are app content developers? What about web developers? Just plain old web developers? Okay, a good mix of both.
So either way, if you've had to deal with debugging a website in mobile Safari, and you've probably been left with a lot of question marks over your head where it's not always easy to get information out of your mobile device when you're trying to debug your app or Safari. And the same applies to your app, not just Safari.
But maybe you might think, okay, well, it's Safari, right? I could use the Safari that comes on my Mac. And after all, they're built on the same WebKit engine, and Safari on Mac has some great developer tools. But Safari and iOS Safari are really not equal in a few key areas. There's differences in frame behavior. There's differences in resource limits. There's differences in the existence of touch events and the nonexistence of touch events. So that can really make debugging your website difficult in the desktop version of Safari, even though there are a lot of similarities.
Tim Hatcher But like I said, there's these great developer tools that come with Safari that you might be familiar with when you've worked on a standalone website and you've tried to get away with it. Maybe you're not using any of those advanced features in Safari for iOS, so you can. But when you really are having trouble with debugging your site, you really want to use those same tools and plug in your device and tether it up and use those same tools. it up and use the same great tools that come with Safari.
Same for the simulator. You want to open up the simulator and bring up the Web Inspector. If you've ever used the Web Inspector, that's what we're going to be talking about today, and not just for mobile Safari, but for your iOS app as well. And in Safari 6 and iOS 6, you now have the brand new Safari Web Inspector at your disposal.
And if you're first, if this is the first time seeing this, it might look somewhat familiar if you've ever used Xcode, and I'm sure a lot of you have used Xcode before. So we've taken a lot of the same cues, but I want to go over it. If you're familiar with the old Web Inspector, you might notice some similarities, and there's some new things as well. So the first question I get asked is, what are all these icons? And we're going to go over that, and we're also going to go over inspection and tweaking, and then some performance analysis and debugging issues.
So let's first go over the Web Inspector. So like I said, the first question I get asked is, what are those icons in the top left? And that's the navigation sidebar, and the switching buttons at the top are your navigation area. So let's go over the navigation bar specifically.
The first icon is where you'll find resource loads. And this is all of the resources that your page or your UIWebView bring in as part of the loading process. And each of these sidebars also has a keyboard shortcut. This one's Control 1 through 8 in this case. And this is where you'll also find frames and something we call anonymous scripts. And that's if you use the eval function, which you might or might not use. The next icon over is the Storage Navigator, and this is where you'll find cookies, anything that saves information on the device.
And then you have your instrument navigator, and this is where you'll find the timelines, the network loads, the script timeline, and layout and rendering timelines, as well as one-off JavaScript profiles that you can take if you use console.profile or a new CSS profiler that lets you see how slow or fast your CSS selectors are.
And then the next one over is self-explanatory. This is a full-text search, lets you search all of the resources and the DOM trees. Next over is the Issue Navigator, and this is where you'll find all of the JavaScript exceptions, any console errors that your page is emitting, and any HTML errors that the WebKit produces for you. And these are all grouped together in this one place. The next navigator over is the Debug Navigator, and this really is only useful when you're paused in the debugger. And this is where you'll see the current call stack.
And next to last is the Breakpoint Navigator, where you'll see all of the breakpoints for the resources in your page, and you'll only see ones for actually loaded resources and some special breakpoints for controlling when exceptions are broken on. Tim Hatcher And the final one is the Log Navigator.
And this is where you'll see your current JavaScript console log, and if you reload, you will see previous logs with all the results from any previous session. So that's a good way to switch back to see what an error might have been in an earlier session of that page.
So those are a quick overview of the navigation bar and the navigation sidebar. Next, the middle area. This is really the meat and potatoes of the Web Inspector, and this is where you find the full content of what you're looking at. And this is, you see this content based on what you get to in the navigation sidebar. But you can hide both of these sidebars and see just the content, and that leaves you really a limited way to navigate. But you have your back forward buttons and the navigation bar at the top. And let's go ahead and talk about that navigation bar.
So you have the buttons that let you hide the sidebar, and you have your back-forward buttons, so you can go back to whatever you were previously looking at in the content browser. And then you have what we call the content path, and this is the path from the navigation sidebar of where you got to that view to see that resource. And usually it's one or two levels deep, but if you're looking at a frame, you could be multiple frames deep.
And then certain views have special view selectors, and in this case, a frame that I'm looking at has the ability to switch between the original source code and the DOM tree. So you can go back and see what actually came over the network or see the actual DOM representation of that frame.
And the final thing, if you're looking at the DOM tree, you will have the current selection path. So these are all the DOM nodes, the hierarchy up to the root node of what I have currently selected in the DOM view. And like the content view selector and any of these, they're all clickable, so you can jump between siblings. So you can quickly jump to another DOM node that's a sibling of the one you have selected anywhere in this path.
And the final item, also special to the DOM, is the DOM node locator. If you've used the Web Inspector before and are looking for the magnifying glass that lets you highlight a specific element on the page, it's now this pointer icon, this finger pointer icon, that lets you select it, and it highlights in blue. And when it's in this mode, you can go tap anywhere on the device to select the DOM node. And I'll go into that in more detail later.
Tim Hatcher So that's the navigation bar. And the content area is in the middle, and that's pretty self-explanatory. That's the content that you're looking at for that resource. And at the bottom is what we call the Quick Console. And this usually starts out as a small strip, and as you type and evaluate, the results show up and automatically expand.
Tim Hatcher So it's an auto-expanding console that you can evaluate, and when you're on the current breakpoint, it's evaluating in the current scope, and you have access to special variables when you're on the DOM tree. So $0 is the current selected DOM node, so you can evaluate object properties off of that current selected DOM node.
So it's really fast and efficient if you're wanting a command line console. This is it. And you'll notice on the right-hand side, you have your debugger controls. When you're paused in the debugger, you'll see extra controls pop in. When you're not paused, you'll just have a pause button. And these let you do your standard step-over, step-in-to, step-out controls.
So that's the Content Browser and Quick Console. And the last sidebar on the right is the Details sidebar. And this is a contextual sidebar, so things come and go in this sidebar based on the current resource that's selected from the navigation sidebar and the current view. So if you have a DOM node selected, the DOM node details will change in this sidebar as well. So let's talk about some of the sidebars that you'll see in this sidebar real quick.
Tim Hatcher So you have the resource details. This one you'll pretty much always have. This is whatever details the current URL, the full URL of that resource, and any query parameters, request and response headers, things like that. And like I said, you'll pretty much always have this because almost everything is resource-based in the new Web Inspector.
The next one over is specific to the DOM view, and this is details about the current selected nodes. So you have your type, your value, any attributes, DOM properties, and event listeners are in here. Usually when you have a DOM node, it has style information. Any CSS rules that match for this DOM node, HTML attributes, base rules that are brought in by WebKit that you can't edit. The next one over is the Appearance Details, and this is where you'll find box model information about the DOM node, any position, padding, margin, that sort of thing.
The next one over is kind of rare, so we don't even have a keyboard shortcut for it. This is when you have an application cache and you have it selected in the sidebar. And you'll see the manifest and the frame URLs that this cache applies to. Again, if you're using application cache, this is probably useful information for you.
And the offline status of that application cache. And the final one only shows up when you're paused in the debugger, and this will be where you'll see all the local variables, your global variables, things like that. And this will automatically come in and select for you when you pause in the debugger.
So that's the details sidebar and overall the new Safari Web Inspector. So now let's talk about what you can actually do with the Web Inspector and how you can use it in your application and Safari. So let's talk about inspection and tweaking. So what do I mean by this? There's a long process in web development where you need to modify something, and usually it's kind of involved.
You have your resource that you want to edit, and say you're an app developer and you're building content in a UIWebView in your app. So you're in Xcode trying to edit this file, and you think you fixed something or you want to try out this change to the appearance. Tim Hatcher And you have to then, in Xcode, command R, build and run, and wait.
[Transcript missing]
So once Xcode's done getting that onto your device or in the simulator, you can now start the long process of getting to the spot in your app that reproduces this problem or has this appearance that you want to look at, and you go around tapping, following this - You can use the treasure map to try to find where you need to get in your application.
And you finally get there, And you hit a bug. And now what? You have to redo this whole process. And that's never fun. And usually the second time comes with a little more hatred and angst. So how do we solve that with the new Web Inspector? So I'm going to jump to a demo now.
So I have the iOS 6 SDK installed as well as Safari 6 installed in Mountain Lion. So I'm going to -- first things first, I need to enable the developer tools in Safari. And if you've never done this before, you need to go to Safari and go to the Safari preferences.
And in Advanced Preferences, you can enable the Develop menu, and that will give you a new menu item in Safari. And a lot of you have probably done this before. I just want to make sure to cover the basis for everyone. So that's enabling it in Safari. So now I have the iOS Simulator. I'm going to use the Simulator, but you can use your device, your iPhone, your iPad, as long as it's running iOS 6 and it's plugged in with a USB cable.
And we're just using the Simulator for demo purposes here. But it works just fine if you don't have a device or you just prefer the Simulator. This works just great. So we need to enable it in the Settings app, and we need to enable it in Safari's Settings.
And that's it. So we'll go ahead and exit out of here. And now I'm going to go ahead and open up Safari on iOS. And I have a couple tabs open. And the first one I have is Vimeo, and the other one I have is Apple.com. So let's go ahead and switch back to Safari on the Mac.
And in the Develop menu, You'll see, when I bring it up, you see a new section here for all of your devices, including the simulator. If I had an iPhone or iPad, they would also show up here. And the menu shows all of the running apps and all of the WebViews in that app, and I'm going to zoom out here. You'll notice as I mouse over the menu item, it highlights which WebView it is.
So if you have multiple WebViews in your app, this is a good way to find which one it is. And in Safari's case, it's pretty self-explanatory. But you're probably wondering where Apple.com is. It's supposed to be loaded, right? Well, Safari on iOS optimizes background tabs, and they're really not debuggable and sometimes not even loaded. So keep that in mind.
If you want to debug a website, it needs to be the frontmost app, and it needs to be usually on screen in Safari to be usable. at all. So I'm going to go ahead and open up the Web Inspector for Vimeo and just pick the menu item, and it brings up a window in Safari connected to the iPhone simulator, the Safari app, and Vimeo.com.
And you'll see the resource list over here on the side for all of the resources that Vimeo brought in. And some of them are on Vimeo's CDN server. Some of them are on other servers. And you'll notice it's kind of a lightweight site, and that's a really good thing for a mobile site.
But Vimeo has actually got pretty heavy in its content where there's all these images. And you'll notice as I scroll down, Vimeo is automatically loading in more images as I scroll down. And once I reach a certain threshold, the Web Inspector will smartly start organizing all of these resources. So now they're in folders.
based on the type of resource that was loaded. And this can be a little cumbersome if you have a really large site with a lot of subframes and things like that and you really only care about all the CSS files or all the JPEGs. And that's what the filter bar down here is for.
I'll go ahead and type in a simple glob query. So this filters out and shows me all the JPEGs that were loaded. And you can do the same for CSS or anything that came from Google. We'll immediately show you those resources. And that's a quick way to focus and find what you're actually looking for in the Web Inspector. And that applies to all of the navigators. They're all filterable in this way.
So I'll go ahead and clear that out. So I want to tweak some of the spacing on this site. I think it's a little tight, and I want to expand it and play around with it. So you'll notice as I hover over the DOM nodes here, I have the highlights, just like you would expect if you've ever used the Web Inspector before. And you'll start to be able to dig in without really even knowing the structure. I now know that all of the videos are in this sub-element.
And if I select one, I can go ahead and bring up the style information in the detail sidebar. But say I want to find it a different way. Say I don't really want to dig in and hunt and peck for it. I can use the node selector. This button right here, we'll turn it on, it'll turn blue, and now I'll go back to the device and I'll just tap on what I want to select. So I want to take a look at this byline. So that takes me right to that H3 element in this WebView.
And I can now take a look at that style information, even look at the metrics where I can see individual boxes as I hover over to see what specific one I is. So this is the margin. And I could take and double-click this value and change it to be whatever I want. And now I've updated the margin top. Tim Hatcher But you'll notice that only applied to this one element.
It's not applying to everything because it's only specific to that element. It's actually setting a style rule down here in the DOM. So we'll just go ahead and revert that. And I really want to edit the actual style rules. So in the style details, I'll go and find the margin. Whoa.
So here's the same margin rule, and this applies to all of the video H3 elements, but I noticed that they have line height as well. So I'm going to actually edit the line height and zoom out here so you can see the changes. And if I hit the arrow keys, you'll notice all of them are updating. It's incrementing and decrementing as I hit the arrow keys. And I have fine-grained control if I hold down the option key. So this is a good way to tweak and test.
Tim Hatcher Where I would have had to rebuild and test each of these individual changes. Now I can just do it all at once and take these changes back to my original code. So I like this spacing, so I'm just going to go ahead and hit enter and commit it.
And that's using the Web Inspector in Safari, but it works just as well with your application. So I have an application. It's a chat client called Colloquy. And if anyone knows me, I originally developed Colloquy for the Mac ages ago. And some of my friends have developed it for iOS, taking the same open source code and porting it over to iOS.
Tim Hatcher And I remember when they did this, their frustration of using UIWebView and making sure it worked and debugging any problems they ran into, because they used UIWebView for the chat view. And I'll just go ahead and open it up, and it's going to take a second to join a network.
And while that's loading up, it's going to be bringing in this WebView, and I have a WebView here. It's currently empty. This is where all the chat will show up. And I'm just going to go ahead and say something here. So now we have some chat information. But I have no way to know what this is, what the DOM looks like in this view, because it's all dynamic.
I can look at the original HTML, but it's just going to be blank because nothing was there. So as a developer, I want to know how to style this information. So I'm going to go switch back to Safari now. As I have Coloquy open and up, I'll go back to the iPhone simulator. And now I have a new app running. And Coloquy is the only item here. And I'm going to go ahead and select this web view.
So now I can see, for the first time, the actual DOM tree in my UIWebView, and I can dig in and see all these individual elements just like I would in Safari. And same for all the style rules, all the colors. And I can tweak any of these. Double click, tweak some of the color using the arrow keys.
[Transcript missing]
So in summary, you can finally get View Source in Safari for iOS. This is something that you've been asking for and more. You now have the whole Web Inspector available to you, not just View Source. And you can tweak without the endless rebuild cycle that you might have been used to before. Please.
And hover DOM nodes and highlight their CSS boxes on screen. And in general, anything that you can see in the DOM or style is editable, so you can double-click and tweak it. So that's inspection and tweaking. Now let's talk about performance analysis. And in the mobile space, performance is critical.
Where you have your app, it might be loading on a Wi-Fi network one minute and a cellular network the next. And you might have noticed the speed on my device, my simulator, was reduced. I was simulating a 3G connection. Tim Hatcher And with the Web Inspector, you can tether and turn off your Wi-Fi network on your device and take advantage of the actual 3G network to see how slow it actually is going to load all of your resources for your page.
And you might think, okay, I have just this single HTML file. It's not that big, and I have a script that it pulls down, and I have just a handful of images like Vimeo, and that's a really lightweight site, and if you can really achieve something like this in size, you're definitely winning. But often, things get out of hand, scope changes, you had all these images, and you're pulling down tons of resources.
And there's things you can do. You can try to group them all together, make one big file, that helps. But then you just end up with...
[Transcript missing]
And if you can reduce those library dependencies, you're really going to speed up the load time of your website. And if you're interested in this information, you should definitely attend the session that's immediately following this, which is all about updating your site and your app for better performance on an iOS device.
Tim Hatcher But don't get me wrong, images can be a big culprit here too, and if you attend the next session, you'll see why. But let's see how the Web Inspector can help us pinpoint some of these problems. Tim Hatcher So let's go back to Safari for iOS, and we're on Vimeo again. And let's bring up the Web Inspector.
And we're mostly going to talk about the instruments in this section, because this is where you can find all the fine-grained information about the page load. And the resource sidebar will give you some information, but to get the actual picture of the network load, you really need to capture that while it's loading.
Tim Hatcher And you'll notice this is blank at this point, because the Web Inspector is optimized to not record any of this information when it's not open. Tim Hatcher So you'll need to reload the page with the Inspector open to capture this load information and all the other timelines that we captured now.
And without even touching the device, I'm just going to go ahead and hit Command-Shift-R in the Web Inspector. And this is going to reload the page on my device without even touching it.
[Transcript missing]
And right now it's sorted by the timeline, and I'm going to go ahead and press this button over here, which will expand the timeline completely and just give me the name and the timeline graph. And if you've ever used the Web Inspector before, this graph is pretty familiar. If you haven't, there's two different bars. There's the light shade and the dark shade.
The light shade is how long it took for WebKit to want that resource before the server responded with the first byte. And it's 1.5 seconds later. And remember, I'm simulating a 3G network here, so that's pretty realistic on a mobile device. And the latency drastically dwarfs the actual load time because cellular networks are pretty high latency, even though they might have a lot of bandwidth to download the data. data.
And we can collapse this out and go find the highest latency thing. And you'll see it took 3.2 seconds to load this non-Vimeo resource to load this website. And remember what I was saying about scripts are usually the largest resource on the page? So let's go ahead and sort by transferred. And sure enough, some script from some server is the largest resource on this page, slowing down this page load of vimeo.com.
And we have two different size columns, size and transferred. If your server is employing GZIP encoding, the transferred size should be smaller when it's actually efficiently compressing that resource. So that's one thing to look out for. If both columns are pretty much the same size, you're not fully optimizing the download speed of that content.
So that's just a brief look at the timeline view in the new Web Inspector in the network view. But you'll notice we have three different timelines here at the top. We have The Layout and Rendering Timeline and JavaScript and Events. And this is where you'll see all of the JavaScript load events and any other events that are firing. Touch events will show up here.
This is easily the best way to find when an event is happening or a timer is firing and let you jump right to that source code. So that's a brief look at all of the different timelines. And if you want to, again, if you want to know more about optimizing your content, definitely stay for the next section where they'll talk about what optimizations you can take and put in place for your website.
So in summary, always test the cell network. If you're always testing the Wi-Fi network, you're not getting the full picture of what your users might experience if they are only living on the cell network. And minimize the number of resources and the number of large resources that you are bringing in in your page as much as possible.
Get rid of those JavaScript libraries if you're really only using the bare minimum of them anyway. Things like that. And minify, if you have to have JavaScript, which it's a necessary evil sometimes, definitely minify it so it's compressed, gzip encoded on the server, and sends down the smallest it can be.
And I'm not going to go into details, but we have some new capabilities in WebKit to do asynchronous loading or deferred script loading. So if your script doesn't need to block other loads or it doesn't need to run until the very end when DOM content is ready, then you can tell us to defer it. And again, there's going to be some more information about that in the next session.
So that's performance analysis. Now let's talk about debugging. And this is where we're going to talk about JavaScript debugging. And if you've ever written an iOS app that talks to a UIWebView, you've probably used string by evaluating JavaScript string. How many of you have used that? How many have successfully debugged a problem in that? That's what I thought.
So, Since you've, some of you have risen your hand that mastered this, you can probably tune out, but anyone else that rose their hand that has never successfully debugged a problem with this, you'll know how much of a black hole, black box that function call is, and you really have no information. Sometimes you can send something in, and it comes out just fine, but often you send something in And then you're just left wondering. What happened? Why? And all sorts of things. So let me show you another demo.
And I'm going to use Coliqui. I pointed out before that it was dynamically modifying the UIWebView. And to do that, they're using string by evaluating JavaScript string. So I'm going to switch back to Coliqui here. And while it connects, I'm going to go ahead and bring up the Web Inspector.
I know they're using a function -- they're calling a function in StringByEvaluating JavaScript String that's called appendMessage. Whenever someone types a message, it gets funneled through this function. So I'm just going to go ahead and do a search for that. And I found two hits in transcript.js. And you can see the first one is the call site, and the final one is the actual function. So let's just set a break point here. This is JavaScript after all. I should be able to debug it. So I'm going to go ahead and go back to the simulator and go ahead and type a new message. And you'll notice I'm now paused in the debugger.
So over here, it switched me to the debug sidebar, the debug navigator, and you'll see the call stack. of all of the functions that it passed through calling into where I set the breakpoint. And as I switch through here, you'll see all of the different local variables for that call frame, and you can expand and see all of the functions, arguments that came in. You can see all the objects that are local variables that are being built up.
And I really want to know what this object is that we're about to append, and I know I can use the Quick Console here. And I know it's called message, oh yeah, that's it, message wrapper. And I'm just auto-completing on the current scope for this call frame, and we'll just go ahead and evaluate it. It's undefined currently because it hasn't even been declared yet. So I'm just gonna go ahead and step with the debugger, with the controls down here. And you'll notice the tool tip tells you what all the key commands are.
I'm just going to step over until we get to this object, and I'm going to go ahead and hit the up arrow and reevaluate that. And you'll see it's now an empty div element. And this is a serialization of that DOM element. It's an actual DOM object, but we're going to show it to you as an HTML representation because that's the best way to see those things.
Tim Hatcher So I'm just going to keep stepping over as it builds up this object, this DOM node. And here it appends. So let's go ahead and log that again. And you'll see now we have another child element. And you'll see that it's building up this DOM node as we go through this function.
And let's go all the way to the end here and log the final thing. Now we have both of our DOM elements, and this is what you'll need to style it. You need to know the class names that end up, and maybe you didn't know what they were, and now you can pause in the debugger and see what they are as they're being built up. Or you run into some JavaScript error that you need to correct.
Tim Hatcher So that's using the debugger in a UIWebView. And again, this works just as well on Safari. So if you're needing to debug those touch events that you can't debug any other way, you can now pause on those touch events and see what exactly the information is you're getting.
So finally, String by Evaluating JavaScript String is no longer that black box that you have no idea what's going on inside. You can finally open up the Web Inspector, set a breakpoint, log the local variables, and see exactly what's going on with your code like you've never been able to do before.
And one tip for that debugging is call functions instead of passing in big scripts. It's easier to be able to go find the actual script like I did in Colloquy, find the function that they're calling, and set the breakpoint instead of trying to debug this string that hasn't been parsed yet. Tim Hatcher Not to mention that's a performance issue where the engine is always reparsing the same string. So try to keep your scripts small and call into functions that can have a lot of meat to them.
And you can evaluate again in the Quick Console against the current scope, and that's really handy and useful when you want to use that command line. You can also use the sidebar, the variable, the scope chain sidebar like I showed you, but if you're used to the command line and like typing, that's what you want to use.
So that's debugging with the new Safari Web Inspector in your app and Safari. So in summary, there's some sessions coming up that Talk about optimizing, like I said. And if you're really curious about optimizing for the Retina display, the new MacBook Pro, you should definitely attend the session on Wednesday talking about how to take advantage of that 4X pixel density that you'll now be able to take advantage of with your website in addition to Retina iOS devices. Tim Hatcher Talk about optimizing, like I said. And if you're really curious about optimizing, like I said. And if you're really curious about optimizing, like I said.
And I hope you like the new streamlined look in the Web Inspector. Definitely give us feedback if there's anything missing or you find something that's hard to use. You can come down to the lab or file bugs, and we'll definitely be listening. And you can finally be informed in your debugging of your app and your mobile websites in Safari.