无法解包Optional.None错误,但未使用可选

时间:2014-07-07 16:03:18

标签: swift hmac

我试图在Swift中编写一个HMAC类,首先在Objective C中编写它,然后使用Bridging-Header使该类可用于我的Swift代码。我很抱歉,如果我粘贴了太多代码,但我想知道为什么会这样,所以我可以更好地理解Swift和Objective C的接口,以及我如何解决错误I&# 39;得到。 " TBGHMAC.calculateWithAlgorithm:forKey:和Data:"函数产生一个"致命错误:无法解包Optional.None"错误。

从顶部开始,这是我的Swift代码中的代码片段,它调用Swift代码

    let key : String = "" // start with empty string"
    let data : String = "" // start with empty string"

    let signature : String = TBGHMAC.calculateWithAlgorithm(HMACAlgorithm.SHA256, forKey: key, andData: data)

    println(signature)

这是TBGHMAC头文件

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>

@interface TBGHMAC : NSObject


typedef NS_ENUM(NSInteger, HMACAlgorithm)
{
SHA1,
MD5,
SHA256,
SHA384,
SHA512,
SHA224
};

+ (NSString *)calculateWithAlgorithm:(HMACAlgorithm)algorithm forKey:(NSString*)key andData:(NSString *)data;

+ (NSInteger)digestLengthForAlgorithm:(HMACAlgorithm)algorithm;

@end

最后这里是实现文件

+ (NSString *)calculateWithAlgorithm:(HMACAlgorithm)algorithm forKey:(NSString *)key andData:(NSString *)data
{

    NSUInteger keyNumberOfBytes = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    void *keyBuffer = malloc(keyNumberOfBytes);
    NSUInteger keyUsedLength = 0;
    NSRange keyRange = NSMakeRange(0, [key length]);
    BOOL keyResult = [key getBytes:keyBuffer maxLength:keyNumberOfBytes usedLength:&keyUsedLength encoding:NSUTF8StringEncoding options:0 range:keyRange remainingRange:NULL];

    NSUInteger dataNumberOfBytes = [data lengthOfBytesUsingEncoding:NSUnicodeStringEncoding];
    void *dataBuffer = malloc(dataNumberOfBytes);
    NSUInteger dataUsedLength = 0;
    NSRange dataRange = NSMakeRange(0, [data length]);
    BOOL dataResult = [data getBytes:dataBuffer maxLength:dataNumberOfBytes usedLength:&dataUsedLength encoding:NSUTF8StringEncoding options:0 range:dataRange remainingRange:NULL];

    NSInteger digestLength = [self digestLengthForAlgorithm:algorithm];
    unsigned char hmac[digestLength];

    CCHmac(algorithm, &keyBuffer, strlen(keyBuffer), &dataBuffer, strlen(dataBuffer), &hmac);

    NSData *hmacBytes = [NSData dataWithBytes:hmac length:sizeof(hmac)];

    NSString* returnStr = [[NSString alloc] initWithData:hmacBytes encoding:NSUTF8StringEncoding];

    free(keyBuffer);
    free(dataBuffer);

    return returnStr;
}

+ (NSInteger)digestLengthForAlgorithm:(HMACAlgorithm)algorithm
{
    switch (algorithm)
    {
        case MD5: return CC_MD5_DIGEST_LENGTH;
        case SHA1: return CC_SHA1_DIGEST_LENGTH;
        case SHA224: return CC_SHA224_DIGEST_LENGTH;
        case SHA256: return CC_SHA256_DIGEST_LENGTH;
        case SHA384: return CC_SHA384_DIGEST_LENGTH;
        case SHA512: return CC_SHA512_DIGEST_LENGTH;
        default: return 0;
    }
}

@end

请指出为什么会出现此错误,以及我如何解决它。我不明白这个错误是如何产生的,因为我没有使用任何Optionals,Xcode也没有试图纠正我使用Optionals。

1 个答案:

答案 0 :(得分:1)

Objective-C方法

+ (NSString *)calculateWithAlgorithm:(HMACAlgorithm)algorithm forKey:(NSString*)key andData:(NSString *)data;

以暴露于Swift

class func calculateWithAlgorithm(algorithm: HMACAlgorithm, forKey key: String!, andData data: String!) -> String!

它返回(隐式解包)可选字符串,因为Objective-C方法返回的NSString可能是nil

将返回值转换为

中的String
let signature : String = BGHMAC.calculateWithAlgorithm(...)
如果返回值为nil(&#34;没有值&#34;),

会导致运行时异常。因此,您应该测试返回值 在使用之前:

let signature : String! = TBGHMAC.calculateWithAlgorithm(HMACAlgorithm.SHA256, forKey: key, andData: data)
if signature {
    println(signature)
} else {
    println("failed")
}

但为什么calculateWithAlgorithm()会返回nil?问题出在这里:

NSString* returnStr = [[NSString alloc] initWithData:hmacBytes encoding:NSUTF8StringEncoding];

消息摘要是一个非常随意的字节序列,无法解释 因此,作为UTF-8字符串,returnStr为零。

要解决您的问题,您可以将消息摘要转换为 使用 Base64编码的字符串:

NSString* returnStr = [hmacBytes base64EncodedStringWithOptions:0];