Skip to main content
Code Review

Return to Answer

added 109 characters in body
Source Link
Hamish
  • 433
  • 4
  • 7
struct PasswordGenerator {
 
 var length: Int
 
 var characterSet: CharacterSet {
 didSet {
 // re-compute the characters array after the character set changing.
 characters = Array(characterSet.characters)
 }
 }
 
 // cached characters.
 private var characters: [Character] // cached characters.
 
 // default options of just using letters (upper and lowercase)
 init(length: Int, characterSet: CharacterSet = .letters) {
 self.length = length
 self.characterSet = characterSet
 self.characters = Array(characterSet.characters)
 }
 
 func/// generate()Generate ->a Stringnew {
password with a given length from the given character set.
 /// we cannot generate a/// password- ifPrecondition: there'sThe nocharacter charactersset must be non-empty.
 func generate() -> String //{
 to generate it from.
 guard precondition(!characters.isEmpty,
 else {
 return ""
 "Cannot generate password }from an empty character set.")
 
 let characterCount = UInt32(characters.count)
 
 let result = (0 ..< length).map { _ in
 characters[Int(arc4random_uniform(characterCount))]
 }
 
 return String(result)
 }
}
  • Caching the characters to generate the password from (re-creating upon the character set changing, with a didSet observer)
  • Using our custom .letters option as the default character set to generate from.
  • Guarding against an empty character option set being selected by just returning an empty stringusing a precondition check.
struct PasswordGenerator {
 
 var length: Int
 
 var characterSet: CharacterSet {
 didSet {
 // re-compute the characters array after the character set changing.
 characters = Array(characterSet.characters)
 }
 }
 
 // cached characters.
 private var characters: [Character]
 
 // default options of just using letters (upper and lowercase)
 init(length: Int, characterSet: CharacterSet = .letters) {
 self.length = length
 self.characterSet = characterSet
 self.characters = Array(characterSet.characters)
 }
 
 func generate() -> String {
 // we cannot generate a password if there's no characters
 // to generate it from.
 guard !characters.isEmpty else {
 return ""
 }
 
 let characterCount = UInt32(characters.count)
 
 let result = (0 ..< length).map { _ in
 characters[Int(arc4random_uniform(characterCount))]
 }
 
 return String(result)
 }
}
  • Caching the characters to generate the password from (re-creating upon the character set changing, with a didSet observer)
  • Using our custom .letters option as the default character set to generate from.
  • Guarding against an empty character option set being selected by just returning an empty string.
struct PasswordGenerator {
 
 var length: Int
 
 var characterSet: CharacterSet {
 didSet {
 // re-compute the characters array after the character set changing.
 characters = Array(characterSet.characters)
 }
 }
 
 private var characters: [Character] // cached characters.
 
 // default options of just using letters (upper and lowercase)
 init(length: Int, characterSet: CharacterSet = .letters) {
 self.length = length
 self.characterSet = characterSet
 self.characters = Array(characterSet.characters)
 }
 
 /// Generate a new password with a given length from the given character set.
 /// /// - Precondition: The character set must be non-empty.
 func generate() -> String {
  precondition(!characters.isEmpty,
 "Cannot generate password from an empty character set.")
 
 let characterCount = UInt32(characters.count)
 
 let result = (0 ..< length).map { _ in
 characters[Int(arc4random_uniform(characterCount))]
 }
 
 return String(result)
 }
}
  • Caching the characters to generate the password from (re-creating upon the character set changing, with a didSet observer)
  • Using our custom .letters option as the default character set to generate from.
  • Guarding against an empty character option set being selected by using a precondition check.
added 62 characters in body
Source Link
Hamish
  • 433
  • 4
  • 7

