ฉันจะต่อ NSAttributedStrings ได้อย่างไร


159

ฉันต้องการค้นหาสตริงและตั้งค่าคุณลักษณะบางอย่างก่อนที่จะรวมสตริงดังนั้นการมี NSStrings -> เชื่อมโยงพวกเขา -> ทำให้ NSAttributedString ไม่ใช่ตัวเลือก


13
มันเป็นเรื่องไร้สาระที่ความยากลำบากนี้ยังคงอยู่ในเดือนสิงหาคม 2559
Wedge Martin

17
แม้แต่ในปี 2018 ...
DehMotth

11
ยังอยู่ใน 2019;)
raistlin

8
ยังอยู่ในปี 2020 ...
Hwangho Kim

คำตอบ:


210

ฉันขอแนะนำให้คุณใช้สตริงประกอบที่ไม่แน่นอนที่แนะนำ @Linuxios และนี่เป็นอีกตัวอย่างของ:

NSMutableAttributedString *mutableAttString = [[NSMutableAttributedString alloc] init];

NSString *plainString = // ...
NSDictionary *attributes = // ... a dictionary with your attributes.
NSAttributedString *newAttString = [[NSAttributedString alloc] initWithString:plainString attributes:attributes];

[mutableAttString appendAttributedString:newAttString];

อย่างไรก็ตามเพื่อให้ได้ตัวเลือกทั้งหมดออกไปคุณสามารถสร้างสตริงที่มีการเปลี่ยนแปลงได้ซึ่งทำจาก NSString ที่จัดรูปแบบแล้วซึ่งมีสตริงอินพุตที่ใส่เข้าด้วยกันแล้ว จากนั้นคุณสามารถใช้addAttributes: range:เพื่อเพิ่มคุณสมบัติหลังจากข้อเท็จจริงไปยังช่วงที่มีสตริงการป้อนข้อมูล ฉันขอแนะนำวิธีเก่า แต่


ทำไมคุณแนะนำการผนวกสตริงแทนการเพิ่มคุณสมบัติ?
ma11hew28

87

หากคุณกำลังใช้ Swift คุณสามารถโอเวอร์โหลด+โอเปอเรเตอร์เพื่อให้คุณสามารถต่อข้อมูลได้แบบเดียวกับที่คุณเชื่อมสตริงปกติ:

// concatenate attributed strings
func + (left: NSAttributedString, right: NSAttributedString) -> NSAttributedString
{
    let result = NSMutableAttributedString()
    result.append(left)
    result.append(right)
    return result
}

ตอนนี้คุณสามารถต่อข้อมูลได้เพียงแค่เพิ่ม:

let helloworld = NSAttributedString(string: "Hello ") + NSAttributedString(string: "World")

5
ระดับที่ไม่แน่นอนเป็นประเภทย่อยของชั้นที่ไม่เปลี่ยนรูป
สาหร่าย

4
คุณสามารถใช้ประเภทย่อยที่ไม่แน่นอนในบริบทใด ๆ ที่คาดว่าจะมีประเภทผู้ปกครองที่ไม่เปลี่ยนรูป แต่ไม่กลับกัน คุณอาจต้องการตรวจสอบคลาสย่อยและการสืบทอด
สาหร่าย

6
ใช่คุณควรทำสำเนาการป้องกันถ้าคุณต้องการที่จะป้องกัน (ไม่ใช่การเสียดสี)
algal

1
ถ้าคุณอยากจะกลับ NSAttributedString แล้วบางทีนี้จะทำงาน:return NSAttributedString(attributedString: result)
อเล็กซ์

2
@ N13 ฉันจะสร้างโฟลเดอร์ที่เรียกว่าHelpersหรือและใส่ฟังก์ชั่นนี้ในแฟ้มที่มีชื่อว่าExtensions NSAttributedString+Concatenate.swift
David Lawson

34

Swift 3: เพียงแค่สร้าง NSMutableAttributedString และผนวกสตริงประกอบกับพวกเขา

let mutableAttributedString = NSMutableAttributedString()

let boldAttribute = [
    NSFontAttributeName: UIFont(name: "GothamPro-Medium", size: 13)!,
    NSForegroundColorAttributeName: Constants.defaultBlackColor
]

let regularAttribute = [
    NSFontAttributeName: UIFont(name: "Gotham Pro", size: 13)!,
    NSForegroundColorAttributeName: Constants.defaultBlackColor
]

let boldAttributedString = NSAttributedString(string: "Warning: ", attributes: boldAttribute)
let regularAttributedString = NSAttributedString(string: "All tasks within this project will be deleted.  If you're sure you want to delete all tasks and this project, type DELETE to confirm.", attributes: regularAttribute)
mutableAttributedString.append(boldAttributedString)
mutableAttributedString.append(regularAttributedString)

descriptionTextView.attributedText = mutableAttributedString

อัพเดต swift5:

    let captionAttribute = [
        NSAttributedString.Key.font: Font.captionsRegular,
        NSAttributedString.Key.foregroundColor: UIColor.appGray
    ]

25

ลองสิ่งนี้:

NSMutableAttributedString* result = [astring1 mutableCopy];
[result appendAttributedString:astring2];

อยู่ที่ไหนastring1และastring2มีNSAttributedStrings


13
[[aString1 mutableCopy] appendAttributedString: aString2]หรือ
JWWalker

