Objective-C与Swift编码结果不一致问题排查及解决方案咨询
嘿,我来帮你理清这个问题——你遇到的编码不一致根本不是Objective-C和Swift的Base64实现差异,而是输入的原始字符串本身就不一样!
一、问题根源:JSON键顺序导致原始字符串不同
先对比你给出的两个初始字符串:
Objective-C初始字符串:
{"userType":2,"password":"qazwsx2","account":"15921810000"}
Swift初始字符串:"{\"userType\":2,\"account\":\"15921810000\",\"password\":\"qazwsx2\"}"
你会发现,JSON里的键顺序不一样:Objective-C是userType→password→account,Swift是userType→account→password。Base64是对原始二进制字节的直接编码,只要输入的字符串字节序列有差异,编码结果必然不同。而Objective-C和Swift的dataUsingEncoding:/data(using:)、Base64编码逻辑是完全一致的,问题出在输入源上。
二、最优解决办法:统一用JSON序列化生成字符串
手动拼接JSON字符串很容易出现这种键顺序不一致的问题,正确的做法是用系统的JSON序列化API生成字符串,这样能保证两边生成的二进制数据完全一致(iOS 13+/macOS 10.15+之后,JSONSerialization会按字典键的排序生成JSON,低版本虽然无序,但只要两边用同样的序列化逻辑,结果就会一致)。
Objective-C 正确实现代码
// 先构造参数字典,避免手动拼接字符串 NSDictionary *params = @{ @"userType": @2, @"password": @"qazwsx2", @"account": @"15921810000" }; NSError *error; // 序列化生成标准JSON数据 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error]; if (!error) { NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSData *encodeData = [jsonStr dataUsingEncoding:NSUTF8StringEncoding]; NSString *base64Str = [encodeData base64EncodedStringWithOptions:0]; // 此时base64Str会和Swift端完全一致 }
Swift 正确实现代码
// 构造相同的参数字典 let params: [String: Any] = [ "userType": 2, "password": "qazwsx2", "account": "15921810000" ] do { // 序列化生成标准JSON数据 let jsonData = try JSONSerialization.data(withJSONObject: params, options: []) if let jsonStr = String(data: jsonData, encoding: .utf8) { let encodeData = jsonStr.data(using: .utf8) let base64Str = encodeData?.base64EncodedString(options: .init(rawValue: 0)) // 此时base64Str会和Objective-C端完全一致 } } catch { print("JSON序列化失败:\(error)") }
三、备选方案:Objective-C桥接调用
如果你因为历史代码限制,不能修改现有的字符串生成逻辑,可以通过桥接的方式,让Swift直接调用Objective-C的编码方法,确保逻辑完全一致:
- 创建Objective-C工具类
StringEncoder.h
#import <Foundation/Foundation.h> @interface StringEncoder : NSObject /// 将字符串UTF8编码后转Base64 + (NSString *)base64EncodeWithUTF8String:(NSString *)inputStr; @end
StringEncoder.m
#import "StringEncoder.h" @implementation StringEncoder + (NSString *)base64EncodeWithUTF8String:(NSString *)inputStr { NSData *encodeData = [inputStr dataUsingEncoding:NSUTF8StringEncoding]; return [encodeData base64EncodedStringWithOptions:0]; } @end
- 配置Swift桥接文件
在你的Swift项目中创建桥接文件(比如YourProjectName-Bridging-Header.h),并添加:
#import "StringEncoder.h"
(如果项目已有桥接文件,直接添加导入语句即可)
- 在Swift中调用
// 使用和Objective-C端完全一致的原始字符串 let originalStr = "{\"userType\":2,\"password\":\"qazwsx2\",\"account\":\"15921810000\"}" let base64Str = StringEncoder.base64EncodeWithUTF8String(originalStr) // 此时base64Str会和Objective-C端的结果完全相同
内容的提问来源于stack exchange,提问作者dengApro

