views:

153

answers:

3

Hi, everyone,

I want to ask a question about the NSString * in objective C. Can I check the last char of a NSString * object?

Example:

NSString* data = @"abcde,";

if(data is end with ',') // I don't know this part
  // do sth

Thank you very much.

+8  A: 
NSString *data = @"abcd,";
if([data hasSuffix:@","]) // This returns true in this example
    // do something

Is that what you were looking for?

robinjam
robinjam, thank you for your reply. I try it, but it did not work. Is it another method?
Questions
It works for me... You must have a bug elsewhere.
robinjam
robinjam, thank you for your reply. And I try another NSString *, it works also. I guess it is some other problems of my program. Because the NSString * is passed from other object, can I display the last char of the NSString as I want to confirm that the last char. Thank you.
Questions
Try this: `NSString *lastCharacter = [myString substringFromIndex:[myString length] - 1]; NSLog(@"%@", lastCharacter);`
robinjam
+1  A: 

The NSString Programming Guide recommends:

If you simply want to determine whether a string contains a given pattern, you can use a predicate:

So, in your example:

NSString *data = @"abcde,";

// Create the predicate
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"SELF endswith %@", @","];

// Run the predicate
// match == YES if the predicate is successful
BOOL match = [myPredicate evaluateWithObject:data];

// Do what you want
if (match) {
    // do something
}

A bit long winded to write? Maybe, but if you do this in more than one place it can be easily refactored into a helper method.

Here's a link to the NSPredicate docs.

Edit

I've done some profiling and it is overkill in this simple case (see my comment below). I'll leave the answer up here anyway just as an example of using predicates for this sort of thing.

Abizern
Woah! Predicate evaluation just to check the suffix of a string? It's a bit overkill.
dreamlax
Why is it overkill? `-hasSuffix:` is just a convenience method for setting up a search on the NSString. Just because it's shorter to write does not make it more efficient. Also it's a recommendation from the docs (as I linked to) and it also gives the questioner another option for testing his code as the `-hasSuffix:` approach isn't working, and introduces a new approach to string searching that the questioner and others may not have previously considered.
Abizern
It is overkill because you have to create a predicate object, which has to parse the predicate format string, and also you have to evaluate the predicate object with the target object. `hasSuffix:` only has to ensure that the last characters of the receiver are equal to the argument. It wouldn't surprise me if the predicate `endswith` just used `hasSuffix:` internally. Also, the code provided for `hasSuffix:` in the other answer works. If it is not working for the OP then he has not given us enough information to correctly answer his question.
dreamlax
@dreamlax. You know; you're right. I did some profiling and the NSPredicate method is about 3 times slower than using `-hasSuffix`. 36ms compared to 14ms to scan 107,000 words (so it's still fast). I stand corrected!
Abizern
I would be curious to see how the new regex API performs in comparison. I bet it would be slower but who knows.
Marcus S. Zarra
+1  A: 

If you're worried about performance, and you want to check for one character, using -characterAtIndex: method may well be faster. -hasSuffix: takes a string, so potentially needs to do more work than just checking a single character (though the difference may be trivial).

You can also use categories to add a method to NSString like this:

@interface NSString(StringUtilities)
    - (BOOL) endsWithCharacter: (unichar) c;
@end

@implementation NSString(StringUtilities)

    - (BOOL) endsWithCharacter: (unichar) c
    {
        NSUInteger length = [self length];
        return (length > 0) && ([self characterAtIndex: length - 1] == c);
    }

@end

// test it...
NSString *data = @"abcd,";
if ([data endsWithCharacter: L','])
{

}

You should profile, of course, to be sure. Bear in mind though that by putting endsWithCharacter into a method we've added the message passing overhead to it, which will skew the profiling results unless you do the same when profiling the alternatives.

All of this is probably premature optimisation for most cases - but of course if you're doing this test thousands of times a second it may well matter (in that case you would probably want to use the code directly in the loop, as message passing inside a tight inner loop isn't a great plan).

Sam Deane
`-[NSString characterAtIndex:]` returns a `unichar`, not a `char`.
Jonathan Dann
Good point Jonathan - I've updated the example accordingly...
Sam Deane