Réponses:
Mise à jour Swift 4.2
Swift 4.2 a introduit des améliorations majeures dans le traitement 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).map{ _ in letters.randomElement()! })
}
Mise à jour 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
}
Réponse originale:
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
}
Voici une solution prête à l'emploi dans la syntaxe Swiftier . Vous pouvez simplement le copier-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"
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
}
}
Rapide:
let randomString = NSUUID().uuidString
Avec Swift 4.2, votre meilleur pari est de créer une chaîne avec les caractères que vous souhaitez, puis d'utiliser 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 .
Dans le cas inhabituel
Voici une fonction extrêmement claire qui met en cache :
func randomNameString(length: Int = 7)->String{
enum s {
static let c = Array("abcdefghjklmnpqrstuvwxyz12345789")
static let k = UInt32(c.count)
}
var result = [Character](repeating: "-", count: length)
for i in 0..<length {
let r = Int(arc4random_uniform(s.k))
result[i] = s.c[r]
}
return String(result)
}
C'est pour quand vous avez un jeu de caractères fixe et connu .
Conseil pratique:
Il n'y a pas de 0, o, O, i, etc ... les personnages confondent souvent les humains.
Cela est souvent fait pour les codes de réservation et les codes similaires que les clients humains utiliseront.
repeating:count:
.
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}
Swift 3.0
let randomString = UUID().uuidString //0548CD07-7E2B-412B-AD69-5B2364644433
print(randomString.replacingOccurrences(of: "-", with: ""))
//0548CD077E2B412BAD695B2364644433
ÉDITER
Veuillez ne pas confondre avec UIDevice.current.identifierForVendor?.uuidString
cela ne donnera pas de valeurs aléatoires.
Version Swift 2.2
// 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 essentiellement cette méthode qui générera une chaîne aléatoire de la longueur de l'entier remis à la fonction. Pour modifier les caractères possibles, modifiez simplement la chaîne de caractères de chaîne. Prend également en charge les caractères unicode.
https://gist.github.com/gingofthesouth/54bea667b28a815b2fe33a4da986e327
EXC_BAD_INSTRUCTION
let random = randomString(16)
. L'EXC n'était que sur un vrai appareil et je ne l'ai pas vu dans un simulateur et il était intermittent sur l'appareil.
random % count
ne crée pas (toujours) une distribution uniforme. Si cela vous concerne, recherchez d'autres réponses utiles arc4random_uniform()
.
Pour les gens qui ne veulent pas taper l'ensemble complet des 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)
}
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
}
Un Swift pur aléatoire String
de tout 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 characters()
fonction est mon implémentation la plus rapide connue .
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
}
Ma mise en œuvre encore plus rapide 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("")
}
Sans boucle, bien qu'il soit limité à 43 caractères. Si vous en avez besoin de plus, il peut être modifié. Cette approche présente deux avantages par rapport à l'utilisation exclusive d'un UUID:
UUID()
ne génère que des lettres majusculesUUID
comporte au maximum 36 caractères (y compris les 4 tirets), mais seulement 32 caractères sans. Si vous avez besoin de quelque chose de plus long ou si vous ne voulez pas de tirets inclus, l'utilisation des base64EncodedString
poignéesDe plus, cette fonction utilise un 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))
}
Ce qui produit:
Nzk3NjgzMTdBQ0FBNDFCNzk2MDRENzZF
MUI5RURDQzE1RTdCNDA3RDg2MTI4QkQx
M0I3MjJBRjVFRTYyNDFCNkI5OUM1RUVC
RDA1RDZGQ0IzQjI1NDdGREI3NDgxM0Mx
NjcyNUQyOThCNzhCNEVFQTk1RTQ3NTIy
MDkwRTQ0RjFENUFGNEFDOTgyQTUxODI0
RDU2OTNBOUJGMDE4NDhEODlCNEQ1NjZG
RjM2MTUxRjM4RkY3NDU2OUFDOTI0Nzkz
QzUwOTE1N0U1RDVENDE4OEE5NTM2Rjcy
Nzk4QkMxNUJEMjYwNDJDQjhBQkY5QkY5
ODhFNjU0MDVEMUI2NEI5QUIyNjNCNkVF
Swift 5.0
// Generating Random String
func randomString(length: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return String((0..<length).map{ _ in letters.randomElement()! })
}
// Calling to string
label.text = randomString(length: 3)
Le problème avec les réponses aux questions "J'ai besoin de chaînes aléatoires" (dans n'importe quelle langue) est que pratiquement chaque solution utilise une spécification primaire erronée de longueur de chaîne . Les questions elles-mêmes révèlent rarement pourquoi les chaînes aléatoires sont nécessaires, mais je vous mets au défi que vous ayez rarement besoin de chaînes aléatoires de longueur, disons 8. Ce dont vous avez invariablement besoin, c'est d'un certain nombre de chaînes uniques , par exemple, à utiliser comme identificateurs dans un certain but.
Il existe deux façons principales d'obtenir des chaînes strictement uniques : de manière déterministe (qui n'est pas aléatoire) et de stocker / comparer (ce qui est onéreux). Qu'est-ce qu'on fait? Nous abandonnons le fantôme. Nous optons plutôt pour l' unicité probabiliste . Autrement dit, nous acceptons qu'il existe un risque (aussi faible soit-il) que nos cordes ne soient pas uniques. C'est là que la compréhension de la probabilité de collision et de l' entropie est utile.
Je vais donc reformuler le besoin invariable comme nécessitant un certain nombre de chaînes avec un petit risque de répétition. À titre d'exemple concret, supposons que vous souhaitiez générer un potentiel de 5 millions d'ID. Vous ne voulez pas stocker et comparer chaque nouvelle chaîne et vous voulez qu'elles soient aléatoires, vous acceptez donc un risque de répétition. Par exemple, disons un risque de moins de 1 sur mille milliards de chances de répétition. Alors, quelle longueur de chaîne avez-vous besoin? Eh bien, cette question est sous-spécifiée car elle dépend des caractères utilisés. Mais plus important encore, c'est erroné. Ce dont vous avez besoin est une spécification de l'entropie des cordes, pas de leur longueur. L'entropie peut être directement liée à la probabilité de répétition dans un certain nombre de chaînes. La longueur de chaîne ne peut pas.
Et c'est là qu'une bibliothèque comme EntropyString peut vous aider. Pour générer des ID aléatoires qui ont moins de 1 chance sur 1 000 milliards de répétitions dans 5 millions de chaînes en utilisant EntropyString
:
import EntropyString
let random = Random()
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)
"Rrrj6pN4d6GBrFLH4"
EntropyString
utilise un jeu de caractères avec 32 caractères par défaut. Il existe d'autres jeux de caractères prédéfinis et vous pouvez également spécifier vos propres caractères. Par exemple, générer des ID avec la même entropie que ci-dessus mais en utilisant des caractères hexadécimaux:
import EntropyString
let random = Random(.charSet16)
let bits = Entropy.bits(for: 5.0e6, risk: 1.0e12)
random.string(bits: bits)
"135fe71aec7a80c02dce5"
Notez la différence de longueur de chaîne en raison de la différence du nombre total de caractères dans le jeu de caractères utilisé. Le risque de répétition dans le nombre spécifié de chaînes potentielles est le même. Les longueurs de chaîne ne le sont pas. Et surtout, le risque de répétition et le nombre potentiel de chaînes est explicite. Plus besoin de deviner avec la longueur de la chaîne.
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
}
Mis à jour pour Swift 4. Utilisez une variable stockée paresseuse sur l'extension de classe. Cela n'est calculé qu'une seule 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
SWIFT 4
Utilisation de RandomNumberGenerator pour de meilleures performances comme 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
}
}
Ceci est la Swift solution -est je pouvais 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
}
}
func randomUIDString(_ wlength: Int) -> String {
let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var randomString = ""
for _ in 0 ..< wlength {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString = randomString.appendingFormat("%C", letters.character(at: Int(rand)));
}
return randomString
}