web-dev-qa-db-fra.com

Générer une chaîne alphanumérique aléatoire dans Swift

Comment générer une chaîne alphanumérique aléatoire dans Swift?

149
vishnu
func randomStringWithLength (len : Int) -> NSString {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

    var randomString : NSMutableString = NSMutableString(capacity: len)

    for (var i=0; i < len; i++){
        var length = UInt32 (letters.length)
        var Rand = arc4random_uniform(length)
        randomString.appendFormat("%C", letters.characterAtIndex(Int(Rand)))
    }

    return randomString
}

Swift 3.0 Update

func randomString(length: Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = UInt32(letters.length)

    var randomString = ""

    for _ in 0 ..< length {
        let Rand = arc4random_uniform(len)
        var nextChar = letters.character(at: Int(Rand))
        randomString += NSString(characters: &nextChar, length: 1) as String
    }

    return randomString
}

Swift 4.2 Update

Swift 4.2 a apporté d’importantes améliorations dans la gestion des valeurs et des éléments aléatoires. Vous pouvez en savoir plus sur ces améliorations ici . Voici la méthode réduite à quelques lignes:

func randomString(length: Int) -> String {
  let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  return String((0...length-1).map{ _ in letters.randomElement()! })
}
260
iAhmed

Voici une solution prête à l'emploi dans la syntaxe Swiftier. Vous pouvez simplement copier et coller:

func randomAlphaNumericString(length: Int) -> String {
    let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let allowedCharsCount = UInt32(allowedChars.characters.count)
    var randomString = ""

    for _ in 0..<length {
        let randomNum = Int(arc4random_uniform(allowedCharsCount))
        let randomIndex = allowedChars.index(allowedChars.startIndex, offsetBy: randomNum)
        let newCharacter = allowedChars[randomIndex]
        randomString += String(newCharacter)
    }

    return randomString
}

Si vous préférez un Framework qui possède également des fonctionnalités plus pratiques, n'hésitez pas à consulter mon projet HandySwift. Il comprend également une belle solution pour les chaînes alphanumériques aléatoires}:

String(randomWithLength: 8, allowedCharactersType: .alphaNumeric) // => "2TgM5sUG"
56
Dschee

Vous pouvez également l'utiliser de la manière suivante:

extension String {

    static func random(length: Int = 20) -> String {

        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {

            let randomValue = arc4random_uniform(UInt32(base.characters.count))
            randomString += "\(base[base.startIndex.advancedBy(Int(randomValue))])"
        }

        return randomString
    }
}

Utilisation simple:

let randomString = String.random()

Syntaxe de Swift 3:

extension String {

    static func random(length: Int = 20) -> String {
        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {
            let randomValue = arc4random_uniform(UInt32(base.characters.count))
            randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])"
        }
        return randomString
    }
}

Syntaxe de Swift 4:

extension String {

    static func random(length: Int = 20) -> String {
        let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString: String = ""

        for _ in 0..<length {
            let randomValue = arc4random_uniform(UInt32(base.count))
            randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])"
        }
        return randomString
    }
}
44

Rapide:

let randomString = NSUUID().uuidString
20
Said

Avec Swift 4.2, votre meilleur choix est de créer une chaîne avec les caractères de votre choix, puis utilisez randomElement pour choisir chaque caractère:

let length = 32
let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomCharacters = (0..<length).map{_ in characters.randomElement()!}
let randomString = String(randomCharacters)

Je détaille plus sur ces changements ici .

10
leogdion

Swift 2.2 Version

// based on https://Gist.github.com/samuel-mellert/20b3c99dec168255a046
// which is based on https://Gist.github.com/szhernovoy/276e69eb90a0de84dd90
// Updated to work on Swift 2.2

func randomString(length: Int) -> String {
    let charactersString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let charactersArray : [Character] = Array(charactersString.characters)

    var string = ""
    for _ in 0..<length {
        string.append(charactersArray[Int(arc4random()) % charactersArray.count])
    }

    return string
}

Appelez fondamentalement cette méthode qui générera une chaîne aléatoire de la longueur de l'entier transmis à la fonction. Pour changer les caractères possibles, éditez simplement la chaîne charactersString. Prend en charge les caractères unicode aussi.

https://Gist.github.com/gingofthesouth/54bea667b28a815b2fe33a4da986e327

6

Simple et rapide - UUID (). UuidString

// renvoie une chaîne créée à partir de l'UUID, telle que "E621E1F8-C36C-495A-93FC-0C247A3E6E5F"

public var uuidString: String {get}

https://developer.Apple.com/documentation/foundation/uuid

Swift 3.0

let randomString = UUID().uuidString //0548CD07-7E2B-412B-AD69-5B2364644433
print(randomString.replacingOccurrences(of: "-", with: ""))
//0548CD077E2B412BAD695B2364644433

