Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Starfox

macrumors 6502
Original poster
Apr 7, 2011
256
9
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
 

chown33

Moderator
Staff member
Aug 9, 2009
10,706
8,346
A sea of green
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.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
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

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.
 

ytk

macrumors 6502
Jul 8, 2010
252
5
You're totally reinventing the wheel here.

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

Starfox

macrumors 6502
Original poster
Apr 7, 2011
256
9
You're totally reinventing the wheel here.

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

You barely read anything I typed, didn't you now?..
 

jamawa

macrumors newbie
Jul 7, 2009
10
0
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.
 

ytk

macrumors 6502
Jul 8, 2010
252
5
You barely read anything I typed, didn't you now?..

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.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
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.

Please don't subclass NSString or NSMutableString. Just don't.
 

ytk

macrumors 6502
Jul 8, 2010
252
5
Please don't subclass NSString or NSMutableString. Just don't.

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.
 

Senor Cuete

macrumors 6502
Nov 9, 2011
420
30
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?
 
Last edited:

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
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?

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*.
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
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.
 

hchung

macrumors 6502a
Oct 2, 2008
689
1
You barely read anything I typed, didn't you now?..

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?
 

Starfox

macrumors 6502
Original poster
Apr 7, 2011
256
9
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.