12/08/2018, 14:57

Hướng dẫn lập trình ứng dụng cho MacOS: Part 2 - Làm việc với NSTableView

Table views là một trong những controls phổ biến nhất của các ứng dụng iOS lẫn Mac OS, tương đối quen thuộc như Finder, Mail's Messages, Reminder, Notes.... NSTableview sắp xếp data theo cột và hàng, mỗi hàng là một đối tượng và mỗi hàng là một thuộc tính của đối tượng đó. 1. Bắt đầu: Bây giờ ...

Table views là một trong những controls phổ biến nhất của các ứng dụng iOS lẫn Mac OS, tương đối quen thuộc như Finder, Mail's Messages, Reminder, Notes.... NSTableview sắp xếp data theo cột và hàng, mỗi hàng là một đối tượng và mỗi hàng là một thuộc tính của đối tượng đó.

1. Bắt đầu:

Bây giờ ta thử demo ứng dụng File Browser tương tự Finder hoặc các cửa số chọn file upload. Download project starter tại đây Run thì thấy được kết quá: Ta sẽ có một khung trống để chuẩn bị hiện danh sách file. Trong project đã có sẳn các hàm liên quan đến quản lý file để chúng ta tập trung vào tableView mà thôi. Bây giờ chúng ta thử mở File > Open… (hoặc phím tắt là Command + O): Đây sẽ là màng hình mà chúng ta sẽ clone lại để tìm hiểu về Table View. 2. Khởi tạo TableView Mở Main.storyboard trong project. Chọn View Controller Scene và kéo TableView từ Object Library vào trong view. Tiếp tục, chọn đối tượng Table Container. Click nút Pin ở Auto Layout toolbar. Ta sẽ canh 4 lề của Table Container với 4 lề của ViewController để tableView luôn tràn theo kích thướt window. Điểm qua cấu tạo của TableView:

  • TableView gồm có nhiều hàng và nhiều cột.
  • Mỗi hàng là đại diện của data object riêng biệt.
  • Mỗi cột là hiện thị thông tin đặc tính của object đó.
  • Mỗi cột đều có thể có tiêu đề.
  • Hàng tiêu đề mô tả thông tin của cột đó.

Nếu bạn đã làm việc quen với UITableView trên iOS thì thực sự choáng váng khi thấy số lượng object con của NSTableView ở MacOS. NSTableView thực sự phức tạp hơn UITableView nhiều về giao diện, đặc điểm và người dùng sử dụng cả chuột lẫn trackpad. Khác biệt lớn nhất vẫn là ở NSTableView mô tả nhiều cột và tiêu đề mỗi cột để người dùng có thể tùy biến sắp xếp. Sau đó còn có NSScrollViewNSClipView, đại diện cho việc sử lý cuộn và cắt thông tin nếu window ko đủ kích thướt. Còn có 2 NSScroller, cả 2 đều thuộc NSScrollView và mỗi cái lo việc cuộn lên xuống và trái phải.

Mặc định, Interface Builder tạo tableView có 2 Cột, nhưng chúng ta lại cần 3 cột để hiển thị tên, ngày và dung lượng file. Quay về file Main.Storyboard. Chọn vào tableView ở View Controller Scene. Và đảm bảo rằng bạn chọn TableView chứ không phải scroll view. Mở ** Attributes Inspector** và tăng con số Columns lên 3, chỉ như thế, bây giờ bạn đã có 3 cột. Tiếp theo, chọn thuộc tính Multiple, vì khi sử dụng bạn cần chọn nhiều file để sử lý, copy... Và củng cần check Alternating Rows để hiển thị màu background xen kẻ, tương tự Finder.

Đổi tên tiêu đề cột để mô tả chi tiết hơn. Chọn cột đầu tiên ở View Controller Scene. Mở **Attributes Inspector ** và đổi tên cột ở Title thành Name Tương tự với 2 cột còn lại: Đổi tên lại thành Modification DateSize Tiếp theo, chúng ta chỉnh sửa lại kích thướt của mỗi cột để hiển thị vừa đủ thông tin của cột đó. Run thử phát xem thế nào:

Bây giờ, tableView đã có 3 cột Name, Date và Size, thế kiểu loại file được thể hiện như thế nào? Ta sẽ hiển thị hình ảnh thể hiện loại file đó là gì ở phía trước tên của file đó trong cột Name. Nhảy vào lại Main.storyboard, chọn Table Cell View ở cột Name và xóa nó đi. Mở Object Library và kéo Image & Text Table Cell View vào dòng đầu tiên của cột Name hoặc ngay lại ví trí Cell vừa xóa khi nãy đều được.

Đặt tên định danh cho cell

Tất cả các cell đều cần identifier (định danh). Để có thể xác định và tái sử dụng được nó. Chọn cell đầu ở tiền cột Name, và trong Identity Inspector đổi identifier lại thành NameCellID Tương tư với cột DateDateCellID, và Size là: SizeCellID.

Hiển thị dữ liệu cho TableView:

Đã xong việc thiết kế giao diện cho TableView. Bây giờ làm sao thể hiển thị dữ liệu cho nó bây giờ? TableView hiện không biết làm thể nào để hiển thị dự liệu, dữ liệu gì, và mô tả sắp xếp nó ra sao, nên bây giờ, ta cần phải implement 2 protocols để phục vụ việc này:

  • NSTableViewDataSource: báo có bao nhiều dòng cần hiển thị
  • NSTableViewDelegate: cung cấp view cho cell của từng dòng trong từng cột. Trong biểu đồ mô tả:
  1. TableView gọi hàm numberOfRows(in:) của NSTableViewDataSource để lấy thông tin số dòng cần hiển thị.
  2. Sau đó gọi hàm **tableView(:viewFor:row:) ** của NSTableViewDelegate để view hiển thị, kèm theo view là thông tin của cell đó. Cả hàm hàm bắt buộc phải được thêm vào trong ViewController, nếu không tableView sẽ không chạy được.

Mở ViewController.swift với chế độ hiển thị Assistant editor và kéo TableView vào trong file ViewControllers để tạo ánh xạ giửa file viewControllers và TableView. Chắc chắn rằng mình đã kéo đúng TableViewtype trong popup hiện lên là NSTableView, và ConnectionOutlet. Ta sẽ đặt tên cho nó là tableView.

Bây giờ tập trung vào file: ViewController.swift. Bây giờ ta chỉ cần thêm đoạn code này vào cuối file:

extension ViewController: NSTableViewDataSource {
  func numberOfRows(in tableView: NSTableView) -> Int {
    return directoryItems?.count ?? 0
  }
}

Đây là hàm numberOfRows(in:) của protocol NSTableViewDataSource, tableView sẽ gọi hàm này và ta sẻ cung cấp cho tableView biết được là cần hiển thị bao nhiu là dòng. Ở đây, ta hiện thị số dòng mà biến array directoryItems có được.

Tiếp theo ta lại thêm đoạn code này ở cuối file ViewController.swift.

extension ViewController: NSTableViewDelegate {
  fileprivate enum CellIdentifiers {
    static let NameCell = "NameCellID"
    static let DateCell = "DateCellID"
    static let SizeCell = "SizeCellID"
  }
  
  func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var image: NSImage?
    var text: String = ""
    var cellIdentifier: String = ""
 
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .long
    dateFormatter.timeStyle = .long
 
    // 1
    guard let item = directoryItems?[row] else {
      return nil
    }
    // 2
    if tableColumn == tableView.tableColumns[0] {
      image = item.icon
      text = item.name
      cellIdentifier = CellIdentifiers.NameCell
    } else if tableColumn == tableView.tableColumns[1] {
      text = dateFormatter.string(from: item.date)
      cellIdentifier = CellIdentifiers.DateCell
    } else if tableColumn == tableView.tableColumns[2] {
      text = item.isFolder ? "--" : sizeFormatter.string(fromByteCount: item.size)
      cellIdentifier = CellIdentifiers.SizeCell
    }
    // 3
    if let cell = tableView.make(withIdentifier: cellIdentifier, owner: nil) as? NSTableCellView {
      cell.textField?.stringValue = text
      cell.imageView?.image = image ?? nil
      return cell
    }
    return nil
  }
}

