How do I check if a string contains another string in Swift? - swift

In Objective-C the code to check for a substring in an NSString is:
NSString *string = #"hello Swift";
NSRange textRange =[string rangeOfString:#"Swift"];
if(textRange.location != NSNotFound)
{
NSLog(#"exists");
}
But how do I do this in Swift?

You can do exactly the same call with Swift:
Swift 4 & Swift 5
In Swift 4 String is a collection of Character values, it wasn't like this in Swift 2 and 3, so you can use this more concise code1:
let string = "hello Swift"
if string.contains("Swift") {
print("exists")
}
Swift 3.0+
var string = "hello Swift"
if string.range(of:"Swift") != nil {
print("exists")
}
// alternative: not case sensitive
if string.lowercased().range(of:"swift") != nil {
print("exists")
}
Older Swift
var string = "hello Swift"
if string.rangeOfString("Swift") != nil{
println("exists")
}
// alternative: not case sensitive
if string.lowercaseString.rangeOfString("swift") != nil {
println("exists")
}
I hope this is a helpful solution since some people, including me, encountered some strange problems by calling containsString().1
PS. Don't forget to import Foundation
Footnotes
Just remember that using collection functions on Strings has some edge cases which can give you unexpected results, e. g. when dealing with emojis or other grapheme clusters like accented letters.

Extension way
Swift 4
extension String {
func contains(find: String) -> Bool{
return self.range(of: find) != nil
}
func containsIgnoringCase(find: String) -> Bool{
return self.range(of: find, options: .caseInsensitive) != nil
}
}
var value = "Hello world"
print(value.contains("Hello")) // true
print(value.contains("bo")) // false
print(value.containsIgnoringCase(find: "hello")) // true
print(value.containsIgnoringCase(find: "Hello")) // true
print(value.containsIgnoringCase(find: "bo")) // false
Generally Swift 4 has contains method however it available from iOS 8.0+
Swift 3.1
You can write extension contains: and containsIgnoringCase for String
extension String {
func contains(_ find: String) -> Bool{
return self.range(of: find) != nil
}
func containsIgnoringCase(_ find: String) -> Bool{
return self.range(of: find, options: .caseInsensitive) != nil
}
}
Older Swift version
extension String {
func contains(find: String) -> Bool{
return self.rangeOfString(find) != nil
}
func containsIgnoringCase(find: String) -> Bool{
return self.rangeOfString(find, options: NSStringCompareOptions.CaseInsensitiveSearch) != nil
}
}
Example:
var value = "Hello world"
print(value.contains("Hello")) // true
print(value.contains("bo")) // false
print(value.containsIgnoringCase("hello")) // true
print(value.containsIgnoringCase("Hello")) // true
print(value.containsIgnoringCase("bo")) // false

From the docs, it seems that calling containsString() on a String should work:
Swift’s String type is bridged seamlessly to Foundation’s NSString
class. If you are working with the Foundation framework in Cocoa or
Cocoa Touch, the entire NSString API is available to call on any
String value you create, in addition to the String features described
in this chapter. You can also use a String value with any API that
requires an NSString instance.
However, it doesn't seem to work that way.
If you try to use someString.containsString(anotherString), you will get a compile time error that states 'String' does not contain a member named 'containsString'.
So, you're left with a few options, one of which is to explicitly bridge your String to Objective-C by using bridgeToObjectiveC() other two involve explicitly using an NSString and the final one involves casting the String to an NSString
By bridging, you'd get:
var string = "hello Swift"
if string.bridgeToObjectiveC().containsString("Swift") {
println("YES")
}
By explicitly typing the string as an NSString, you'd get:
var string: NSString = "hello Swift"
if string.containsString("Swift") {
println("YES")
}
If you have an existing String, you can initialize an NSString from it by using NSString(string:):
var string = "hello Swift"
if NSString(string: string).containsString("Swift") {
println("YES")
}
And finally, you can cast an existing String to an NSString as below
var string = "hello Swift"
if (string as NSString).containsString("Swift") {
println("YES")
}

Another one. Supports case and diacritic options.
Swift 3.0
struct MyString {
static func contains(_ text: String, substring: String,
ignoreCase: Bool = true,
ignoreDiacritic: Bool = true) -> Bool {
var options = NSString.CompareOptions()
if ignoreCase { _ = options.insert(NSString.CompareOptions.caseInsensitive) }
if ignoreDiacritic { _ = options.insert(NSString.CompareOptions.diacriticInsensitive) }
return text.range(of: substring, options: options) != nil
}
}
Usage
MyString.contains("Niels Bohr", substring: "Bohr") // true
iOS 9+
Case and diacritic insensitive function available since iOS 9.
if #available(iOS 9.0, *) {
"Für Elise".localizedStandardContains("fur") // true
}

As of Xcode 7.1 and Swift 2.1 containsString() is working fine for me.
let string = "hello swift"
if string.containsString("swift") {
print("found swift")
}
Swift 4:
let string = "hello swift"
if string.contains("swift") {
print("found swift")
}
And a case insensitive Swift 4 example:
let string = "Hello Swift"
if string.lowercased().contains("swift") {
print("found swift")
}
Or using a case insensitive String extension:
extension String {
func containsIgnoreCase(_ string: String) -> Bool {
return self.lowercased().contains(string.lowercased())
}
}
let string = "Hello Swift"
let stringToFind = "SWIFT"
if string.containsIgnoreCase(stringToFind) {
print("found: \(stringToFind)") // found: SWIFT
}
print("string: \(string)")
print("stringToFind: \(stringToFind)")
// console output:
found: SWIFT
string: Hello Swift
stringToFind: SWIFT

In Swift 4.2
Use
func contains(_ str: String) -> Bool
Example
let string = "hello Swift"
let containsSwift = string.contains("Swift")
print(containsSwift) // prints true

> IN SWIFT 3.0
let str = "Hello Swift"
if str.lowercased().contains("Swift".lowercased()) {
print("String Contains Another String")
} else {
print("Not Exists")
}
Output
String Contains Another String

You can do this very easily in Swift using the code:
let string = "hello Swift";
let subString = (string as NSString).containsString("Swift")
if(subString){println("Exist")}

Of all of the answers here, I think they either don't work, or they're a bit of a hack (casting back to NSString). It's very likely that the correct answer to this has changed with the different beta releases.
Here is what I use:
let string: String = "hello Swift"
if string.rangeOfString("Swift") != nil
{
println("exists")
}
The "!= nil" became required with Beta 5.

Just an addendum to the answers here.
You can also do a local case insensitive test using:
- (BOOL)localizedCaseInsensitiveContainsString:(NSString *)aString
Example:
import Foundation
var string: NSString = "hello Swift"
if string.localizedCaseInsensitiveContainsString("Hello") {
println("TRUE")
}
UPDATE
This is part of the Foundation Framework for iOS & Mac OS X 10.10.x
and was part of 10.10 at Time of my original Posting.
Document Generated: 2014-06-05 12:26:27 -0700 OS X Release Notes
Copyright © 2014 Apple Inc. All Rights Reserved.
OS X 10.10 Release Notes Cocoa Foundation Framework
NSString now has the following two convenience methods:
- (BOOL)containsString:(NSString *)str;
- (BOOL)localizedCaseInsensitiveContainsString:(NSString *)str;

Here is my first stab at this in the swift playground.
I extend String by providing two new functions (contains and containsIgnoreCase)
extension String {
func contains(other: String) -> Bool{
var start = startIndex
do{
var subString = self[Range(start: start++, end: endIndex)]
if subString.hasPrefix(other){
return true
}
}while start != endIndex
return false
}
func containsIgnoreCase(other: String) -> Bool{
var start = startIndex
do{
var subString = self[Range(start: start++, end: endIndex)].lowercaseString
if subString.hasPrefix(other.lowercaseString){
return true
}
}while start != endIndex
return false
}
}
Use it like this
var sentence = "This is a test sentence"
sentence.contains("this") //returns false
sentence.contains("This") //returns true
sentence.containsIgnoreCase("this") //returns true
"This is another test sentence".contains(" test ") //returns true
I'd welcome any feedback :)

Here you are:
let s = "hello Swift"
if let textRange = s.rangeOfString("Swift") {
NSLog("exists")
}

You can just do what you have mentioned:
import Foundation
...
string.contains("Swift");
From the docs:
Swift’s String type is bridged seamlessly to Foundation’s NSString
class. If you are working with the Foundation framework in Cocoa or
Cocoa Touch, the entire NSString API is available to call on any
String value you create, in addition to the String features described
in this chapter. You can also use a String value with any API that
requires an NSString instance.
You need to import Foundation to bridge the NSString methods and make them available to Swift's String class.

You don't need to write any custom code for this. Starting from the 1.2 version Swift has already had all the methods you need:
getting string length: count(string);
checking if string contains substring: contains(string, substring);
checking if string starts with substring: startsWith(string, substring)
and etc.

In Swift 3
if((a.range(of: b!, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)) != nil){
print("Done")
}

Here you go! Ready for Xcode 8 and Swift 3.
import UIKit
let mString = "This is a String that contains something to search."
let stringToSearchUpperCase = "String"
let stringToSearchLowerCase = "string"
mString.contains(stringToSearchUpperCase) //true
mString.contains(stringToSearchLowerCase) //false
mString.lowercased().contains(stringToSearchUpperCase) //false
mString.lowercased().contains(stringToSearchLowerCase) //true

string.containsString is only available in 10.10 Yosemite (and probably iOS8).
Also bridging it to ObjectiveC crashes in 10.9. You're trying to pass a NSString to NSCFString. I don't know the difference, but I can say 10.9 barfs when it executes this code in a OS X 10.9 app.
Here are the differences in Swift with 10.9 and 10.10:
https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/index.html containsString is only available in 10.10
Range of String above works great on 10.9. I am finding developing on 10.9 is super stable with Xcode beta2. I don't use playgrounds through or the command line version of playgrounds. I'm finding if the proper frameworks are imported the autocomplete is very helpful.

Xcode 8/Swift 3 version:
let string = "hello Swift"
if let range = string.range(of: "Swift") {
print("exists at range \(range)")
} else {
print("does not exist")
}
if let lowercaseRange = string.lowercased().range(of: "swift") {
print("exists at range \(lowercaseRange)")
} else {
print("does not exist")
}
You can also use contains:
string.contains("swift") // false
string.contains("Swift") // true

Swift 4 way to check for substrings, including the necessary Foundation (or UIKit) framework import:
import Foundation // or UIKit
let str = "Oh Canada!"
str.contains("Can") // returns true
str.contains("can") // returns false
str.lowercased().contains("can") // case-insensitive, returns true
Unless Foundation (or UIKit) framework is imported, str.contains("Can") will give a compiler error.
This answer is regurgitating manojlds's answer, which is completely correct. I have no idea why so many answers go through so much trouble to recreate Foundation's String.contains(subString: String) method.

With and new syntax in swift 4 you can just
string.contains("Swift 4 is the best")
string is your string variable

Check if it contains 'Hello'
let s = "Hello World"
if s.rangeOfString("Hello") != nil {
print("Yes it contains 'Hello'")
}

Swift 5, case insensitive:
if string.localizedLowercase.contains("swift".localizedLowercase){

// Search string exist in employee name finding.
var empName:NSString! = employeeDetails[filterKeyString] as NSString
Case sensitve search.
let rangeOfSearchString:NSRange! = empName.rangeOfString(searchString, options: NSStringCompareOptions.CaseInsensitiveSearch)
// Not found.
if rangeOfSearchString.location != Foundation.NSNotFound
{
// search string not found in employee name.
}
// Found
else
{
// search string found in employee name.
}

Swift 3: Here you can see my smart search extension fro string that let you make a search on string for seeing if it contains, or maybe to filter a collection based on a search text.
https://github.com/magonicolas/Swift-Smart-String-Search

If you want to check that one String contains another Sub-String within it or not you can check it like this too,
var name = String()
name = "John has two apples."
Now, in this particular string if you want to know if it contains fruit name 'apple' or not you can do,
if name.contains("apple") {
print("Yes , it contains fruit name")
} else {
print("it does not contain any fruit name")
}
Hope this works for you.

In iOS 8 and newer, you can use these two NSString methods:
#availability(iOS, introduced=8.0)
func containsString(aString: String) -> Bool
#availability(iOS, introduced=8.0)
func localizedCaseInsensitiveContainsString(aString: String) -> Bool

I've found a couple of interesting use cases. These variants make use of the rangeOfString method and I include the equality example to show how one might best use the search and comparison features of Strings in Swift 2.0
//In viewDidLoad() I assign the current object description (A Swift String) to self.loadedObjectDescription
self.loadedObjectDescription = self.myObject!.description
Later after I've made changes to self.myObject, I can refer to the
following string comparison routines (setup as lazy variables that
return a Bool). This allows one to check the state at any time.
lazy var objectHasChanges : Bool = {
guard self.myObject != nil else { return false }
return !(self.loadedObjectDescription == self.myObject!.description)
}()
A variant of this happens when sometimes I need to analyze a missing
property on that object. A string search allows me to find a
particular substring being set to nil (the default when an object is created).
lazy var isMissingProperty : Bool = {
guard self.myObject != nil else { return true }
let emptyPropertyValue = "myProperty = nil"
return (self.myObject!.description.rangeOfString(emptyPropertyValue) != nil) ? true : false
}()

SWIFT 4 is very easy!!
if (yourString.contains("anyThing")) {
print("Exist")
}

Related

How to find if a string contains all the characters of a string for live searching in Swift?

I'm trying to implement search inside my app that I'm making. I have an array that I'm trying to search and I find this code online:
func filterContentForSearchText(searchText: String) {
filteredCandies = candies.filter({( candy : Candies) -> Bool in
if candy.name.lowercaseString.containsString(searchText.lowercaseString) == true {
return true
} else {
return false
}
})
tableView.reloadData()
}
The issue is that the database that I'm trying to implement search on has text that is all scrambled because it was supposed to shortened. How can I make it so that the search will check if all the letters are there instead of searching exactly the right name. Example of object from database (USDA): CRAB, DUNGINESS, RAW
If you have an answer, please make it fast enough for live searching. Non live searching makes searching terrible (at least for me)!
I'm using Swift 2.2 and Xcode 7
As an improvement to #appzYourLife's solution, you could do this with a native Swift Set, as a counted set isn't necessarily needed in this case. This will save having to map(_:) over the characters of each name and bridging them to Objective-C. You can now just use a set of Characters, as they're Hashable.
For example:
struct Candy {
let name: String
}
let candies = [Candy(name: "CRAB"), Candy(name: "DUNGINESS"), Candy(name: "RAW")]
var filteredCandies = [Candy]()
func filterContentForSearchText(searchText: String) {
let searchCharacters = Set(searchText.lowercaseString.characters)
filteredCandies = candies.filter {Set($0.name.lowercaseString.characters).isSupersetOf(searchCharacters)}
tableView.reloadData()
}
filterContentForSearchText("RA")
print(filteredCandies) // [Candy(name: "CRAB"), Candy(name: "RAW")]
filterContentForSearchText("ED")
print(filteredCandies) // Candy(name: "DUNGINESS")]
Also depending on whether you can identify this as a performance bottleneck (you should do some profiling first) – you could potentially optimise the above further by caching the sets containing the characters of your 'candy' names, saving from having to recreate them at each search (although you'll have to ensure that they're updated if you update your candies data).
When you come to search, you can then use zip(_:_:) and flatMap(_:) in order to filter out the corresponding candies.
let candies = [Candy(name: "CRAB"), Candy(name: "DUNGINESS"), Candy(name: "RAW")]
// cached sets of (lowercased) candy name characters
let candyNameCharacterSets = candies.map {Set($0.name.lowercaseString.characters)}
var filteredCandies = [Candy]()
func filterContentForSearchText(searchText: String) {
let searchCharacters = Set(searchText.lowercaseString.characters)
filteredCandies = zip(candyNameCharacterSets, candies).flatMap {$0.isSupersetOf(searchCharacters) ? $1 : nil}
tableView.reloadData()
}
First of all a block of code like this
if someCondition == true {
return true
} else {
return false
}
can also be written this ways
return someCondition
right? :)
Refactoring
So your original code would look like this
func filterContentForSearchText(searchText: String) {
filteredCandies = candies.filter { $0.name.lowercaseString.containsString(searchText.lowercaseString) }
tableView.reloadData()
}
Scrambled search
Now, given a string A, your want to know if another string B contains all the character of A right?
For this we need CountedSet which is available from Swift 3. Since you are using Swift 2.2 we'll use the old NSCountedSet but some bridging to Objective-C is needed.
Here's the code.
struct Candy {
let name: String
}
let candies = [Candy]()
var filteredCandies = [Candy]()
func filterContentForSearchText(searchText: String) {
let keywordChars = NSCountedSet(array:Array(searchText.lowercaseString.characters).map { String($0) })
filteredCandies = candies.filter {
let candyChars = NSCountedSet(array:Array($0.name.lowercaseString.characters).map { String($0) }) as Set<NSObject>
return keywordChars.isSubsetOfSet(candyChars)
}
tableView.reloadData()
}
Swift 3 code update :
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredCandies = candies.filter { candy in
return candy.name.localizedLowercase.contains(searchText.lowercased())
}
tableView.reloadData()
}

