newProgrammer:please help with insertString!

Discussion in 'Mac Programming' started by Scouze, Aug 17, 2010.

  1. Scouze macrumors newbie

    Mar 3, 2010

    I'm sure it's something really simple but the following code in my project:

    NSMutableString *temp = [[NSMutableString alloc] initWithString:[firstNumber stringValue]];
    NSArray *splitInput = [[NSArray alloc]initWithArray:[temp componentsSeparatedByString:mad:"x"]];
    NSMutableString *f = ( NSMutableString * )[splitInput objectAtIndex:1];
    [f insertString: ( NSMutableString * ) @"00000000" atIndex:0];

    Where 'firstNumber' is the outlet from a standard text field in the main window.

    It produces the error:

    Attempt to mutate immutable object with insertString:atIndex:

    My code's a very early stage timecode calculator, so the user can enter '4x23' and the '23' needs to ultimately be padded with zeroes. I realise there's probably a better way by using 'NSNumberFormatter', but now I've a flea in my ear and I'd just like to know what I've done wrong.

    Many thanks!

  2. robbieduncan Moderator emeritus


    Jul 24, 2002
    NSStrings cannot be changed once created. You must use a NSMutableString (creating it if required).

    Edit: just seen you have attempted to use an NSMutableString but you have done it wrong. The split creates an array of NSString objects. You cannot cast them to NSMutableString: you are casting the wrong way. You can cast a subclass (NSMutableString) to a superclass (NSString) but not the other way. You need to create a new mutable object.
  3. Scouze thread starter macrumors newbie

    Mar 3, 2010
    Thanks, Robbie!

    I'll go back to reading about sub classes! I guess, though, that I need to create a temporary, mutable string and insert/replace it's contents with the user input held in the array and then do the 'padding'.


  4. jamawa macrumors newbie

    Jul 7, 2009
    Another option would be to use NSString's stringByAppendingString f.e. by replacing the last two lines of your code with:

    NSString *f = [[NSString stringWithString:mad:"00000000"] stringByAppendingString:[splitInput objectAtIndex:1]];

    and work from there.
    Just a thought.
  5. Scouze thread starter macrumors newbie

    Mar 3, 2010
    And a much better thought than mine. Thanks!

  6. chown33 macrumors 604

    Aug 9, 2009
    Sailing beyond the sunset
    The unwieldy and redundant [NSString stringWithString:mad:"00000000"] is redundant and unwieldy.

    Replace it with @"00000000" and it works as well.

    That's because @"anything" is an actual NSString object, and it responds to the same messages as any NSString does:
    NSString *f = [@"00000000" stringByAppendingString:[splitInput objectAtIndex:1]];

    This code is also redundant. First, temp doesn't need to be mutable. None of the operations or expressions it participates in have any need to modify it. In particular, splitting it does not require a mutable string.

    Therefore, this expression yields a suitable string:
    NSMutableString *temp =[firstNumber stringValue];
    Even without knowing what type firstNumber is.

    And this code is redundant for the same reason:
    NSArray *splitInput = [[NSArray alloc]initWithArray:[temp componentsSeparatedByString:@"x"]];
    It's unnecessary to alloc and init an entire new IMMUTABLE NSArray, when the one returned by componentsSeparatedByString meets every need. Furthermore, the alloc'ed array is leaking, because you own it but haven't released it. An array from componentsSeparatedByString is NOT owned, so WON'T leak when NOT released.

Share This Page