MODIFIER

Veuillez ne pas confondre avec UIDevice.current.identifierForVendor?.uuidString, il ne donnera pas de valeurs aléatoires.

6
Jaleel Nazir

pour Swift 3.0  

func randomString(_ length: Int) -> String {

    let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = UInt32(letters.length)

    var randomString = ""

    for _ in 0 ..< length {
        let Rand = arc4random_uniform(len)
        var nextChar = letters.character(at: Int(Rand))
        randomString += NSString(characters: &nextChar, length: 1) as String
    }

    return randomString
}
5
S1LENT WARRIOR

Peut sauver quelqu'un en tapant, si vous avez le cas inhabituel qui

la performance compte.

Voici une fonction extrêmement simple, claire et autonome qui met en cache,

(Je pense que c'est le genre de choses que vous laisseriez à la portée mondiale pour plus de simplicité.)

func randomNameString(length: Int = 7)->String{

    enum s {
        static let c = Array("abcdefghjklmnpqrstuvwxyz12345789".characters)
        static let k = UInt32(c.count)
    }

    var result = [Character](repeating: "a", count: length)

    for i in 0..<length {
        let r = Int(arc4random_uniform(s.k))
        result[i] = s.c[r]
    }

    return String(result)
}

Notez que le point ici est qu'il s'agit d'un jeu de caractères fixe et connu - il est mis en cache.

Si vous avez besoin d'un autre jeu de caractères différent, créez une autre fonction en cache,

func randomVowelsString(length: Int = 20)->String{
    enum s {
        static let c = Array("AEIOU".characters)
        ...

Astuce pratique:

Notez que l'ensemble "abcdefghjklmnpqrstuvwxyz12345789" évite les "mauvais" caractères

Il n'y a pas de 0, o, O, i, etc ... les personnages que les humains confondent souvent.

Ceci est souvent fait pour les codes de réservation, etc.

4
Fattie
func randomString(length: Int) -> String {
    // whatever letters you want to possibly appear in the output (unicode handled properly by Swift)
    let letters = "abcABC012你好吗????????????∆????∌⌘"
    let n = UInt32(letters.characters.count)
    var out = ""
    for _ in 0..<length {
        let index = letters.startIndex.advancedBy(Int(arc4random_uniform(n)))
        out.append(letters[index])
    }
    return out
}
3
Daniel Howard

Ma encore plus rapide mise en oeuvre de la question:

func randomAlphanumericString(length: Int) -> String {

    let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".characters
    let lettersLength = UInt32(letters.count)

    let randomCharacters = (0..<length).map { i -> String in
        let offset = Int(arc4random_uniform(lettersLength))
        let c = letters[letters.startIndex.advancedBy(offset)]
        return String(c)
    }

    return randomCharacters.joinWithSeparator("")
}
3
Lachezar

Si votre chaîne aléatoire doit être sécurisée-aléatoire, utilisez ceci:

import Foundation
import Security

// ...

private static func createAlphaNumericRandomString(length: Int) -> String? {
    // create random numbers from 0 to 63
    // use random numbers as index for accessing characters from the symbols string
    // this limit is chosen because it is close to the number of possible symbols A-Z, a-z, 0-9
    // so the error rate for invalid indices is low
    let randomNumberModulo: UInt8 = 64

    // indices greater than the length of the symbols string are invalid
    // invalid indices are skipped
    let symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

    var alphaNumericRandomString = ""

    let maximumIndex = symbols.count - 1

    while alphaNumericRandomString.count != length {
        let bytesCount = 1
        var randomByte: UInt8 = 0

        guard errSecSuccess == SecRandomCopyBytes(kSecRandomDefault, bytesCount, &randomByte) else {
            return nil
        }

        let randomIndex = randomByte % randomNumberModulo

        // check if index exceeds symbols string length, then skip
        guard randomIndex <= maximumIndex else { continue }

        let symbolIndex = symbols.index(symbols.startIndex, offsetBy: Int(randomIndex))
        alphaNumericRandomString.append(symbols[symbolIndex])
    }

    return alphaNumericRandomString
}
2
schirrmacher

Un pur Swift aléatoire String de toute CharacterSet.

Usage: CharacterSet.alphanumerics.randomString(length: 100)

extension CharacterSet {
    /// extracting characters
    /// https://stackoverflow.com/a/52133647/1033581
    public func characters() -> [Character] {
        return codePoints().compactMap { UnicodeScalar($0) }.map { Character($0) }
    }
    public func codePoints() -> [Int] {
        var result: [Int] = []
        var plane = 0
        for (i, w) in bitmapRepresentation.enumerated() {
            let k = i % 8193
            if k == 8192 {
                plane = Int(w) << 13
                continue
            }
            let base = (plane + k) << 3
            for j in 0 ..< 8 where w & 1 << j != 0 {
                result.append(base + j)
            }
        }
        return result
    }

    /// building random string of desired length
    /// https://stackoverflow.com/a/42895178/1033581
    public func randomString(length: Int) -> String {
        let charArray = characters()
        let charArrayCount = UInt32(charArray.count)
        var randomString = ""
        for _ in 0 ..< length {
            randomString += String(charArray[Int(arc4random_uniform(charArrayCount))])
        }
        return randomString
    }
}

La fonction characters() est mon implémentation la plus rapide connue .

2
Cœur

Boucle libre, mais limité à 43 caractères. Si vous avez besoin de plus, il peut être modifié. Cette approche présente deux avantages par rapport à l’utilisation exclusive d’un UUID:

  1. Entropie supérieure en utilisant des lettres minuscules, car UUID() ne génère que des majuscules
  2. Une UUID comporte au plus 36 caractères (y compris les 4 tirets), mais seulement 32 caractères sans. Si vous avez besoin de quelque chose de plus, ou si vous ne voulez pas que des tirets soient inclus, l’utilisation du base64EncodedString gère cette

De plus, cette fonction utilise une UInt pour éviter les nombres négatifs.

 func generateRandom(size: UInt) -> String {
        let prefixSize = Int(min(size, 43))
        let uuidString = UUID().uuidString.replacingOccurrences(of: "-", with: "")
        return String(Data(uuidString.utf8)
            .base64EncodedString()
            .replacingOccurrences(of: "=", with: "")
            .prefix(prefixSize))
    }

L'appeler en boucle pour vérifier la sortie:

for _ in 0...10 {
    print(generateRandom(size: 32))
}

Qui produit:

Nzk3NjgzMTdBQ0FBNDFCNzk2MDRENzZF
MUI5RURDQzE1RTdCNDA3RDg2MTI4QkQx
M0I3MjJBRjVFRTYyNDFCNkI5OUM1RUVC
RDA1RDZGQ0IzQjI1NDdGREI3NDgxM0Mx
NjcyNUQyOThCNzhCNEVFQTk1RTQ3NTIy
MDkwRTQ0RjFENUFGNEFDOTgyQTUxODI0
RDU2OTNBOUJGMDE4NDhEODlCNEQ1NjZG
RjM2MTUxRjM4RkY3NDU2OUFDOTI0Nzkz
QzUwOTE1N0U1RDVENDE4OEE5NTM2Rjcy
Nzk4QkMxNUJEMjYwNDJDQjhBQkY5QkY5
ODhFNjU0MDVEMUI2NEI5QUIyNjNCNkVF
1
CodeBender

Mis à jour pour Swift 4. Utilisez une variable stockée paresseuse sur l'extension de classe. Ceci n'est calculé qu'une fois.

extension String {

    static var chars: [Character] = {
        return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".map({$0})
    }()

    static func random(length: Int) -> String {
        var partial: [Character] = []

        for _ in 0..<length {
            let Rand = Int(arc4random_uniform(UInt32(chars.count)))
            partial.append(chars[Rand])
        }

        return String(partial)
    }
}

String.random(length: 10) //STQp9JQxoq
0
Kawin P.

C’est la solution Swift -est que je pourrais trouver. Swift 3.0

extension String {
    static func random(length: Int) -> String {
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let randomLength = UInt32(letters.characters.count)

        let randomString: String = (0 ..< length).reduce(String()) { accum, _ in
            let randomOffset = arc4random_uniform(randomLength)
            let randomIndex = letters.index(letters.startIndex, offsetBy: Int(randomOffset))
            return accum.appending(String(letters[randomIndex]))
        }

        return randomString
    } 
}
0
bojan4

Swift 4

Utilisation de RandomNumberGenerator pour obtenir de meilleures performances que la recommandation Apple

Utilisation: String.random(20) Résultat: CifkNZ9wy9jBOT0KJtV4

extension String{
   static func random(length:Int)->String{
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var randomString = ""

        while randomString.utf8.count < length{
            let randomLetter = letters.randomElement()
            randomString += randomLetter?.description ?? ""
        }
        return randomString
    }
}
0
Jad

Si vous avez juste besoin d'un identifiant unique, UUID().uuidString peut vous aider.

0
man1

Pour les personnes qui ne veulent pas taper tout le jeu de caractères:

func randomAlphanumericString(length: Int) -> String  {
    enum Statics {
        static let scalars = [UnicodeScalar("a").value...UnicodeScalar("z").value,
                              UnicodeScalar("A").value...UnicodeScalar("Z").value,
                              UnicodeScalar("0").value...UnicodeScalar("9").value].joined()

        static let characters = scalars.map { Character(UnicodeScalar($0)!) }
    }

    let result = (0..<length).map { _ in Statics.characters.randomElement()! }
    return String(result)
}
0
fal