Remove all non-numeric characters from a string in swift

I have the need to parse some unknown data which should just be a numeric value, but may contain whitespace or other non-alphanumeric characters.
Is there a new way of doing this in Swift? All I can find online seems to be the old C way of doing things.
I am looking at stringByTrimmingCharactersInSet - as I am sure my inputs will only have whitespace/special characters at the start or end of the string. Are there any built in character sets I can use for this? Or do I need to create my own?
I was hoping there would be something like stringFromCharactersInSet() which would allow me to specify only valid characters to keep
I was hoping there would be something like stringFromCharactersInSet() which would allow me to specify only valid characters to keep.
You can either use trimmingCharacters with the inverted character set to remove characters from the start or the end of the string. In Swift 3 and later:
let result = string.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
Or, if you want to remove non-numeric characters anywhere in the string (not just the start or end), you can filter the characters, e.g. in Swift 4.2.1:
let result = string.filter("0123456789.".contains)
Or, if you want to remove characters from a CharacterSet from anywhere in the string, use:
let result = String(string.unicodeScalars.filter(CharacterSet.whitespaces.inverted.contains))
Or, if you want to only match valid strings of a certain format (e.g. ####.##), you could use regular expression. For example:
if let range = string.range(of: #"\d+(\.\d*)?"#, options: .regularExpression) {
let result = string[range] // or `String(string[range])` if you need `String`
}
The behavior of these different approaches differ slightly so it just depends on precisely what you're trying to do. Include or exclude the decimal point if you want decimal numbers, or just integers. There are lots of ways to accomplish this.
For older, Swift 2 syntax, see previous revision of this answer.
let result = string.stringByReplacingOccurrencesOfString("[^0-9]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
Swift 3
let result = string.replacingOccurrences( of:"[^0-9]", with: "", options: .regularExpression)
You can upvote this answer.
I prefer this solution, because I like extensions, and it seems a bit cleaner to me. Solution reproduced here:
extension String {
var digits: String {
return components(separatedBy: CharacterSet.decimalDigits.inverted)
.joined()
}
}
You can filter the UnicodeScalarView of the string using the pattern matching operator for ranges, pass a UnicodeScalar ClosedRange from 0 to 9 and initialise a new String with the resulting UnicodeScalarView:
extension String {
private static var digits = UnicodeScalar("0")..."9"
var digits: String {
return String(unicodeScalars.filter(String.digits.contains))
}
}
"abc12345".digits // "12345"
edit/update:
Swift 4.2
extension RangeReplaceableCollection where Self: StringProtocol {
var digits: Self {
return filter(("0"..."9").contains)
}
}
or as a mutating method
extension RangeReplaceableCollection where Self: StringProtocol {
mutating func removeAllNonNumeric() {
removeAll { !("0"..."9" ~= $0) }
}
}
Swift 5.2 • Xcode 11.4 or later
In Swift5 we can use a new Character property called isWholeNumber:
extension RangeReplaceableCollection where Self: StringProtocol {
var digits: Self { filter(\.isWholeNumber) }
}
extension RangeReplaceableCollection where Self: StringProtocol {
mutating func removeAllNonNumeric() {
removeAll { !$0.isWholeNumber }
}
}
To allow a period as well we can extend Character and create a computed property:
extension Character {
var isDecimalOrPeriod: Bool { "0"..."9" ~= self || self == "." }
}
extension RangeReplaceableCollection where Self: StringProtocol {
var digitsAndPeriods: Self { filter(\.isDecimalOrPeriod) }
}
Playground testing:
"abc12345".digits // "12345"
var str = "123abc0"
str.removeAllNonNumeric()
print(str) //"1230"
"Testing0123456789.".digitsAndPeriods // "0123456789."
Swift 4
I found a decent way to get only alpha numeric characters set from a string.
For instance:-
func getAlphaNumericValue() {
var yourString = "123456789!##$%^&*()AnyThingYouWant"
let unsafeChars = CharacterSet.alphanumerics.inverted // Remove the .inverted to get the opposite result.
let cleanChars = yourString.components(separatedBy: unsafeChars).joined(separator: "")
print(cleanChars) // 123456789AnyThingYouWant
}
A solution using the filter function and rangeOfCharacterFromSet
let string = "sld [f]34é7*˜µ"
let alphaNumericCharacterSet = NSCharacterSet.alphanumericCharacterSet()
let filteredCharacters = string.characters.filter {
return String($0).rangeOfCharacterFromSet(alphaNumericCharacterSet) != nil
}
let filteredString = String(filteredCharacters) // -> sldf34é7µ
To filter for only numeric characters use
let string = "sld [f]34é7*˜µ"
let numericSet = "0123456789"
let filteredCharacters = string.characters.filter {
return numericSet.containsString(String($0))
}
let filteredString = String(filteredCharacters) // -> 347
or
let numericSet : [Character] = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let filteredCharacters = string.characters.filter {
return numericSet.contains($0)
}
let filteredString = String(filteredCharacters) // -> 347
Swift 4
But without extensions or componentsSeparatedByCharactersInSet which doesn't read as well.
let allowedCharSet = NSCharacterSet.letters.union(.whitespaces)
let filteredText = String(sourceText.unicodeScalars.filter(allowedCharSet.contains))
let string = "+1*(234) fds567#-8/90-"
let onlyNumbers = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
print(onlyNumbers) // "1234567890"
or
extension String {
func removeNonNumeric() -> String {
return self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
}
}
let onlyNumbers = "+1*(234) fds567#-8/90-".removeNonNumeric()
print(onlyNumbers)// "1234567890"
Swift 3, filters all except numbers
let myString = "dasdf3453453fsdf23455sf.2234"
let result = String(myString.characters.filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
print(result)
Swift 4.2
let numericString = string.filter { (char) -> Bool in
return char.isNumber
}
You can do something like this...
let string = "[,myString1. \"" // string : [,myString1. "
let characterSet = NSCharacterSet(charactersInString: "[,. \"")
let finalString = (string.componentsSeparatedByCharactersInSet(characterSet) as NSArray).componentsJoinedByString("")
print(finalString)
//finalString will be "myString1"
The issue with Rob's first solution is stringByTrimmingCharactersInSet only filters the ends of the string rather than throughout, as stated in Apple's documentation:
Returns a new string made by removing from both ends of the receiver characters contained in a given character set.
Instead use componentsSeparatedByCharactersInSet to first isolate all non-occurrences of the character set into arrays and subsequently join them with an empty string separator:
"$$1234%^56()78*9££".componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "0123456789").invertedSet)).joinWithSeparator("")
Which returns 123456789
Swift 3
extension String {
var keepNumericsOnly: String {
return self.components(separatedBy: CharacterSet(charactersIn: "0123456789").inverted).joined(separator: "")
}
}
Swift 4.0 version
extension String {
var numbers: String {
return String(describing: filter { String($0).rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789")) != nil })
}
}
Swift 4
String.swift
import Foundation
extension String {
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
return String(String.UnicodeScalarView(passed))
}
func removeCharacters(from: String) -> String {
return removeCharacters(from: CharacterSet(charactersIn: from))
}
}
ViewController.swift
let character = "1Vi234s56a78l9"
let alphaNumericSet = character.removeCharacters(from: CharacterSet.decimalDigits.inverted)
print(alphaNumericSet) // will print: 123456789
let alphaNumericCharacterSet = character.removeCharacters(from: "0123456789")
print("no digits",alphaNumericCharacterSet) // will print: Vishal
Swift 4.2
let digitChars = yourString.components(separatedBy:
CharacterSet.decimalDigits.inverted).joined(separator: "")
Swift 3 Version
extension String
{
func trimmingCharactersNot(in charSet: CharacterSet) -> String
{
var s:String = ""
for unicodeScalar in self.unicodeScalars
{
if charSet.contains(unicodeScalar)
{
s.append(String(unicodeScalar))
}
}
return s
}
}

Syntax changes from Swift to Swift 2, cannot invoke enumerate with a string and extra NSErrorPointer argument

I am working on Swift 1.2 with Xcode 6 but now I've installed Xcode 7 with Swift 2.1. There are many errors in Swift 2.1 and many syntax changes, even though my code works well with Swift 1.2. The first problem is with this method:
func getSubstringUpToIndex(index: Int, fromString str: String) -> String
{
var substring = ""
for (i, letter) in enumerate(str) {
substring.append(letter)
if i == index - 1 {
break
}
}
return substring
}
Another problem occurs on this line, "extra argument 'error' in call":
let jsonResult: Dictionary = NSJSONSerialization.JSONObjectWithData(self.mutableData, options: NSJSONReadingOptions.MutableContainers, error: &error) as! Dictionary<String, AnyObject>
In both cases it's Swift 1.2 code, not 2.0.
In the first snippet of code, the enumerate method does not exist anymore, you can update it this way:
func getSubstringUpToIndex(index: Int,
fromString str: String) -> String
{
var substring = ""
for (i, letter) in str.characters.enumerate() {
substring.append(letter)
if i == index - 1 {
break
}
}
return substring
}
Or this way, using substringRithRange :
func getSubstringUpToIndex2(index: Int,
fromString str: String) -> String {
let range = str.startIndex.advancedBy(0)..<str.startIndex.advancedBy(index)
return str.substringWithRange(range)
}
Try them out on swiftstub.
The second line you pasted does not work anymore because swift 2 now handles errors with try/do/catch, the last parameter NSErrorPointer does not exist anymore, learn more about swift2 error handling here.

How can I check if a string contains Chinese in Swift?

I want to know that how can I check if a string contains Chinese in Swift?
For example, I want to check if there's Chinese inside:
var myString = "Hi! 大家好!It's contains Chinese!"
Thanks!
This answer
to How to determine if a character is a Chinese character can also easily be translated from
Ruby to Swift (now updated for Swift 3):
extension String {
var containsChineseCharacters: Bool {
return self.range(of: "\\p{Han}", options: .regularExpression) != nil
}
}
if myString.containsChineseCharacters {
print("Contains Chinese")
}
In a regular expression, "\p{Han}" matches all characters with the
"Han" Unicode property, which – as I understand it – are the characters
from the CJK languages.
Looking at questions on how to do this in other languages (such as this accepted answer for Ruby) it looks like the common technique is to determine if each character in the string falls in the CJK range. The ruby answer could be adapted to Swift strings as extension with the following code:
extension String {
var containsChineseCharacters: Bool {
return self.unicodeScalars.contains { scalar in
let cjkRanges: [ClosedInterval<UInt32>] = [
0x4E00...0x9FFF, // main block
0x3400...0x4DBF, // extended block A
0x20000...0x2A6DF, // extended block B
0x2A700...0x2B73F, // extended block C
]
return cjkRanges.contains { $0.contains(scalar.value) }
}
}
}
// true:
"Hi! 大家好!It's contains Chinese!".containsChineseCharacters
// false:
"Hello, world!".containsChineseCharacters
The ranges may already exist in Foundation somewhere rather than manually hardcoding them.
The above is for Swift 2.0, for earlier, you will have to use the free contains function rather than the protocol extension (twice):
extension String {
var containsChineseCharacters: Bool {
return contains(self.unicodeScalars) {
// older version of compiler seems to need extra help with type inference
(scalar: UnicodeScalar)->Bool in
let cjkRanges: [ClosedInterval<UInt32>] = [
0x4E00...0x9FFF, // main block
0x3400...0x4DBF, // extended block A
0x20000...0x2A6DF, // extended block B
0x2A700...0x2B73F, // extended block C
]
return contains(cjkRanges) { $0.contains(scalar.value) }
}
}
}
The accepted answer only find if string contains Chinese character, i created one suit for my own case:
enum ChineseRange {
case notFound, contain, all
}
extension String {
var findChineseCharacters: ChineseRange {
guard let a = self.range(of: "\\p{Han}*\\p{Han}", options: .regularExpression) else {
return .notFound
}
var result: ChineseRange
switch a {
case nil:
result = .notFound
case self.startIndex..<self.endIndex:
result = .all
default:
result = .contain
}
return result
}
}
if "你好".findChineseCharacters == .all {
print("All Chinese")
}
if "Chinese".findChineseCharacters == .notFound {
print("Not found Chinese")
}
if "Chinese你好".findChineseCharacters == .contain {
print("Contains Chinese")
}
gist here: https://gist.github.com/williamhqs/6899691b5a26272550578601bee17f1a
Try this in Swift 2:
var myString = "Hi! 大家好!It's contains Chinese!"
var a = false
for c in myString.characters {
let cs = String(c)
a = a || (cs != cs.stringByApplyingTransform(NSStringTransformMandarinToLatin, reverse: false))
}
print("\(myString) contains Chinese characters = \(a)")
I have created a Swift 3 String extension for checking how much Chinese characters a String contains. Similar to the code by Airspeed Velocity but more comprehensive. Checking various Unicode ranges to see whether a character is Chinese. See Chinese character ranges listed in the tables under section 18.1 in the Unicode standard specification: http://www.unicode.org/versions/Unicode9.0.0/ch18.pdf
The String extension can be found on GitHub: https://github.com/niklasberglund/String-chinese.swift
Usage example:
let myString = "Hi! 大家好!It contains Chinese!"
let chinesePercentage = myString.chinesePercentage()
let chineseCharacterCount = myString.chineseCharactersCount()
print("String contains \(chinesePercentage) percent Chinese. That's \(chineseCharacterCount) characters.")

How to capitalize the first character of sentence using Swift

I have a String description that holds my sentence and want to capitalize only the first letter. I tried different things but most of them give me exceptions and errors. I'm using Xcode 6.
Here is what I tried so far:
let cap = [description.substringToIndex(advance(0,1))] as String
description = cap.uppercaseString + description.substringFromIndex(1)
It gives me:
Type 'String.Index' does not conform to protocol 'IntegerLiteralConvertible'
I tried:
func capitalizedStringWithLocale(locale:0) -> String
But I haven't figured out how to make it work.
In Swift 2, you can do
String(text.characters.first!).capitalizedString + String(text.characters.dropFirst())
Another possibility in Swift 3:
extension String {
func capitalizeFirst() -> String {
let firstIndex = self.index(startIndex, offsetBy: 1)
return self.substring(to: firstIndex).capitalized + self.substring(from: firstIndex).lowercased()
}
}
For Swift 4:
Warnings from above Swift 3 code:
'substring(to:)' is deprecated: Please use String slicing subscript
with a 'partial range upto' operator.
'substring(from:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator.
Swift 4 solution:
extension String {
var capitalizedFirst: String {
guard !isEmpty else {
return self
}
let capitalizedFirstLetter = charAt(i: 0).uppercased()
let secondIndex = index(after: startIndex)
let remainingString = self[secondIndex..<endIndex]
let capitalizedString = "\(capitalizedFirstLetter)\(remainingString)"
return capitalizedString
}
}
Swift 5.0
Answer 1:
extension String {
func capitalizingFirstLetter() -> String {
return prefix(1).capitalized + dropFirst()
}
mutating func capitalizeFirstLetter() {
self = self.capitalizingFirstLetter()
}
}
Answer 2:
extension String {
func capitalizeFirstLetter() -> String {
return self.prefix(1).capitalized + dropFirst()
}
}
Answer 3:
extension String {
var capitalizeFirstLetter:String {
return self.prefix(1).capitalized + dropFirst()
}
}
import Foundation
// A lowercase string
let description = "the quick brown fox jumps over the lazy dog."
// The start index is the first letter
let first = description.startIndex
// The rest of the string goes from the position after the first letter
// to the end.
let rest = advance(first,1)..<description.endIndex
// Glue these two ranges together, with the first uppercased, and you'll
// get the result you want. Note that I'm using description[first...first]
// to get the first letter because I want a String, not a Character, which
// is what you'd get with description[first].
let capitalised = description[first...first].uppercaseString + description[rest]
// Result: "The quick brown fox jumps over the lazy dog."
You may want to make sure there's at least one character in your sentence before you start, as otherwise you'll get a runtime error trying to advance the index beyond the end of the string.
Here is how to do it in Swift 4; just in case if it helps anybody:
extension String {
func captalizeFirstCharacter() -> String {
var result = self
let substr1 = String(self[startIndex]).uppercased()
result.replaceSubrange(...startIndex, with: substr1)
return result
}
}
It won't mutate the original String.
extension String {
var capitalizedFirstLetter:String {
let string = self
return string.replacingCharacters(in: startIndex...startIndex, with: String(self[startIndex]).capitalized)
}
}
Answer:
let newSentence = sentence.capitalizedFirstLetter
For one or each word in string, you can use String's .capitalized property.
print("foo".capitalized) //prints: Foo
print("foo foo foo".capitalized) //prints: Foo Foo Foo
Swift 4.2 version:
extension String {
var firstCharCapitalized: String {
switch count {
case 0:
return self
case 1:
return uppercased()
default:
return self[startIndex].uppercased() + self[index(after: startIndex)...]
}
}
}
Simplest soulution for Swift 4.0.
Add as a computed property extension:
extension String {
var firstCapitalized: String {
var components = self.components(separatedBy: " ")
guard let first = components.first else {
return self
}
components[0] = first.capitalized
return components.joined(separator: " ")
}
}
Usage:
"hello world".firstCapitalized