

<https://stackoverflow.com/a/42166899/1979953>  
と  
<https://stackoverflow.com/a/38297423/1979953>

を参考に

[code]

    extension UILabel {
        func replaceAttributedText(string: String) {
            if let originalAttributedText = self.attributedText {
                let attributes = originalAttributedText.attributes(at: 0, effectiveRange: nil)
                self.attributedText = NSAttributedString(string: string, attributes: attributes)
            }
        }
    }
    
[/code]

を作ってみたのですが、`空文字`を与えた後で

`Terminating app due to uncaught exception 'NSRangeException', reason:
'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'`

になります。

つまり

[code]

    self.hogeLabel.replaceAttributedText(string: "hoge")
    self.hogeLabel.replaceAttributedText(string: "")
    self.hogeLabel.replaceAttributedText(string: "aaa") // 空文字を与えてしまった後なのでエラー
    
[/code]

このようなコードでエラーが発生します。

`空文字`を与えたことによってアトリビュート情報が吹っ飛んでしまったせいなのかと推測しているのですが、うまく文字列だけ入れ替える方法はないのでしょうか？

（`空文字`ではなくて、スペースなどの`空白文字`を入れるとうまくいくのですが、`空文字`を入れたいです）


CC BY-SA 4.0
2019-07-04T05:13:09.370
56370
2019-07-05T11:44:59.283
9008
question
swift ios
ストーリーボードで設定したアトリビュートを残してUILabelの文字列のみを変更したい


コメントしたように現在の`NSAttributeString`の実装では(空文字列を代入したい、と言う前提のもとで)掲載されたextensionは使えない、と言うことになります。

ここでは、「他の方法」のひとつとして、「ストーリーボードで設定したアトリビュートを残して文字列のみを変更」出来るようなカスタムLabelクラスをお示ししておきます。

[code]

    import UIKit
    
    class AttrLabel: UILabel {
        //ストーリーボードで設定されたアトリビュートを保存しておくインスタンスプロパティ
        var attributes: [NSAttributedString.Key: Any] = [:]
    
        override func awakeFromNib() {
            //Xib/Storyboardからインスタンス化された時に設定されたアトリビュートを保存しておく
            if let attrText = self.attributedText, attrText.length > 0 {
                attributes = attrText.attributes(at: 0, effectiveRange: nil)
            }
        }
    
        //`text`プロパティを操作すると、保存されたアトリビュートを使って、文字列だけを変更する
        override var text: String? {
            get {
                return super.text
            }
            set {
                self.attributedText = NSAttributedString(string: newValue ?? "",
                                                         attributes: self.attributes)
            }
        }
    }
    
[/code]

普通にストーリーボードに配置したLabelのCustom Classを上記の`AttrLabel`に付け替えればすぐに使えます。

少なくともこの程度の単純な例なら

[code]

            self.hogeLabel.text = "hoge"
            self.hogeLabel.text = ""
            self.hogeLabel.text = "aaa"
    
[/code]

元のアトリビュートを保存したまま、文字列だけ入れ替えられるのが確認できると思います。

* * *

本当にやりたいことは何なのか考えて、ひとつのやり方に縛られずに考えれば、もっと良い方法があるかもしれません。上の例も含めて、ぜひあれこれ試してみてください。


CC BY-SA 4.0
2019-07-05T11:44:59.283
56422
2019-07-05T11:44:59.283
13972
56370
answer