2017-09-15 48 views
1

我想在我的應用程序中創建一個控制檯,以便在屏幕上顯示活動或信息。它將以一個簡單的字符串「等待新消息...」開始,當不同的事情發生時,新的消息將被添加到該字符串中。當控制檯填滿時,該字段將隨每次添加而滾動,以便用戶始終在控制檯底部看到最新消息,而舊消息從頂部視圖中消失。如何在Swift應用程序中創建最小化控制檯(UILabel,UITextView,滾動,截斷頭?)

是否與「截斷頭」和一個多行的UILabel的方法嗎?我試圖先用UILabel做到這一點,但我無法總是查看字符串的END。截斷頭實際上是一行一行地工作,所以它會顯示字符串的前五行,然後顯示最後一行可見行的尾部。我嘗試了各種對齊和包裝設置,但沒有任何工作......我錯過了什麼?有沒有辦法讓UILabel總是顯示一個字符串的結尾並讓內容從頂部消失?

剪切字符串以適應每次?也許我可以將字符串切成最後一千個字符或類似的字符?但我不知道UILabel會有多大(在不同的屏幕上)...即使我做了,字體是他們的,我懷疑我可以確切地知道我應該修剪字符串的字符數量。我無法將它修剪到給定量的SPACE中,並獲得我UILabel中的空間量,對嗎?

或者,我可以使用UITextView和滾動也許這是我必須做的。我可以獲取文本視圖文本的整個值,並將新的字符串添加到UITextView中,然後使用NSMakeRange和.scrollRangeToBottom滾動到底部。

func updateConsole(switchType: String) { 

     //unwind the console's text 

     if let tempString = consoleZe.text { 
      currentText = tempString 
     } 

     consoleZe.text = currentText + "A new message here! Something clever taken from \(switchType).\n" 

     //Scroll to the bottom 

     let bottom = NSMakeRange(consoleZe.text.characters.count - 1, 1) 
     consoleZe.scrollRangeToVisible(bottom) 
} 

這似乎是我的小更新控制檯的很多工作。我不關心滾動查看過去的值。我甚至更喜歡控制檯沒有滾動...所以抓住,添加,粘貼,獲得底部,然後滾動看起來像很多額外的,不需要的行李。

上實現最小的控制檯,使用的UILabel或UITextView的或其他任何方式,歡迎所有的想法,謝謝!

回答

1

我實現了一個「控制檯視圖控制器」使用的tableview和「ConsoleBuffer」類作爲數據源。一個tableview很好地符合消息記錄控制檯的逐行定位特性,並且使自動滾動變得容易。

ConsoleBuffer是一個單獨的類,其保持在字符串和附加了一些輔助功能的一個簡單的數組控制檯消息。請參閱下面的完整ConsoleBuffer實現:

class ConsoleBuffer { 
    struct Prefs { 
     static let defaultLines = 100 
     static let maxLines = 1000 
    } 
    static let shared = ConsoleBuffer() 

    private var buffer = [String]() { 
     didSet { 
      if buffer.count > lines { 
       buffer.removeFirst(buffer.count - lines) 
      } 
      tableView?.reloadData() 
      NSAnimationContext.runAnimationGroup({ (context) in 
       if let tableView = self.tableView { 
        if let scrollView = tableView.enclosingScrollView { 
         let range = tableView.rows(in: scrollView.contentView.visibleRect) 
         let lastRow = range.location + range.length 
         if lastRow == oldValue.count - 1 { 
          context.allowsImplicitAnimation = true 
          tableView.scrollRowToVisible(buffer.count - 1) 
         } 
        } 
       } 
      }, completionHandler: nil) 

     } 
    } 

    var lines = ConsoleBuffer.Prefs.defaultLines { 
     didSet { 
      if lines > ConsoleBuffer.Prefs.maxLines { 
       lines = ConsoleBuffer.Prefs.maxLines 
      } 
     } 
    } 

    var count: Int { 
     get { 
      return buffer.count 
     } 
    } 

    var tableView: NSTableView? 

    private init() { } 

    func line(_ n: Int) -> String { 
     if n >= 0 && n < buffer.count { 
      return buffer[n] 
     } else { 
      return "" 
     } 
    } 

    func add(_ line: String) { 
     let dateStampedLine = "\(Date()) \(line)" 
     buffer.append(dateStampedLine) 
    } 

    func clear() { 
     buffer.removeAll() 
    }  
} 

這兩句話使ConsoleBuffer單身:

static let shared = ConsoleBuffer() 
private init() { } 

有一個單身可以很容易增加新的控制檯線項目中的任何位置,而不需要具有的引用該類的一個實例。私下製作init可以防止任何人致電ConsoleBuffer() - 不管您是否被迫使用其單例實例:ConsoleBuffer.shared

控制檯線串的buffer陣列是私人保持其執行隱藏舉行。當向該數組添加新行時,tableview平滑地滾動到添加的最後一行,但前提是最後一行顯示。否則,滾動位置保持不變。

數據源現在是很容易實現:

func numberOfRows(in tableView: NSTableView) -> Int { 
    return ConsoleBuffer.shared.count 
} 

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { 
    let cell = tableView.make(withIdentifier: "ConsoleCell", owner: self) as? NSTableCellView 
    cell?.textField?.stringValue = ConsoleBuffer.shared.line(row) 
    return cell 
} 

在的tableview控制器的viewDidLoad功能,你需要的ConsoleBuffertableView屬性設置爲使用的實現代碼如下。此外,這是設置線的期望最大數量的緩存陣列中的存儲地點:

ConsoleBuffer.shared.tableView = tableView 
ConsoleBuffer.shared.lines = 500 

現在你可以添加新行到控制檯這樣的:

ConsoleBuffer.shared.add("console message") 

希望這得到你走向正確的方向。

+0

感謝您分享您的實施!我的能力不足以理解你分享的大部分代碼,但將控制檯消息存儲在數組中的概念對我來說是有意義的 - 它會更加強大,並且允許我指定要顯示多少在不同的情況下。在嘗試類似的東西之前,我需要在Swift中學習更多關於tableViews和數組的知識。再次感謝,D. – Beagley

相關問題