无法在Swift中读取此闭包

时间:2016-04-04 15:47:16

标签: xcode swift dictionary closures

我已经关闭了(我带来了很多THX到dfri!)并且不知道如何改变它:

let attributesOverRanges = fooAttrString.getAttributes()
for (rng, attributes) in attributesOverRanges {
    print("Attributes over range \(rng):")
    attributes.forEach { print("\t\($0.0) = \($0.1)") }
}

这是一些结果:

Attributes over range (0,12):
    NSFont == <UICTFont: 0x7fc7f2d31330> font-family: "Helvetica Neue";    
font-weight: bold; font-style: normal; font-size: 17.00pt

现在我必须得到信息

  1. NSRange
  2. NSFont
  3. font-family:“Helvetica Neue”; font-weight:bold; font-style:normal; font-size:17.00pt
  4. 并将它们作为数组/字典。我尝试了很多,但我无法解决这个问题,感觉就像绝对的Newby我似乎是(有一个可怕的英语)! : - (

    请帮助我,

    在@rickster的答案之后,我尝试了一个粗体字体。但我得到一个错误,因为让值= $ 0.0不要检索字符串而不是字体。我可以将字体转换为字符串???我必须在字符串中找到“粗体”。或者你知道另一种检查Bold的方法

    let attributesOverRanges = fooAttrString.getAttributes()
    var newAttributes: [(NSRange, String)] = []
    for (rng, attributes) in attributesOverRanges {
        attributes.forEach {
            let value = $0.0
            if value.contains("font-weight: bold") {    // ERROR
                newAttributes.append((rng, "Bold"))
            }
        }
        print(newAttributes)
    }
    

1 个答案:

答案 0 :(得分:2)

forEach is a method on all sequence types that iterates though the sequence — it's a functional-programming version of the for-in loop. The closure passed to forEach takes one parameter, the current element of the sequence being examined. (For example, in [1,2,3].forEach { /*...*/ }, the closure parameter is an integer. In the shortest possible shorthand for writing a closure, you can refer to the parameter as $0, so in this example you could write { print($0) } for the closure.)

In your code, attributes is a dictionary. When you iterate over a dictionary, the element type is a (key, value) tuple. The shortest / label-agnostic way to address the items in a tuple is by index: foo.0, foo.1, etc.

Putting them together: in your forEach closure, $0.0 is a key in your attributes dictionary, and $0.1 is the corresponding value.

Since you're working with the attributes dictionary of an NSAttributedString, keys are attribute names ("NSFont" is the value of the NSFontAttributeName constant), and values are whatever object type corresponds to that key (in this case, an NSFont instance — what you see printed is the summary of a font that you get by asking for its description).

You can use them as a key-value pair in another dictionary (otherDict[$0.0] = $0.1), or maybe just use the value in an array since there's probably not much need to keep the "NSFont" string around (myArray.append($0.1)).


Finding out whether an NSFont instance represents a bold font is actually not a simple question with a simple answer. Remember that many fonts have a wide variety of weights — usually, a font designer will give weights above some threshold a tag that semantically identifies them as "bold", but not always.

NSFont has a companion API NSFontDescriptor that lets you get some of this semantic information. Here's a shot at getting that, along with the rest of your info, but you'll need to adapt this to fit your situation:

for (rng, attributes) in attributesOverRanges {
    print("NSRange: \(rng) - has attributes:")
    for (name, value) in attributes {
        if name == NSFontAttributeName {
            if let font = value as? NSFont {
                print("font name (use with `NSFont(name:size:)`): \(font.fontName)")

                let isBold = font.fontDescriptor.symbolicTraits & UInt32(NSFontBoldTrait) != 0
                print("is bold font: \(isBold)")
            }
        }
    }
}