(Note that this will conflict with Foundation's CharacterSet, but given as it's a nested type, this shouldn't be problematic, as it will only conflict in the scope of PasswordGenerator)

(Note that this will conflict with Foundation's CharacterSet, but given as it's a nested type, this shouldn't be problematic)

(Note that this will conflict with Foundation's CharacterSet, but given as it's a nested type, this shouldn't be problematic, as it will only conflict in the scope of PasswordGenerator)

added 36 characters in body
Source Link
Hamish
  • 433
  • 4
  • 7
extension PasswordGenerator {
 
 struct CharacterSet : OptionSet {
 
 static let lowercase = CharacterSet(rawValue: 1 << 0)
 static let uppercase = CharacterSet(rawValue: 1 << 1)
 static let numbers = CharacterSet(rawValue: 1 << 2)
 static let symbols = CharacterSet(rawValue: 1 << 3)
 
 static let letters: CharacterSet = [.lowercase, .uppercase]
 static let alphanumeric: CharacterSet = [.letters, .numbers]
 
 let rawValue: Int
 var characters: Set<Character> {
 
 var characters = Set<Character>()
 
 if contains(.lowercase) { // in Swift 4, remove ".characters"
 characters.formUnion("abcdefghijklmnopqrstuvwxyz".characters)
 }
 
 if contains(.uppercase) {
 characters.formUnion("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
 }
 
 if contains(.numbers) {
 characters.formUnion("1234567890".characters)
 }
 
 if contains(.symbols) {
 characters.formUnion("!@#$%^&*".characters)
 }
 return characters
 }
 }
}

This also lets us define some custom character sets, such as letters and alphanumeric, which are a combination of other sets – as well as encapsulate the logic to produce the set of characters to work with, as this could well be re-used.

Note that we're now using a Set to represent the collection of characters we can choose from, as it better describes the collection (unique characters that aren't ordered) – not to mention allowing for constant lookup time of a given character in the set.

You can see we're now also:

extension PasswordGenerator {
 
 struct CharacterSet : OptionSet {
 
 static let lowercase = CharacterSet(rawValue: 1 << 0)
 static let uppercase = CharacterSet(rawValue: 1 << 1)
 static let numbers = CharacterSet(rawValue: 1 << 2)
 static let symbols = CharacterSet(rawValue: 1 << 3)
 
 static let letters: CharacterSet = [.lowercase, .uppercase]
 static let alphanumeric: CharacterSet = [.letters, .numbers]
 
 let rawValue: Int
 var characters: Set<Character> {
 
 var characters = Set<Character>()
 
 if contains(.lowercase) {
 characters.formUnion("abcdefghijklmnopqrstuvwxyz".characters)
 }
 
 if contains(.uppercase) {
 characters.formUnion("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
 }
 
 if contains(.numbers) {
 characters.formUnion("1234567890".characters)
 }
 
 if contains(.symbols) {
 characters.formUnion("!@#$%^&*".characters)
 }
 return characters
 }
 }
}

This also lets us define some custom character sets, such as letters and alphanumeric, which are a combination of other sets – as well as encapsulate the logic to produce the set of characters to work with, as this could well be re-used. Note that we're now using a Set to represent the collection of characters we can choose from, as it better describes the collection (unique characters that aren't ordered).

You can see we're now:

extension PasswordGenerator {
 
 struct CharacterSet : OptionSet {
 
 static let lowercase = CharacterSet(rawValue: 1 << 0)
 static let uppercase = CharacterSet(rawValue: 1 << 1)
 static let numbers = CharacterSet(rawValue: 1 << 2)
 static let symbols = CharacterSet(rawValue: 1 << 3)
 
 static let letters: CharacterSet = [.lowercase, .uppercase]
 static let alphanumeric: CharacterSet = [.letters, .numbers]
 
 let rawValue: Int
 var characters: Set<Character> {
 
 var characters = Set<Character>()
 
 if contains(.lowercase) { // in Swift 4, remove ".characters"
 characters.formUnion("abcdefghijklmnopqrstuvwxyz".characters)
 }
 
 if contains(.uppercase) {
 characters.formUnion("ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
 }
 
 if contains(.numbers) {
 characters.formUnion("1234567890".characters)
 }
 
 if contains(.symbols) {
 characters.formUnion("!@#$%^&*".characters)
 }
 return characters
 }
 }
}

This also lets us define some custom character sets, such as letters and alphanumeric, which are a combination of other sets – as well as encapsulate the logic to produce the set of characters to work with, as this could well be re-used.

Note that we're now using a Set to represent the collection of characters we can choose from, as it better describes the collection (unique characters that aren't ordered) – not to mention allowing for constant lookup time of a given character in the set.

You can see we're now also:

added 113 characters in body
Source Link
Hamish
  • 433
  • 4
  • 7
Loading
added 31 characters in body
Source Link
Hamish
  • 433
  • 4
  • 7
Loading
Source Link
Hamish
  • 433
  • 4
  • 7
Loading
default

AltStyle によって変換されたページ (->オリジナル) /