Đoạn code này khai báo thõa mãn NSTableViewDelegate protocol và mô tả hàm **tableView(:viewFor:row) **, Tableview sẽ gọi hàm này cho mỗi cell của từng hàng và từng cột. Trong đoạn code trên có đoạn chính:

  1. Nếu không có data thì return là cell trống.
  2. Dựa theo cột mà mà xác định identifier sẽ sử dụng trong cell đó.
  3. Get cellView bằng hàm make(withIdentifier:owner:), sau đó truyền thông tin vào trong cell đó theo từng hàng và cột.

Tiếp theo, ta thêm 2 đoạn code này vào trong hàm viewDidLoad():, để tableView xác định được đối tượng để lấy thông tin từ đó.

tableView.delegate = self
tableView.dataSource = self

Bây giờ, ta xem biến representedObject với hàm didSet của nó, và thêm vào dòng code này: directory = Directory(folderURL: url)

Xong, bây giờ chỉ có việc sử build và chạy thử thành quả, sau khi Run xong, ta sử dụng menu: File > Open… (hoặc phím tắt Command + O), sẽ mở ra pop up chọn file như hồi nãy, ta chọn vào thử mục bất kì và open nó. Và đây là kết quả.

Kết luận

Qua đây, chúng ta sẽ biết được cách đơn giản nhất để sử dụng tableView trên MacOS. Trong phần tiếp theo, ta sẽ xử lý tiếp với việc sắp xếp, click vào hàng, cột trên tableView.

Bài liên quan

[VB.NET] Hướng dẫn lập trình ứng dụng chat facebook messager

Hôm nay, mình xin hướng dẫn các bạn viết ứng dụng chat facebook, Facebook messager bằng ngôn ngữ vb.net. Nhiều lúc các bạn không muốn vào trang web facebook để đọc thông tin, mà chỉ muốn tán gẫu thôi. Mình hướng dẫn các bạn viết ứng dụng ...

Hoàng Hải Đăng viết 2 tuần trước

Hướng dẫn lập trình ứng dụng đọc QR (Scan QR ) code sử dụng thư viện Zxing bằng VB.NET

Hôm nay, mình xin hướng dẫn các bạn lập trình một ứng dụng đọc QR cod e, sử dụng thư viện Zxing bằng ngôn ngữ VB.NET. Đầu tiên, mình xin giới thiệu, thư viện Zxing. Zxing là dự án mã nguồn mở (viết tắt của Zebra Crossing), cho phép người dùng quét " Mã ...

Trần Trung Dũng viết 2 tuần trước

Series Hướng Dẫn Lập Trình Ruby on Rails (Phần 9) Hướng dẫn xây dựng ứng dụng API đơn giản với gem doorkeeper

Chào các bạn, Hôm nay mình sẽ tiếp tục Series Hướng Dẫn Lập Trình Ruby on Rails , trong bài này mình sẽ hướng dẫn các bạn cách xây dựng một ứng dụng API đơn giản. Mình sẽ tiếp tục làm trên project đã có sẵn từ trước đến nay đó là cái Login App của chúng ta. Bạn này quên hoặc chưa có thì có thể ...

Trịnh Tiến Mạnh viết 17:16 ngày 12/08/2018

Hướng dẫn lập trình macos phần 2

Ở phần trước chúng ta đã làm quen với việc sử dụng các thành phần UI đơn giản, nên ở phần 2 này chúng ta sẽ làm quen với những UI phức tạp hơn, các bạn sẽ học cách để tùy chỉnh độ lớn của window tùy thích. Cùng với đó là cách thiết kế và chuyển màn hình hay windown để hiện trong app của bạn Hãy ...

Trịnh Tiến Mạnh viết 15:39 ngày 12/08/2018

Hướng dẫn lập trình macOS (phần 1)

Bạn đang là iOS developer và bạn muốn có hứng thú muốn chuyển sang lập trình cho macOS, rất may mắn là Apple đã giúp đỡ chúng ta có thể lập trình macOS cực kì dễ dàng, cho dù bạn có là người mới bắt đầu bước chân vào làng lập trình. Bài hướng dẫn này sẽ sử dụng ngôn ngữ Swift nên nếu các bạn chưa ...

Bùi Văn Nam viết 15:30 ngày 12/08/2018
0