176

characters - an instance property of String, is deprecated from with Xcode 9.1

It was very useful to get a substring from String by using the characters property but now it has been deprecated and Xcode suggests to use substring. I've tried to check around SO questions and apple developer tutorials/guidelines for the same. But could not see any solution/alternate as suggested.

Here is warning message:

'characters' is deprecated: Please use String or Substring

enter image description here

I've so many string operations are performed/handled using property characters.

Anyone have any idea/info about this update?

Mark Gerrior
  • 378
  • 2
  • 11
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • 5
    Here is an [interesting article](https://useyourloaf.com/blog/updating-strings-for-swift-4/) about the `String` changes from Swift 3 to 4 and please read also [SE0163](https://github.com/apple/swift-evolution/blob/master/proposals/0163-string-revision-1.md) – vadian Sep 28 '17 at 11:01
  • 5
    try to use [`count`](https://developer.apple.com/documentation/swift/string/2894926-count) instead. – holex Nov 03 '17 at 12:15
  • 1
    If you were using `string.characters.forEach` the new API is `string.forEach { char in process(char) }` – Efren Jun 21 '18 at 01:47

8 Answers8

276

Swift 4 introduced changes on string API.
You can just use !stringValue.isEmpty instead of stringValue.characters.count > 0

for more information you get the sample from here

for e.g

let edit = "Summary"
edit.count   // 7
andreskwan
  • 1,152
  • 1
  • 13
  • 13
songxunzhao
  • 3,149
  • 1
  • 11
  • 13
  • Thanks for your answer.. But can I have detail reference of sub string. This is just sample example, I've so many other operations dealing with characters – Krunal Sep 28 '17 at 10:55
  • 1
    Please check detail information from here. https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html – songxunzhao Sep 28 '17 at 10:59
  • let greeting = "Hello, world!" let index = greeting.index(of: ",") ?? greeting.endIndex let beginning = greeting[.. – songxunzhao Sep 28 '17 at 11:00
  • 1
    Online reference for [Substring](https://developer.apple.com/documentation/swift/substring). – Dennis Vennink Sep 28 '17 at 11:00
  • 32
    Never use count > 0 to check if a collection is empty. There is a property on Collection called isEmpty exactly for that. From the docs **When you need to check whether your collection is empty, use the isEmpty property instead of checking that the count property is equal to zero. For collections that don’t conform to RandomAccessCollection, accessing the count property iterates through the elements of the collection.** – Leo Dabus Sep 28 '17 at 11:04
  • `extension Collection {var isNotEmpty: Bool {get {return self.isEmpty ? false : true}}}` – Jonny Nov 01 '17 at 05:41
  • Is it backward compatible? I've few 3.0.2 version to support as well. – Bhanu Birani Nov 20 '17 at 04:31
  • @Jonny `extension Collection { var isNotEmpty: Bool { return !isEmpty } }` – Leo Dabus May 26 '18 at 23:10
88

Swift 4 vs Swift 3 examples:

let myString = "test"

for char in myString.characters {print(char) } // Swift 3
for char in myString { print(char) } // Swift 4

let length = myString.characters.count // Swift 3
let length = myString.count // Swift 4
Mohammad Sadegh Panadgoo
  • 3,929
  • 1
  • 10
  • 12
  • 2
    This should be the accepted answer. The question is about the replacement for string.characters.count, not the replacement for comparing to zero; that's only mentioned in the screenshot. – Timothy Kanski Feb 07 '19 at 01:28
9

One of the most common cases for manipulating strings is with JSON responses. In this example I created an extension in my watch app to drop the last (n) characters of a Bitcoin JSON object.

Swift 3:

func dropLast(_ n: Int = 0) -> String {
    return String(characters.dropLast(n))

Xcode 9.1 Error Message:

'characters' is deprecated: Please use String or Substring directly

Xcode is telling us to use the string variable or method directly.

Swift 4:

func dropLast(_ n: Int = 0) -> String {
    return String(dropLast(n))
    }

Complete Extension:

extension String {
    func dropLast(_ n: Int = 0) -> String {
        return String(dropLast(n))
    }

    var dropLast: String {
        return dropLast()
    }
}

Call:

print("rate:\(response.USDRate)")
let literalMarketPrice = response.USDRate.dropLast(2)
print("literal market price: \(literalMarketPrice)")

Console:

//rate:7,101.0888 //JSON float
//literal market price: 7,101.08 // JSON string literal

Additional Examples:

  • print("Spell has \(invisibleSpellName.count) characters.")
  • return String(dropLast(n))
  • return String(removeLast(n))

Documentation:

You'll often be using common methods such as dropLast() or removeLast() or count so here is the explicit Apple documentation for each method.

droplast()

removelast()

counting characters

tiw
  • 535
  • 1
  • 6
  • 22
Edison
  • 11,881
  • 5
  • 42
  • 50
3

Use this characters because String stopped being a collection in Swift 2.0. However this is still valid code in Swift 4 but is no longer necessary now that String is a Collection again.

For example a Swift 4 String now has a direct count property that gives the character count:

// Swift 4
let spString = "Stack"
spString.count           // 5

Examples for String and SubString.

String

Swift 4 String now directly get Element that gives the first character of String: (string.characters.first)

let spString = "Stack"
let firstElement = spString.first   //S

SubString

Using SubString get first character.

let spstring = "Welcome"
let indexStartOfText = spstring.index(spstring.startIndex, offsetBy: 1)
let sub = spstring.substring(to: indexStartOfText)
print(sub) //W
Pranavan SP
  • 1,785
  • 1
  • 17
  • 33
  • I want to get first character of string so I want to know that which way should I use let firstElement = spString.first or Substring? – Pulkit Aug 23 '18 at 07:12
  • 1
    @Pulkit Better to use `.first` because if string is `""` empty. it will only return nil but `substring` will produce error. – Pranavan SP Aug 23 '18 at 07:20
  • how to convert this line of code to swift 4 'AuthorImageText = String(val.characters[(AuthorName.startIndex)]).capitalized' – Pulkit Aug 23 '18 at 08:08
  • @Pulkit just remove `.characters` enough – Pranavan SP Aug 23 '18 at 08:44
2

That warning is just a top of the iceberg, there were a loot of string changes, strings are again a collection of characters, but we got soemthing new and cool, subStrings :)

This is a great read about this: https://useyourloaf.com/blog/updating-strings-for-swift-4/

Boris
  • 178
  • 1
  • 7
2

Just remove characters For example:

stringValue.characters.count to stringValue.count

1

You can also use this code for dictionary grouping without using { $0.characters.first! }.

let cities = ["Shanghai": 24_256_800, "Karachi": 23_500_000, "Beijing": 21_516_000, "Seoul": 9_995_000]
let groupedCities = Dictionary(grouping: cities.keys) { $0.first! }
print(groupedCities)
1
func validatePhoneNumber(number:String) -> Bool{
    if number.count < 10. //deprecated ->(number.characters.count)
    {
        return false;
    }else{
        return true;
    }
}

You use directly .count and characters is deprecated.