UIImagePNGRepresentation返回为nil

本文介绍了在使用 UIImagePNGRepresentation 方法时遇到返回 nil 的问题,并提供了有效的解决方法。通过对图片进行重新绘制,可以避免该方法因无效的位图格式而返回 nil。

最近在改项目的bug,发现UIImagePNGRepresentation返回的值为空,然后在网上大概查了下也没有找到结果,因为在之前的一个项目中我也使用过这个方法,然后那个项目并没有返回nil。所以很懊恼,然后看了下api。我靠,竟然明文说明了有可能会返回nil的情况。

UIKIT_EXTERN  NSData * __nullable UIImagePNGRepresentation(UIImage * __nonnull image);                               // return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format
UIKIT_EXTERN  NSData * __nullable UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality);  // return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)
复制代码

May return nil if image has no CGImageRef or invalid bitmap format 解决方法就是重新给他绘制一个图就行了:

- (UIImage *)scaleImage:(UIImage *)image{
    //确定压缩后的size
    CGFloat scaleWidth = image.size.width;
    CGFloat scaleHeight = image.size.height;
    CGSize scaleSize = CGSizeMake(scaleWidth, scaleHeight);
    //开启图形上下文
    UIGraphicsBeginImageContext(scaleSize);
    //绘制图片
    [image drawInRect:CGRectMake(0, 0, scaleWidth, scaleHeight)];
    //从图形上下文获取图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    //关闭图形上下文
    UIGraphicsEndImageContext();
    return newImage;
}
复制代码
#pragma mark -- UIImagePickerControllerDelegate- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{ UIImage *pickImage = info[UIImagePickerControllerOriginalImage]; CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}]; // 获取选择图片中识别结果 NSArray *features = [detector featuresInImage:[CIImage imageWithData:UIImagePNGRepresentation(pickImage)]]; [picker dismissViewControllerAnimated:YES completion:^{ if (features.count > 0) { CIQRCodeFeature *feature = features[0]; NSString *stringValue = feature.messageString; [self handleScanValue:stringValue]; } else { [self readFromAlbumFailed]; } }];}- (void)changeVideoScale:(AVMetadataMachineReadableCodeObject *)objc { NSArray *array = objc.corners; CGPoint point = CGPointZero; int index = 0; CFDictionaryRef dict = (__bridge CFDictionaryRef)(array[index++]); // 把点转换为不可变字典 // 把字典转换为点,存在point里,成功返回true 其他false CGPointMakeWithDictionaryRepresentation(dict, &point); NSLog(@"X:%f -- Y:%f",point.x,point.y); CGPoint point2 = CGPointZero; CGPointMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)array[2], &point2); NSLog(@"X:%f -- Y:%f",point2.x,point2.y); NSLog(@"bounds:%@",NSStringFromCGRect(objc.bounds));}#pragma mark -- App 从后台进入前台- (void)appDidBecomeActive:(NSNotification *)notify { [self resumeScanning];}#pragma mark -- App 从前台进入后台- (void)appWillResignActive:(NSNotification *)notify { [self pauseScanning];}/** 恢复扫一扫功能 */- (void)resumeScanning { if (self.session) { [self.session startRunning]; [self.scannerView startLineAnimation]; }}/** 暂停扫一扫 */- (void)pauseScanning { if (self.session) { [self.session stopRunning]; [self.scannerView stopLineAnimation]; }}#pragma mark -- 扫一扫API/** 处理扫一扫结果 @param value 扫描结果 */- (void)handleScanValue:(NSString *)value { NSLog(@"handleScanValue === %@", value);}/** 相册选取图片无法读取数据 */- (void)readFromAlbumFailed { NSLog(@"readFromAlbumFailed");}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819
04-03
<think>首先,用户的问题是关于Redis的:当执行GET key命令时,返回nil nil的原因和解决方法。用户提到“返回 nil nil”,这可能是个打字错误,因为在Redis中,GET命令返回nil表示键不存在或值为空,但标准输出是(nil),而不是“nil nil”。所以,我需要澄清:在Redis命令行中,输出是像"(nil)"这样的格式。 从系统级指令中,我有一些引用: - 引用[1]:提到GET返回nil的原因包括键不存在、过期或类型不匹配。 - 引用[2]:解释nil值表示键不存在或值为null。 - 引用[3]:给出例子,如GET nonexisting返回(nil)。 - 引用[4]:提到keys命令返回空列表。 用户的问题焦点是“返回 nil nil”,但根据引用,应该是(nil)。所以,我会假设这是指返回(nil)的情况。 现在,回答结构: - 系统指令要求回答结构清晰,帮助用户逐步解决问题。 - 使用中文回答。 - 在行内数学表达式使用$...$,但这个问题不涉及数学,所以可能不需要。 - 独立公式用$$...$$,但这里没有公式。 - 生成相关问题。 - 在引用段落末尾添加引用标识,如[^1]。 回答内容: 1. **解释原因**:根据引用,GET key返回(nil)的原因主要有: - 键不存在:key从未被设置或已被删除。 - 键已过期:如果key设置了过期时间且已过期。 - 类型不匹配:如果key存在但不是字符串类型(GET只用于字符串类型)。 - 其他可能原因:如键被显式设置为nil(但在Redis中,SET key nil会设置键为字符串"nil",而不是nil值)。 2. **解决方法**: - 检查键是否存在:使用EXISTS key命令。 - 检查键的类型:使用TYPE key命令。 - 检查过期时间:使用TTL key命令查看剩余生存时间。 - 确保正确设置键:使用SET key value命令设置键。 - 如果键过期,重新设置它。 - 如果类型不匹配,使用正确的命令(如HGET for hash, etc.)。 3. **引用添加**:在解释中,自然地添加引用标识。例如: - 引用[1]说:GET返回nil的原因包括键不存在、过期或类型不匹配[^1]。 - 引用[2]解释:nil值表示键不存在或值为null[^2]。 - 引用[3]的例子:GET nonexisting返回(nil)[^3]。 4. **生成相关问题**:在回答末尾,添加"§§相关问题§§"部分,列出几个相关问题。 完整回答结构: - 开头:简要概述问题。 - 逐步解释原因。 - 提供解决方法。 - 添加引用。 - 最后,生成相关问题。 确保语言清晰、专业。</think>### Redis GET key 返回 (nil) 的原因和解决方法 在使用 Redis 时,执行 `GET key` 命令返回 `(nil)` 表示键 `key` 的值不存在或无效。这通常发生在开发或调试过程中,导致数据无法正常获取。根据 Redis 的官方文档和常见实践,我将逐步解释原因并提供解决方法,帮助您快速定位问题。以下分析基于 Redis 的标准行为,确保数据操作的可靠性和高效性[^1]。 #### 一、返回 (nil) 的常见原因 Redis 的 `GET` 命令仅用于获取字符串类型的值。如果返回 `(nil)`,表明键 `key` 无法被正确访问,主要原因包括: 1. **键不存在**:键 `key` 从未被设置、已被删除,或名称拼写错误。例如,如果键 `username` 不存在,执行 `GET username` 会直接返回 `(nil)`[^2][^3]。 2. **键已过期**:如果键设置了过期时间(通过 `EXPIRE` 或 `SETEX` 命令),且时间已到,Redis 会自动删除该键。此时 `GET` 会返回 `(nil)`,表示键已失效[^1]。 3. **类型不匹配**:Redis 支持多种数据类型(如字符串、哈希、列表)。如果键 `key` 不是字符串类型(例如是哈希或列表),`GET` 命令无法处理,会返回 `(nil)`[^1][^3]。例如,尝试用 `GET` 获取一个哈希键的值会失败。 4. **键被显式设置为空值**:虽然 Redis 不支持真正的 `null` 值,但如果键被设置为空字符串(如 `SET key ""`),`GET` 可能在某些客户端中显示为空或 `(nil)`,但这不是标准行为(标准返回应为空字符串)。 5. **网络或客户端问题**:在分布式环境中,网络延迟或客户端配置错误可能导致键未正确同步,表现为 `(nil)`。但这较少见,通常优先检查服务器端原因。 这些原因中,键不存在和过期是最常见的场景[^1][^2]。例如,引用中的一个例子显示:`GET nonexisting` 返回 `(nil)`,因为键 `nonexisting` 不存在[^3]。 #### 二、解决方法 要解决 `GET key` 返回 `(nil)` 的问题,请逐步排查以下步骤。确保使用 Redis 命令行工具(如 `redis-cli`)或客户端库进行测试。 1. **检查键是否存在**: - 使用 `EXISTS key` 命令确认键是否被创建。如果返回 `0`,表示键不存在。 - **解决方法**:重新设置键值。例如: ```bash SET key "value" # 设置键值 GET key # 现在应返回 "value" ``` - 如果键名可能拼写错误,使用 `KEYS pattern` 命令搜索匹配键(如 `KEYS user*` 查找以 "user" 开头的键)[^4]。 2. **检查键的过期状态**: - 使用 `TTL key` 命令查看键的剩余生存时间(TTL)。如果返回 `-2`,表示键已过期;返回 `-1` 表示永不过期。 - **解决方法**:如果键已过期,重新设置并指定过期时间。例如: ```bash SETEX key 3600 "value" # 设置键值,并设置1小时过期时间 ``` 3. **验证键的数据类型**: - 使用 `TYPE key` 命令检查键的类型。如果返回不是 `string`(如 `hash` 或 `list`),则 `GET` 命令无效。 - **解决方法**:改用对应数据类型的命令。例如: - 如果键是哈希类型,用 `HGET key field` 获取字段值。 - 如果键是列表类型,用 `LRANGE key 0 -1` 获取所有元素。 4. **排查客户端或环境问题**: - 确保 Redis 服务器运行正常(使用 `PING` 命令测试连接)。 - 检查客户端代码:确认在设置键时未出错(如误用 `DEL key` 删除键)。 - 如果使用集群,验证键是否在正确的节点上(使用 `CLUSTER KEYSLOT key` 检查槽位分配)。 #### 三、预防措施 为避免 `GET` 返回 `(nil)`,建议: - **设置默认值**:在代码中,处理 `(nil)` 时提供回退逻辑。例如在 Python 中: ```python import redis r = redis.Redis() value = r.get('key') or 'default' # 如果返回 None(对应 (nil)),使用默认值 ``` - **监控键状态**:定期使用 `EXISTS` 或 `TTL` 监控关键键,确保数据有效性。 - **合理使用命令**:避免对非字符串键使用 `GET`。Redis 的文档强调,理解数据类型是高效操作的基础[^1][^2]。 通过以上步骤,您可以快速诊断并解决 `GET key` 返回 `(nil)` 的问题。Redis 的高性能依赖于正确的命令使用,合理设置和检查键能显著提升应用可靠性[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值