23

SecRandomCopyBytesSwift 3.0 で使用してランダムなバイトを生成したい。これがSwift 2.2での方法です

private static func generateRandomBytes() -> String? {
    let data = NSMutableData(length: Int(32))

    let result = SecRandomCopyBytes(kSecRandomDefault, 32, UnsafeMutablePointer<UInt8>(data!.mutableBytes))
    if result == errSecSuccess {
        return data!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    } else {
        print("Problem generating random bytes")
        return nil
    }
}

Swift 3 では、unsafemutablebytes の概念が今とは異なることを知っているので、このようにしようとしましたが、戻ることはできません。リターン部分をコメントアウトしても、まだGeneric Parameter ResultType could not be inferred

fileprivate static func generateRandomBytes() -> String? {
    var keyData = Data(count: 32)
    _ = keyData.withUnsafeMutableBytes {mutableBytes in
        let result = SecRandomCopyBytes(kSecRandomDefault, keyData.count, mutableBytes)
        if result == errSecSuccess {
            return keyData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
        } else {
            print("Problem generating random bytes")
            return nil
        }
    }
    return nil
}

これを修正する方法を知っている人はいますか?

ありがとう

4

3 に答える 3

50

あなたは近くにいましたがreturn、クロージャーの内側では、外側の関数からではなく、クロージャーから戻ります。したがってSecRandomCopyBytes()、クロージャーでのみ呼び出す必要があり、結果が返されます。

func generateRandomBytes() -> String? {

    var keyData = Data(count: 32)
    let result = keyData.withUnsafeMutableBytes {
        (mutableBytes: UnsafeMutablePointer<UInt8>) -> Int32 in
        SecRandomCopyBytes(kSecRandomDefault, 32, mutableBytes)
    }
    if result == errSecSuccess {
        return keyData.base64EncodedString()
    } else {
        print("Problem generating random bytes")
        return nil
    }
}

「単一式クロージャ」の場合、クロージャ タイプは自動的に推測できるため、次のように短縮できます。

func generateRandomBytes() -> String? {

    var keyData = Data(count: 32)
    let result = keyData.withUnsafeMutableBytes {
        SecRandomCopyBytes(kSecRandomDefault, 32, $0)
    }
    if result == errSecSuccess {
        return keyData.base64EncodedString()
    } else {
        print("Problem generating random bytes")
        return nil
    }
}

スウィフト 5 アップデート:

func generateRandomBytes() -> String? {

    var keyData = Data(count: 32)
    let result = keyData.withUnsafeMutableBytes {
        SecRandomCopyBytes(kSecRandomDefault, 32, $0.baseAddress!)
    }
    if result == errSecSuccess {
        return keyData.base64EncodedString()
    } else {
        print("Problem generating random bytes")
        return nil
    }
}
于 2016-10-02T19:16:08.773 に答える
11

これは、Swift 5 を使用して関数を実装する最も簡単で「最も迅速な」方法です。

func generateRandomBytes() -> String? {
    var bytes = [UInt8](repeating: 0, count: 32)
    let result = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)

    guard result == errSecSuccess else {
        print("Problem generating random bytes")
        return nil
    }

    return Data(bytes).base64EncodedString()
}

一般に、関数の制御フローが式の成功または失敗、または非 nil 値の存在に依存する場合、if/else ステートメントではなくガード ステートメントを使用することが Swift でのベスト プラクティスです。

于 2019-10-30T04:59:50.473 に答える