有没有更好的办法在Swift textView中对齐此数字列? [英] is there a better way to align this column of numbers in a Swift textView?

查看:79
本文介绍了有没有更好的办法在Swift textView中对齐此数字列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要通过显示一列小数和小数并对齐它们来格式化 textView 中的一列数字,以便小数点或正斜杠字符出现在同一位置

I need to format a column of numbers in textView by displaying a column of fractional and decimal numbers and aligning them so the decimal point or forward slash characters appear in the same column like so ...

    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中通过插入适当数量的前导空白字符并使用带有字体的左对齐来实现的,每个字符的列宽都相同。

This was achieved in Swift by inserting the appropriate number of leading whitespace characters and using left justification with a font where the column width is the same for each character.

要计算空格数,请从每个数字的字符总数中减去余数或除数中的字符。这个简单的任务涉及从 .count 中减去 .index(of:),并且由于 .index(of:)返回可选的 Array.Index?而不是 Int?

To calculate the number of whitespaces, characters in the remainder or the dividend are excluded from the total number of characters in each number. This simple task involved subtracting .index(of: ) from .count and was complicated by the fact that .index(of:) returns an optional Array.Index? not an Int?

我怀疑可能有一种更简单的方法来实现相同的结果,并欢迎对下面的Swift代码进行任何改进对于必须维持生命的人来说,生活会更轻松。该代码是从我的项目中提取的,并已在Playground中进行了测试。

I suspect there might be a simpler way to achieve the same result and welcome any improvements to the Swift code below that might make life easier for whoever has to maintain it. The code was extracted from my project and has been tested in Playground.

注意。 textMessage 是一个字符串。当前显示在调试区域中。最终将显示在 textView 中。

Note. textMessage is a single string. It is currently displayed in the Debug area. It will eventually be displayed in a 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()


推荐答案

您可以使用带有自定义制表位的属性文本,例如本例:

You could use attributed text with custom tab stops, like in this example:

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)来获得一个不错的值。但是也许您可以简单地使用这样的常量。

The only drawback is, that you have to calculate the position of the decimal tab somehow; in the example I just use CGFloat(100) to get a nice value. But maybe you could simply live with a constant like this.

这篇关于有没有更好的办法在Swift textView中对齐此数字列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