2017-02-10 39 views
0

我需要通過顯示分數和小數的一列,對準他們,所以小數點或正斜槓字符出現在像這樣同一列的textView格式化數字的列...有沒有更好的方法來對齊Swift textView中的這一列數字?

x  1/1 
    1  76.04900 
    x 193.15686 
    x 310.26471 
    4  5/4 
    x 503.42157 
    6 579.47057 
    x 696.57843 
    x  25/16 
    9 889.73529 
    x 1006.84314 
    11 1082.89214 

這在Swift中通過插入適當數量的前導空白字符並使用左對齊與列寬相同的字體來實現。

要計算空格的數量,其餘字符或被除數中的字符將從每個數字中的字符總數中排除。這個簡單的任務涉及減去.count.index(of:),被一個事實,即.index(of:)返回一個可選Array.Index?不是Int?

我懷疑有可能達到同樣的結果更簡單的方法,並歡迎雨燕下面的代碼任何改進複雜這可能會讓維持它的人更容易。代碼是從我的項目中提取的,並已在Playground中進行了測試。

注意。 textMessage是單個字符串。它當前顯示在調試區域中。它最終將顯示在textView中。

//: Playground 

    import UIKit 

    var tuningArray   = ["1/1", "76.04900", "193.15686", "310.26471", "5/4", "503.42157", "579.47057", "696.57843", "25/16", "889.73529", "1006.84314", "1082.89214"] 
    var keyArray    = ["x", "1", "x", "x", "4", "x", "6", "x", "x", "9", "x", "11"] 

    var characterCountArray = [Int]() 
    var scaleSize    = Int() 
    var textMessage   = String() 



    func formatTextMessage() { 
    var formattedTextArray  = [String](repeating: "", count: scaleSize) 

    for i in 0..<scaleSize { 
     let element   = tuningArray[i] 
     countNumericCharactersBeforeDotOrSlash (s: element) 
     } 

    let largestStringSize  = characterCountArray.reduce(Int.min, { max($0, $1) }) 

    for i in 0..<scaleSize { 

     let thisStringSize  = characterCountArray[i] 
     let blanks    = largestStringSize - thisStringSize 
     let filler    = insertWhiteSpace(count: blanks) 

     formattedTextArray[i].append("\t" + keyArray[i] + "\t" + filler + tuningArray[i] + "\n") 
     textMessage   += formattedTextArray[i] 
     } 
    print(textMessage) 
    } 



    func insertWhiteSpace(count: Int) -> String { 
    var filler     = "" 
     for _ in 0..<count { 
     filler     = filler + " " 
     } 
    return filler 
    } 



    func countNumericCharactersBeforeDotOrSlash (s: String) { 

    let fractionalNumber  = findFractionalNumber(s: s) 
    let decimalNumber   = findDecimalNumber(s: s) 
    var thisStringSize   = 0 

    if !fractionalNumber && !decimalNumber { 
     print("Error: invalid number format") 
    } 

    if fractionalNumber  == true { 

    let pitchStringArray  = Array(s.characters) 
    let endIndex    = pitchStringArray.count 

    if let slashIndex   = pitchStringArray.index(of: "/") { 
     let dividendFiller  = endIndex - slashIndex 
     thisStringSize   = s.characters.count - dividendFiller 
    } 

    } else { 

    if decimalNumber   == true { 

     let pitchStringArray = Array(s.characters) 
     let endIndex   = pitchStringArray.count 

     if let dotIndex  = pitchStringArray.index(of: ".") { 
      let remainderFiller = endIndex - dotIndex 
      thisStringSize  = s.characters.count - remainderFiller 
      } 
     } 
     } 
    characterCountArray.append(thisStringSize) 
    } 



    func findDecimalNumber(s: String?) -> Bool { 
    if (s?.contains("."))  == true { 
     return true 
     } 
     return false 
    } 



    func findFractionalNumber(s: String?) -> Bool { 
    if (s?.contains("/"))  == true { 
     return true 
     } 
     return false 
    } 



    scaleSize     = tuningArray.count 
    formatTextMessage() 
+0

Greg,你想對齊上面的文字嗎?看起來像表格合成? –

+0

是的。與Word或Excel類似,但數字需要在小數或正斜槓列上對齊以符合Scala中使用的比例標準(請參見http://www.huygens-fokker.org/microtonality/scales.html) – Greg

+0

All your十進制數字必須像上圖一樣對齊?即全部「。」。必須符合。 –

回答

1

你可以使用屬性文本自定義製表位,就像這個例子:

import UIKit 
import PlaygroundSupport 


var tuningArray   = ["1/1", "76.04900", "193.15686", "310.26471", "5/4", "503.42157", "579.47057", "696.57843", "25/16", "889.73529", "1006.84314", "1082.89214"] 

var keyArray = ["x", "1", "x", "x", "4", "x", "6", "x", "x", "9", "x", "11"] 
let scaleSize = tuningArray.count 
var textMessage = "" 

for i in 0..<scaleSize { 
    var textLine = "\t" + keyArray[i] + "\t" + tuningArray[i] + "\n" 
    textMessage += textLine 
} 

let paragraphStyle = NSMutableParagraphStyle() 
let decimalTerminators:CharacterSet = [".", "/"] 
let decimalTabOptions = [NSTabColumnTerminatorsAttributeName:decimalTerminators] 
let decimalTabLocation = CGFloat(100) // TODO: Calculate... 
var decimalTab = NSTextTab(textAlignment: .natural, location: decimalTabLocation, options: decimalTabOptions) 
var leftTab = NSTextTab(textAlignment: .left, location: CGFloat(0.01), options: [:]) 
paragraphStyle.tabStops = [leftTab, decimalTab] 

var a = NSAttributedString(string:textMessage,attributes: [NSParagraphStyleAttributeName: paragraphStyle]) 

let tv = UITextView(frame:CGRect(x:0, y:0, width:400, height:200)) 
tv.attributedText = a 
PlaygroundPage.current.liveView = tv 

唯一的缺點是,你必須以某種方式計算小數點選項卡的位置;在這個例子中,我只是使用CGFloat(100)來獲得一個很好的價值。但也許你可以簡單地生活在這樣一個常數。

Screenshot

+0

Andreas,你讓這看起來比我原來的代碼簡單得多。謝謝。我現在試圖讓它在ViewController中的Xcode項目中工作,其中電視將出現在StackViewController中。斯威夫特對我來說仍然是新的,所以我需要更多時間徹底檢查這個答案。請放心,一旦我有信心接受它,我會盡快回復您。 – Greg

+0

安德烈亞斯,你是一顆寶石!您的解決方案將我的代碼減少到現在可在我的Xcode項目中工作的單個函數。這必須是被接受的答案。 – Greg

+0

安德烈亞斯,我已經採取了進一步,但它不是那裏。如果你能抽出一點時間,請看看。 http://stackoverflow.com/q/42298647/2348597謝謝。 – Greg

1

格雷格, 而不是使用的空間來設置的列使用製表符(\ t)的樹次基於列的大小,你需要。 這將有助於以更少和更強大的編碼更好地管理代碼。

感謝

+0

Ashwin,你的意思是隻使用'「\ t」'而不是'「\ t」+ filler'? - 就像我在'formattedTextArray [i] .append(「\ t」+ keyArray [i] +「\ t」+ filler + tuningArray [i] +「\ n」)' – Greg

+0

是的,您可以使用只有\ t。但單一\ t不會幫助。您必須根據最大文本長度添加多個選項卡。 –

相關問題