12/08/2018, 16:22

Developer Tools for UI Debugging

Giao diện người dùng của một ứng dụng hiện đại là một cấu trúc phức tạp. Mối quan hệ phức tạp giữa các UI elements, layout, và drawing làm cho quá trình debug trở nên khắc nghiệt. Biết các công cụ có sẵn có thể làm giảm thời gian debug và làm cho quá trình phát hiện các vấn đề một cách đơn giản ...

Giao diện người dùng của một ứng dụng hiện đại là một cấu trúc phức tạp. Mối quan hệ phức tạp giữa các UI elements, layout, và drawing làm cho quá trình debug trở nên khắc nghiệt. Biết các công cụ có sẵn có thể làm giảm thời gian debug và làm cho quá trình phát hiện các vấn đề một cách đơn giản hơn. Trong bài viết này tôi muốn làm một đánh giá nhanh các công cụ gỡ lỗi giao diện người dùng cung cấp bởi Apple.

View Hierarchy Debugger provides the ability to inspect and understand the UI hierarchy. Your app’s hierarchy, views, constraints, and view controllers, displayed as a hierarchical list. Object inspector and size inspector. And even interactive 3D model. All built in in Xcode. How cool is that! View Hierarchy Debugger cung cấp khả năng kiểm tra và hiểu được hệ thống phân cấp UI hierarchy. Hierarchy, views, constraints và view controllers, được hiển thị dưới dạng hierarchical list (danh sách có thứ bậc). Object inspector và size inspector. Và ngay cả mô hình 3D tương tác. Tất cả được xây dựng trong Xcode. Thật cool! Debug View Hierarchy button nằm trong thanh debug. UI debugging available cho iOS, tvOS, and macOS, simulator và device.

Nếu bạn thích giao diện điều khiển trên các công cụ trực quan, bạn sẽ rất vui mừng khi biết rằng UIKit bao gồm các log API. Có một vấn đề nhỏ - các API này là private. Nhưng chúng tôi không sử dụng các chức năng debug trong bản release.

-[UIView recursiveDescription]

— Print UIView hierarchy:

(lldb) po [view recursiveDescription]
<UIView: 0x7faa328013c0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x60400003e260>>
| <UILabel: 0x7faa328045d0; frame = (175 198; 95 21); text = 'Hello, world!'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x6040000916c0>>
| <UIButton: 0x7faa2f408000; frame = (152 325; 50 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x60c00003a420>>

Each UIView node includes layout and drawing information, CALayer, and additional specific fields. Mỗi UIView bao gồm layouts và drawing infomation, CALayer và các trường bổ sung cụ thể.

-[UIViewController _printHierarchy]

Similar method for UIViewController

(lldb) po [viewController _printHierarchy]
<UISplitViewController 0x7fb23a605920>, state: disappeared, view: <UILayoutContainerView 0x7fb23d80dc60> not in the window
| <UINavigationController 0x7fb23b817000>, state: disappeared, view: <UILayoutContainerView 0x7fb23d80e280> not in the window
|    | <MasterDetailTemplate.MasterViewController 0x7fb23a606140>, state: disappeared, view: <UITableView 0x7fb23b05ac00> not in the window
+ <UINavigationController 0x7fb23b01d600>, state: appeared, view: <UILayoutContainerView 0x7fb23a503150>, presented with: <_UIFullscreenPresentationController 0x7fb23d808f20>
|    | <MasterDetailTemplate.ModalViewController 0x7fb23a409660>, state: appeared, view: <UIView 0x7fb23a51dfc0>
  • Ký tự | chỉ ra child view controllers;
  • Ký tự + viết tắt của modal presentation. Method _printHierarchy đặc biệt hữu ích khi được gọi trên rootViewController của UIWindow:
(lldb) po [[[UIWindow keyWindow] rootViewController] _printHierarchy]

Cần chú ý - trong Swift console hoạt động khác nhau tùy thuộc vào trường hợp:

  • khi thực thi chương trình bị tạm dừng từ debug bar, chúng ta có thể sử dụng syntax Objective-C cho việc gửi tin nhắn, ví dụ: po [xem recursiveDescription] sẽ làm việc (với điều kiện bạn có quyền truy cập vào biến view hoặc biết địa chỉ)
  • Khi lldb dừng lại bởi breakpoint, bạn phải sử dụng Swift syntax: po view.recursiveDescription()

Tất nhiên, bạn sẽ không thể sử dụng private API trong Swift:

#if DEBUG

extension UIWindow {

    class var key: UIWindow {
        let selector: Selector = NSSelectorFromString("keyWindow")
        let result = UIWindow.perform(selector)
        return result?.takeUnretainedValue() as! UIWindow
    }
}

extension UIView {
    
    var recursiveDescription: NSString {
        let selector: Selector = NSSelectorFromString("recursiveDescription")
        let result = perform(selector)
        return result?.takeUnretainedValue() as! NSString
    }
}


extension UIViewController {
    
    var printHierarchy: NSString {
        let selector: Selector = NSSelectorFromString("_printHierarchy")
        let result = perform(selector)
        return result?.takeUnretainedValue() as! NSString
    }
}

#endif

Lưu ý, lệnh po print các ký tự đặc biệt trong String. NSString khi print sẽ thuận tiện hơn. Bây giờ bạn sẽ có thể print cả hai cấp bậc trong Swift:

(lldb) po view.recursiveDescription
(lldb) po UIWindow.key.rootViewController!.printHierarchy

Trên đây tôi đã giới thiệu các bạn cách để debug UI trong iOS sử dụng công cụ có sẵn mà Apple đã cung cấp. Bài viết của mình đến đây là hết, cám ơn các bạn đã đọc bài. Nguồn: Medium

0