1

I am starting to learn Swift and hope to find it an excellent replacement for Objective C.

I am attempting to convert my Objective C classes into Swift and I cannot find the best way to translate the following method into Swift.

@implementation VersionReader

- (NSString *)readVersionFromString:(NSString *)string {
    if (string.length == 0) {
        return nil;
    }

    unichar firstChar = [string characterAtIndex:0];
    if (firstChar < '0' || firstChar > '9') {
        return nil;
    }

    NSUInteger length = string.length;
    for (NSUInteger i = 0; i < length; ++i) {
        if ([string characterAtIndex:i] == ' ') {
            return [string substringToIndex:i];
        }
    }

    return string;
}
@end

So far my Swift code looks like this:

import Cocoa

class VersionReader {
    func readVersionFromString(string: String) -> String? {
        if (string.isEmpty) {
            return nil
        }

        var firstChar = string.characterAtIndex[0]
        if (firstChar < 48 || firstChar > 57) {
            return nil
        }

        var length = string.utf16Count
        for (var i = 0; i < length; ++i) {
            if (string.characterAtIndex(i) == 32) {
                return string.substringToIndex(i)
            }
        }

        return string
    }
}

Tom this, I get the same error on two lines:

'String' does not have a member named 'characterAtIndex'

What would be an alternative to make this work in Swift? Thanks in advance.

gepree
  • 617
  • 7
  • 9
  • http://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language – trojanfoe Jul 24 '14 at 13:10
  • IMO there is a reason that Apple did not provide characterAtIndex in Swift. The main problem is that what a character is is not an easy question to answer. For starters, there are surrogate pairs and plane 1 characters that are two UTF-16 code points. Emoji characters are in plane 1. Note also that there is no String.length method for much the same reason. – zaph Jul 24 '14 at 13:44
  • 'characterAtIndex` and `length` have the same problems in `NSString` and it seems that Apple has decided that the solution is not to provide methods that do not work as expected. 'length' was replaced by `utf16count` and `countElements` the later is a method that iterates over the String counting the characters with O(N) time. – zaph Jul 24 '14 at 13:57
  • What Input string are you expecting and what output do you want to generate? I'm inclined to believe the whole approach could be improved. – Mario Jul 24 '14 at 16:32

3 Answers3

1

A possible Swift solution:

func readVersionFromString(string: String) -> String? {
    if string.isEmpty {
        return nil
    }

    let firstChar = string[string.startIndex]
    if !find("0123456789", firstChar) {
        return nil
    } else if let pos = find(string, " ") {
        return string.substringToIndex(pos)
    } else {
        return string
    }
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Swift's String type doesn't have a characterAtIndex method. You can cast it to an NSString and use it as below:

var firstChar = (string as NSString).characterAtIndex(0)

Or

var firstChar = string.bridgeToObjectiveC().characterAtIndex(0)

Note that the characterAtIndex method returns an unichar, which seems to be what you want. But the correct approach to get a Swift Character would be that suggested by FreeAsInBeer in his answer: Array(string)[0]

Community
  • 1
  • 1
Cezar
  • 55,636
  • 19
  • 86
  • 87
  • @NateCook Yep. You're right. And I never said it was. I don't intend to provide a comprehensive treatment of Strings in Swift in this answer. Also, the scope of the question is pretty limited and I don't think encoding is much of a concern. The OP can correct me if that's not the case. – Cezar Jul 24 '14 at 13:46
-1

Swift doesn't have a characterAtIndex selector. Instead, you need to use Array(string)[0].

FreeAsInBeer
  • 12,937
  • 5
  • 50
  • 82
  • (Did not vote, but) note that `Array(string)[0]` returns a `Character`, and that is not comparable with 48 or with other characters. – Martin R Jul 24 '14 at 13:28
  • Does the answer handle non ASCII characters? Is this really a good idea? Will it continue to work? Does an Array really have the same properties as a String? Does it handle surrogate pairs? Plane 1 unicode characters (emoji)? (not down voter but I agree with the down voter) – zaph Jul 24 '14 at 13:41