Developers Club geek daily blog

1 year, 2 months ago
Once I almost completely refused a mouse for navigation on Xcode and is quite glad to it. The following step is a failure from visual control facilities a debugger. What for? — we Increase opportunities, we reduce time of a debag, we spend less calories for movement of a tyazhelenky ruchishka (calories are necessary to us, that to work the head) and by that we provoke less tunnel syndrome.

iOs Debug Master
.
Especially new opening in article will not be, I will just sum up that you also well knew and as it can be used for someone in a new way.

I do not consider such subjects: how to work in Xcode how in general to debug the application at what moment it is necessary to do it and why that such LLDB that such Step Into and Step Over, etc.

At once to examples:

We configure the console


We refuse here from this panelka:

iOs Debug Master

And here about this we will forget soon

iOs Debug Master

Now our new best friend this tempting white canvas, it is possible to stretch it even at all length or in general all screen.

iOs Debug Master

Thanks to my colleague: it achieved my old dream — to open the debugger console in a new window. And that always strained that only opened and configured tabs as it is necessary to you then at the first breykpoint everything was bungled. That it was not we go Xcode-> Behaviours-> Edit behaviors... Further we need the section Running-> to Pause.
We select Show tab named, we write our unique name of a tab, for example there Debug (I will notice that at restarts the tab is not duplicated), at the end we put active window — it, strangely enough, opens a new tab (Cmd + T) for our debugger. Eshyo I hid an unnecessary right panel — but it at will. In general customization of the environment under different conditions is in the section Behaviours

image

Everything, we are configured, we move further.

We manage a debugger


We add to a moneybox of useful hotkey'ev who at once did not know Cmd + Shift + C. It is fast transition to the console.
Cmd + Shift + Y is to hide/show the console.
Our new commands:
Step Into — step or is short s
Step Over — next or is short n
Step Out — finish
Continue — continue or with
To disconnect all breykpointa — breakpoint disable
Behind the complete list of the lldb commands it is possible to go here here
I will not list all opportunities of the direct LLDB commands, but their list is more, than the visual Xcode environment allows to make and everyone has the right to decide to use to it similar approach or not and what commands are necessary and interesting. I will stop on what showed where to look.
Convenience of execution of commands that there is usual as in the terminal a transition to the previous/subsequent command through arrows up-down.
As a result our work with a debugger looks here so:

iOs Debug Master

Swift and obj-c! What in object?


I do not know as to you, but I was not lucky to write the project on Swift from scratch, and it was necessary with an output of a modern language in huge obj-c the project all new files to write on Swifte. I do not write about all not joining, but the main problem in debugging, probably, in the following:
We create a simple class of model on Swift

class TestObject: NSObject {
    var name: String = "name"
    var index: Int = 123
}

Now we write on obj-c a simple array with our class:
NSArray *array = @[[[TestObject alloc] init],
                 [[TestObject alloc] init],
                 [[TestObject alloc] init]];

Now we put breykpoint on the following line and we look at what we would see in Variables:

image

Familiarly? And where our name and index
Now we watch that we can hands in the console:

(lldb) p array
(__NSArrayI *) $0 = 0x00007f9a1878c6b0 @"3 objects"
(lldb) po array
<__NSArrayI 0x7f9a1878c6b0>(
<CornerApp.TestObject: 0x7f9a1870fc60>,
<CornerApp.TestObject: 0x7f9a1878c650>,
<CornerApp.TestObject: 0x7f9a1878c680>
)

(lldb) po [array debugDescription]
<__NSArrayI 0x7f9a1878c6b0>(
<CornerApp.TestObject: 0x7f9a1870fc60>,
<CornerApp.TestObject: 0x7f9a1878c650>,
<CornerApp.TestObject: 0x7f9a1878c680>
)

(lldb) po array[0]
<CornerApp.TestObject: 0x7f9a1870fc60>

(lldb) po array[0].name
error: property 'name' not found on object of type 'id'
error: 1 errors parsing expression
(lldb) po [array[0] name]
name

(lldb) 

p is print
po is print object, throws to object the message of description, pay attention that objects still can send the message of debugDescription
po array [0] .name — not to work because for a debugger a zero element in an array like id. And here sending of the message of name (po [array [0] name]) perfectly works. We do not forget, that obj-c is message oriented a programming language.

Find me


