Search code examples
objective-cnsattributedstring

How to copy a NSMutableAttributedString


I'm wondering how I can make a copy of an NSMutableAttributedString. I have a property called text that I'd like to save its contents at a certain point and revert back to it in case something happens. I've tried making a property called textCopy where I can save it to with @property (nonatomic, copy) but I get a runtime error when I do this:

-[NSConcreteAttributedString insertAttributedString:atIndex:]: unrecognized selector sent to instance.

How would I accomplish this?

I'm getting this anytime I set the NSMutableAttributedString to @property (nonatomic, copy). I don't understanding why this wouldn't work. In general the copy parameter doesn't seem to work with NSMutableAttributedString whether I'm using its setter method or not.


Solution

  • The problem is that you've declared the property with the copy attribute, and are presumably using the compiler-generated setter. The compiler-generated setter sends the copy message to the object to make a copy. The copy message makes an immutable copy. That is, it creates an NSAttributedString, not an NSMutableAttributedString.

    One way to fix this is to write your own setter that uses mutableCopy, like this if you're using ARC:

    - (void)setTextCopy:(NSMutableAttributedString *)text {
        textCopy = [text mutableCopy];
    }
    

    or like this if you're using manual reference counting:

    - (void)setTextCopy:(NSMutableAttributedString *)text {
        // Careful copy/release dance in case text and textCopy
        // are the same object.
        id old = textCopy;
        textCopy = [text mutableCopy];
        [old release];
    }
    

    Another fix would be to make textCopy be an NSAttributedString instead of an NSMutableAttributedString, and make the rest of your code work with it as an immutable object.