@JWWalker 'oneliner' ของคุณเสียหาย คุณไม่สามารถรับผลลัพธ์ "การต่อข้อมูล" นี้ได้เนื่องจาก appendAttributedString จะไม่ส่งคืนสตริง เรื่องเดียวกันกับพจนานุกรม
gaussblurinc

@gaussblurinc: จุดดีแน่นอนการวิจารณ์ของคุณยังใช้กับคำตอบที่เราแสดงความคิดเห็น NSMutableAttributedString* aString3 = [aString1 mutableCopy]; [aString3 appendAttributedString: aString2];มันควรจะเป็น
JWWalker

@gaussblurinc, JWalker: แก้ไขคำตอบแล้ว
Linuxios

@Linuxios ยังคุณกลับเป็นresult NSMutableAttributedStringไม่ใช่สิ่งที่ผู้เขียนต้องการเห็น stringByAppendingString- วิธีนี้จะดี
gaussblurinc

5

2563 | SWIFT 5.1:

คุณสามารถเพิ่ม 2 NSMutableAttributedStringด้วยวิธีต่อไปนี้:

let concatenated = NSAttrStr1.append(NSAttrStr2)

วิธีอื่นทำงานร่วมกับNSMutableAttributedStringและNSAttributedStringทั้งสอง:

[NSAttrStr1, NSAttrStr2].joinWith(separator: "")

อีกวิธีคือ ....

var full = NSAttrStr1 + NSAttrStr2 + NSAttrStr3

และ:

var full = NSMutableAttributedString(string: "hello ")
// NSAttrStr1 == 1


full += NSAttrStr1 // full == "hello 1"       
full += " world"   // full == "hello 1 world"

คุณสามารถทำได้ด้วยส่วนขยายต่อไปนี้:

// works with NSAttributedString and NSMutableAttributedString!
public extension NSAttributedString {
    static func + (left: NSAttributedString, right: NSAttributedString) -> NSAttributedString {
        let leftCopy = NSMutableAttributedString(attributedString: left)
        leftCopy.append(right)
        return leftCopy
    }

    static func + (left: NSAttributedString, right: String) -> NSAttributedString {
        let leftCopy = NSMutableAttributedString(attributedString: left)
        let rightAttr = NSMutableAttributedString(string: right)
        leftCopy.append(rightAttr)
        return leftCopy
    }

    static func + (left: String, right: NSAttributedString) -> NSAttributedString {
        let leftAttr = NSMutableAttributedString(string: left)
        leftAttr.append(right)
        return leftAttr
    }
}

public extension NSMutableAttributedString {
    static func += (left: NSMutableAttributedString, right: String) -> NSMutableAttributedString {
        let rightAttr = NSMutableAttributedString(string: right)
        left.append(rightAttr)
        return left
    }

    static func += (left: NSMutableAttributedString, right: NSAttributedString) -> NSMutableAttributedString {
        left.append(right)
        return left
    }
}

2
ฉันกำลังใช้ Swift 5.1 และฉันไม่สามารถเพิ่ม NSAttrStrings สองตัวเข้าด้วยกันได้ ...
PaulDoesDev

1
แปลก. ในกรณีนี้ให้ใช้NSAttrStr1.append(NSAttrStr2)
Andrew

Updated คำตอบของฉันที่มีส่วนขยายเพียงเพิ่มสอง NSAttrStrings :)
แอนดรู

4

หากคุณใช้ Cocoapods ทางเลือกอื่นสำหรับทั้งสองคำตอบข้างต้นที่ให้คุณหลีกเลี่ยงความไม่แน่นอนในโค้ดของคุณคือการใช้NSAttributedString + CCLFormatหมวดหมู่ที่ยอดเยี่ยมNSAttributedStringซึ่งช่วยให้คุณเขียนสิ่งต่อไปนี้:

NSAttributedString *first = ...;
NSAttributedString *second = ...;
NSAttributedString *combined = [NSAttributedString attributedStringWithFormat:@"%@%@", first, second];

แน่นอนมันใช้NSMutableAttributedStringภายใต้ผ้าคลุม

นอกจากนี้ยังมีข้อได้เปรียบเพิ่มเติมจากการเป็นฟังก์ชั่นการจัดรูปแบบที่สมบูรณ์แบบดังนั้นจึงสามารถทำได้มากกว่าการต่อท้ายสตริงเข้าด้วยกัน


1
// Immutable approach
// class method

+ (NSAttributedString *)stringByAppendingString:(NSAttributedString *)append toString:(NSAttributedString *)string {
  NSMutableAttributedString *result = [string mutableCopy];
  [result appendAttributedString:append];
  NSAttributedString *copy = [result copy];
  return copy;
}

//Instance method
- (NSAttributedString *)stringByAppendingString:(NSAttributedString *)append {
  NSMutableAttributedString *result = [self mutableCopy];
  [result appendAttributedString:append];
  NSAttributedString *copy = [result copy];
  return copy;
}

1

คุณสามารถลองSwiftyFormat มันใช้ไวยากรณ์ต่อไปนี้

let format = "#{{user}} mentioned you in a comment. #{{comment}}"
let message = NSAttributedString(format: format,
                                 attributes: commonAttributes,
                                 mapping: ["user": attributedName, "comment": attributedComment])

1
คุณช่วยอธิบายเพิ่มเติมได้มั้ยมันจะทำงานอย่างไร
Kandhal Bhutiya
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.