Following case: we have API — we go to the server behind the list of the countries, then we will transform them to internal logic and somewhere we store. For example, our modelView follows data in storage and looks for a modelka in the dictionary on a key:
- (CACountry *)countryByCode:(NSString *)code
{
    return  [_countries objectForKey:code];
}

What do we see in Variables? 242 countries, perfectly how to us quickly to find Russia?
image

I know, here so:
(lldb) po [_countries objectForKey:@"RU"]
<CACountry: 0x7fae00630ba0>

(lldb) po [[[_countries objectForKey:@"RU"] title] string]
Россия

Also I want to notice that in a line of a debugger autocompletion for sending of messages in objective-c perfectly works

Magic UIView


For certain, if did some nontrivial UI there were situations when something in the interface moved down and it is necessary to understand who is guilty. Thus restart the application threatens with what can it will not be possible to reproduce a situation. Here work with a debugger is irreplaceable.
As a result of execution simple
(lldb) po self.view.subviews

let's see something like it:
<UICollectionView: 0x7fd9fb81a200; frame = (0 0; 375 667); clipsToBounds = YES; opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fd9fb416cb0>; layer = <CALayer: 0x7fd9fb4067f0>; contentOffset: {0, -180}; contentSize: {375, 843}> collection view layout: <TGLStackedLayout: 0x7fd9fb410000>,
<CASortView: 0x7fd9fb4468c0; frame = (67.5 607; 240 60); clipsToBounds = YES; alpha = 0; opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fd9fb481290>>,
<UIView: 0x7fd9fb47e240; frame = (0 0; 375 687); alpha = 0; layer = <CALayer: 0x7fd9fb4895a0>>

At once we see the view set, their frames, properties, all that developers of Apple pushed in the standard message of description.
If it is necessary we can easily specify some property, it is possible to use an in-memory address directly:
(lldb) po [0x7fae2b792ba0 backgroundColor]
UIDeviceWhiteColorSpace 0 1

And here to you finally the piece of a code which can get all view of the set class on hierarchy can will seem useful. I use itself.
import UIKit

extension UIView {
    
    func debugAllSubviewsOfClass(cls: AnyClass) -> [String] {
        func goDeepAndPrint(inout views: [String], currentView: UIView) {
            for v in currentView.debugSubview() {
                views.append(v.debugDescriptionWithParent())
                goDeepAndPrint(&views;, currentView:v)
            }
        }
        var views = [String]()
        goDeepAndPrint(&views;, currentView:self)
        return views
    }
    
    func debugDescriptionWithParent() -> String {
        let parentAddress = self.superview != nil ? String(format: "%p", self.superview!) : "nil"
        return "\(self.description), parent = \(parentAddress)"
    }
    
    func debugSubview() -> [UIView] {
        return self.subviews
    }
}

extension UITableView {
    
    override func debugSubview() -> [UIView] {
        return self.subviews + self.visibleCells
    }
}

extension UICollectionView {
    
    override func debugSubview() -> [UIView] {
        return self.subviews + self.visibleCells()
    }
}

Summary


  • It is possible to work with a debugger not only through Xcode buttons.
  • How to configure opening of the console when debugging in a new tab? The beginning — the big picture
  • Fast transition to the console — Cmd + Shift + C,
    to contract/deploy the console — Cmd + Shift + Y
  • Our new commands:
    Step Into — step or is short s
    Step Over — next or is short n
    Continue — continue or with
    To disconnect all breykpointa — breakpoint disable
    There is all command list LLDB.
  • Obj-c does not see an object property of Swift-ovy of a class? It does not matter:
    (lldb) po [array[0] name]
    
  • In the variables window 242 keys at the dictionary?
    We look for quickly:
    (lldb) po [[[_countries objectForKey:@"RU"] title] string]
    Россия
    
  • We facilitate to ourselves debugging of UIView — slightly higher summary is a little useful code


All thanks who read. I hope to steam of tricks someone for himself new opened.
Described each of opportunities not in detail, but tried to show the direction for whom it is necessary — can understand more deeply or ask in comments!

This article is a translation of the original post at habrahabr.ru/post/269095/
If you have any questions regarding the material covered in the article above, please, contact the original author of the post.
If you have any complaints about this article or you want this article to be deleted, please, drop an email here: sysmagazine.com@gmail.com.

We believe that the knowledge, which is available at the most popular Russian IT blog habrahabr.ru, should be accessed by everyone, even though it is poorly translated.
Shared knowledge makes the world better.
Best wishes.

comments powered by Disqus