6

I'm sure mutable means it can be changed, so why's this happening?

attrString = [[NSMutableAttributedString alloc] initWithString:@"Tip 1: Aisle Management The most obvious step – although one that still has not been taken by a disconcerting number of organisations – is to configure cabinets in hot and cold aisles. If you haven’t got your racks into cold and hot aisle configurations, we can advise ways in which you can achieve improved airflow performance."];

        [attrString setFont:[UIFont systemFontOfSize:20] range:NSMakeRange(0, 23)];
        [attrString setFont:[UIFont systemFontOfSize:15] range:NSMakeRange(24, 325)];
        [attrString setTextColor:[UIColor blackColor] range:NSMakeRange(0,184)];
        [attrString setTextColor:[UIColor blueColor] range:NSMakeRange(185,325)];
        break;

Both my catextlayer and my nsmutableattributedsring are defined in my header file. I make the changes to my string above in a switch, then call this code to update the catextlayer the string is shown in:

//updates catext layer
TextLayer = [CATextLayer layer];

TextLayer.bounds = CGRectMake(0.0f, 0.0f, 245.0f, 290.0f);
TextLayer.string = attrString;
TextLayer.position = CGPointMake(162.0, 250.0f);
TextLayer.wrapped = YES;

[self.view.layer addSublayer:TextLayer];

It crashes on when it tries to set the font, but I cant work out why?

-[NSConcreteMutableAttributedString setFont:range:]: unrecognized selector sent to instance 0xd384420 * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableAttributedString setFont:range:]: unrecognized selector sent to instance 0xd384420'

Why is this happening?

dev6546
  • 1,412
  • 7
  • 21
  • 40
  • Here is some free code that demonstrates the use of attributed strings: github.com/artmayes167/Attribute – AMayes Apr 03 '13 at 16:15

2 Answers2

11

NSMutableAttributedString doesn't have a setFont:range: function.

Taken from here.... iphone/ipad: How exactly use NSAttributedString?

So I did a bit of reading from the docs.

The functions is...

[NSMutableAttirbutedString setAttributes:NSDictionary range:NSRange];

So you should be able to do something like this...

[string setAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"Helvetice-Neue"]} range:NSMakeRange(0, 2)];

or

[string setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:@"Helvetice-Neue"], NSFontAttributeName", nil] range:NSMakeRange(0, 2)];

if you're still using old ObjC syntax.

Hope that helps.

Community
  • 1
  • 1
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • I get an error on use of undeclared NSFontAttributeName? I haven't tried the colours yet. – dev6546 Sep 20 '12 at 17:38
  • edited after reading docs. https://developer.apple.com/library/mac//#/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/Reference/Reference.html – Fogmeister Sep 20 '12 at 17:44
  • I think those docs just work for os x 10+ that also causes a crash. – dev6546 Sep 20 '12 at 18:04
  • Yeah I put a string instead of the UIFont code. I've tested it on my iPhone and it works fine using this line... [string setAttributes:@{NSBackgroundColorAttributeName:[UIColor greenColor]} range:NSMakeRange(4, 6)]; If you are using it to populate a UILabel then you also need to set the label to accept attributed text not just plain text. (In UIBuilder it is a dropdown at the top of the inspector) – Fogmeister Sep 20 '12 at 18:07
  • What is the error you are getting. I have tested the code so I know it works. – Fogmeister Sep 20 '12 at 18:12
  • I'm setting it to CAlayer, could I set it to a uitextfield instead maybe? – dev6546 Sep 20 '12 at 18:25
  • If you need to to be 245x290 then I'd maybe try a UITextView (set not editable and userInteractionEnabledNo) or UILabel. Remember to set the AttributedText property on them though. You could also try a UITextField. – Fogmeister Sep 20 '12 at 18:33
  • Here is some free code that demonstrates the use of attributed strings: https://github.com/artmayes167/Attribute – AMayes Apr 03 '13 at 16:13
1

First of all,Is the attrString you said a property?If it's a property,you'd better check that have you declared the property with the copy attribute, and are you presumably using the compiler-generated setter? If YES 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 {
    [textCopy release];
    textCopy = [text mutableCopy];
}

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.

Reference: 1️⃣How to copy a NSMutableAttributedString 2️⃣NSConcreteAttributedString mutableString crash

Community
  • 1
  • 1
ChenYilong
  • 8,543
  • 9
  • 56
  • 84