Replacing a substring in an NSString

Discussion in 'Mac Programming' started by Starfox, Dec 9, 2012.

  1. macrumors regular

    Joined:
    Apr 7, 2011
    #1
    I've been trying to replace a substring of an NSString and it has been driving me crazy - the problem is the edge case where characters in the string take more than one UTF-16 codepoints, like Emoji. characterAtIndex: is kind of useless in this case and my best solution was going character by character getting the ranges for UTF-chars but my code seems to crash with out-of-range exceptions. Could anyone lend me a second pair of eyes? Code is at http://pastebin.com/kazBx6Qt
     
  2. macrumors 603

    Joined:
    Aug 9, 2009
    #2
    Post the stack-trace of the crash.

    Have you tried using the debugger? Set a breakpoint at the start of the function/method, then step through the code one line at a time.
     
  3. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    First, you can't modify an NSString. You can only modify an NSMutableString.
    Second, methods like "replaceOccurencesOfString" should help you. With Unicode, the higher level functions you use, the better.
     
  4. ytk
    macrumors regular

    Joined:
    Jul 8, 2010
    #4
    You're totally reinventing the wheel here.

    Just convert the string into an NSMutableString via [NSMutableString stringWithString:], then use NSMutableString's replaceCharactersInRange:withString: method.
     
  5. thread starter macrumors regular

    Joined:
    Apr 7, 2011
    #5
    You barely read anything I typed, didn't you now?..
     
  6. macrumors newbie

    Joined:
    Jul 7, 2009
    #6
    Looking at the code and given the out-of-range errors; you might want to have a look at the value of EndIndex. Unless it is meant to indicate the character after the last character of 'range' instead of the last character itself.

    As Chown33 suggested: walk through the code with the debugger and verify the values of the variables with what you expect them to be.
    NextIndex is one to watch as it is used to get a character from an index without verifying whether NextIndex is indeed a valid index. The values of all variables called range is another.
    It seems likely that one of those is the cause of the error.
     
  7. ytk
    macrumors regular

    Joined:
    Jul 8, 2010
    #7
    No need to be rude.

    I read exactly what you typed. You're fundamentally just trying to replace part of an NSString with another string. Regardless of what issue you're trying to work around, why are you reimplementing replaceCharactersInRange:withString: when that method already exists? Try writing a function (or subclass NSMutableString and write a method) to correctly determine the part of the string that needs to be replaced, then use the built-in method to do the actual replacement.

    If you do it that way, and the built-in method still doesn't work the way you need it to, then you can reimplement it as a separate function instead of chopping it up and blending it into one big function the way you have it now. You'll find doing so makes bugs much easier to track down.
     
  8. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    Please don't subclass NSString or NSMutableString. Just don't.
     
  9. ytk
    macrumors regular

    Joined:
    Jul 8, 2010
    #9
    Okay, so use a category to add a method to NSString. Or write a function I guess, but functions are so déclassé. Either way, what you don't want to do is roll the functionality to determine the replacement subset along with the kludgey reimplementation of an existing method to build a new string into a single function.
     
  10. Senor Cuete, Dec 13, 2012
    Last edited: Dec 13, 2012

    macrumors regular

    Joined:
    Nov 9, 2011
    #10
    auto?

    Looking at the index of my Objective-C Pocket Reference I can't find any listing for the keyword "auto".

    Since this builds I assume that the auto declaration is legitimate. What does auto mean? Did this appear in Objective-C 2 or otherwise become part of Objective-C after my book was printed?

    Woops, I see that this is written in C++. And yes you shouldn't subclass NSString and you can't edit an NSString. If you are learning to program OS X or iOS why not use Objective-C?
     
  11. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #11
    Before C++11, "auto" is a storage class like "extern", "static" and "register". It is the storage class for local variables in a function. So instead of having a variable "int x;" in a function you could write "auto int x;" and it means exactly the same thing.

    In C++11, they introduced a new meaning: If you have a declaration with an initializer, you don't have to write the type if you use auto. For example, "auto x = 3.0;" means that x is double, because 3.0 is double. Or "auto x = @"Hello"; " means x is an NSString* because @"Hello" is an NSString*.
     
  12. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #12
    As ytk said, it is hard to understand why Starfox is going to so much trouble to replicate a built-in function (NSString method). The method that creates a new string by replacing a substring is only available since 10.5, so I could possibly see the extreme need to insure compatibility with a six-year-old version of OS X, but even then, there are very simple ways to dice up and reassemble a string that do not involve stepping through a loop (at most, 5 or 6 lines of code, given range checking). NSString handles code points of various encodings quite well of its own accord, there is no practical need to muck around inside strings, just let the object do what it is good at.
     
  13. macrumors 6502a

    Joined:
    Oct 2, 2008
    #13
    Do you have an example where replaceOccurencesOfString:withString: does not work with a double-byte characters?

    Can you give an example input to your posted code that fails?
     
  14. thread starter macrumors regular

    Joined:
    Apr 7, 2011
    #14
    I managed to solve the issue by adding special code to cater for Emoji. The problem was that I'm trying to replace a range (not an occurence) and the way ranges were reported (from Twitter's API, if that matters) never properly accounted for Emoji. You can see the bug yourself if you use Twitter for Mac and post a tweet with Emoji (especially problematic: emoji flags, since they take four 16-bit "characters" to store in an NSString). Thanks for the help everyone.
     

Share This Page