iOS小技能: 保存图片到相册 |文件的常用操作(删除、修改、移动、复制)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

引言

  • iOS 保存图片到相册的需求:微信认证二维码界面,新增一个“保存到相册”按钮,点击完成将核心视图信保存到相册 。

  • NSFileManager类对文件的操作需求背景: 切换微信机器人时,备份iOS微信app的沙盒文件和目录

I 保存图片

    //参数1:图片对象
    //参数2:成功方法绑定的target
    //参数3:成功后调用方法
    //参数4:需要传递信息(成功后调用方法的参数) 一般写nil
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

复制代码

需求: 码牌类设备(含电子立牌、静态码牌、码牌喇叭一体机)增加收款二维码查看和下载功能

在这里插入图片描述

1.1 直接保存图片对象

  • 例子1
- (IBAction)saveClick:(UIButton *)sender {
    //参数1:图片对象
    //参数2:成功方法绑定的target
    //参数3:成功后调用方法
    //参数4:需要传递信息(成功后调用方法的参数) 一般写nil
    UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    /* 1.先保存图片到【相机胶卷】(不能直接保存到自定义相册中)
        1> C语言函数
        2> AssetsLibrary框架  (iOS4支持,iOS9.0被废弃)
        3> Photos框架 (iOS 8.0支持 推荐使用)
       2.拥有一个【自定义相册】
        1> AssetsLibrary框架
        2> Photos框架
       3.将刚才保存到【相机胶卷】里面的图片引用到【自定义相册】
        1> AssetsLibrary框架
        2> Photos框架
     */
    
}
#pragma mark -- <保存到相册>
-(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    NSString *msg = nil ;
    if(error){
        msg = @"保存图片失败" ;
    }else{
        msg = @"保存图片成功" ;
    }
}

复制代码

1.2 保持视图到相册

  • 例子2: 保持视图到相册

保留商户名称和微信商户号信息

在这里插入图片描述

//保存图片
- (void)saveImageToPicture {
    
    
    UIGraphicsBeginImageContextWithOptions(self.penView.canvasView.bounds.size, NO, 0.0);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    [self.penView.canvasView.layer renderInContext:ctx];
    
    self.saveImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    //保存到相册
    UIImageWriteToSavedPhotosAlbum(self.saveImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

    
    return;

}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    NSString *msg = @"保存成功";
    if (error != nil) {
        msg = @"保存失败!";
    }
    
    UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"" message:msg preferredStyle:UIAlertControllerStyleAlert];
    [alertVc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        
    }]];
    
    [self presentViewController:alertVc animated:YES completion:nil];
}


复制代码

效果: 在这里插入图片描述

II、相关辅助工具

2.1 做权限校验

在这里插入图片描述

  • 用法
// 检测摄像头
    if(![QCTLocationServiceUtil isHasCameraAuthorityWithisShowAlert:YES]){
        return ;
    }

        // 做相册权限校验
        
        if(![QCTLocationServiceUtil isHasPhotoLibraryAuthorityWithisShowAlert:YES]){
            return ;
        }


复制代码
  • 做相册权限校验
+(BOOL)isHasPhotoLibraryAuthorityWithisShowAlert:(BOOL)showAlert
{
    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
    if (status == ALAuthorizationStatusRestricted || status == ALAuthorizationStatusDenied) {
        NSLog(@"LBLog 没有访问图库的权限==============");
        if (showAlert) {
            [LBAlertController showAlertTitle:@"无法使用相册" content:@"请在iPhone的\"设置-隐私-照片\"中允许访问照片。" cancelString:@"取消" cancleBlock:nil sureString:@"去设置" sureBlock:^{
                // 需要在info.plist中添加 URL types 并设置一项URL Schemes为prefs  IOS10 以后不起作用 else的方法
                
                    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]){
                    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                }
            } currentController:[DY_Common getCurrentVC]];
        }
        
        
        return NO;
    }else if(status == ALAuthorizationStatusNotDetermined){
        
    }
    
    return  YES;
}

复制代码
  • 做照相机权限校验
/**
 去设置相机权限的的时候系统会kill 当前app进程 Message from debugger: Terminated due to signal 9
 @param showAlert <#showAlert description#>
 @return <#return value description#>
 */
+(BOOL)isHasCameraAuthorityWithisShowAlert:(BOOL)showAlert
{
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied) {
        NSLog(@"LBLog 没有访问相机的权限");
        if (showAlert) {
            [LBAlertController showAlertTitle:@"无法使用相机" content:@"请在iPhone的\"设置-隐私-相机\"中允许访问相机。" cancelString:@"取消" cancleBlock:nil sureString:@"去设置" sureBlock:^{
                // 需要在info.plist中添加 URL types 并设置一项URL Schemes为prefs  IOS10 以后不起作用
                    if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]){
                    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                }
            } currentController:[DY_Common getCurrentVC]];
            return NO;
        }else if (status == AVAuthorizationStatusNotDetermined){
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if (granted) {
                    NSLog(@"LBLog 获取相机权限正常==============");
                    
                }else{
                    NSLog(@"LBLog 获取相机权限不正常==============");
                }
            }];
        }
    }
    NSLog(@"LBLog 有访问相机的权限 =============");
    return YES;
}

复制代码

2.2 Base64 转UIImage

  • Base64 转UIImage
+ (UIImage *)stringToImage:(NSString *)str {

NSData * imageData =[[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

UIImage *photo = [UIImage imageWithData:imageData ];

return photo;

}


复制代码

2.3 将当前的VC的界面作为另一个VC的背景图片

使用系统自带的modal样式:UIModalPresentationOverCurrentContext

  • A presentation style where the content is displayed over another view controller’s content)

———————————————— 版权声明:本文为CSDN博主「iOS逆向」的原创文章,遵循CC 4.0 >BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/z929118967/…

III see also :视频下载,并保存到相册

iOS NSFileManager类对文件的操作、NSFileHandle对文件内容进行读取和写入例子:使用dataWithContentsOfURL进行视频下载,并保存到相册

1、使用dataWithContentsOfURL进行视频下载,并保存到相册

2、从沙盒获取信息:NSFileManager类主要对文件的操作(删除、修改、移动、复制等等) NSFileHandle 类主要对文件内容进行读取和写入操作

————————————————

版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/z929118967/…

3.1 视频下载,并保存到相册

  • 使用dataWithContentsOfURL进行视频下载,并保存到相册
NSFileManager *fileManage = [NSFileManager defaultManager];
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:videoUrl]];
          
        if (data == nil)
        {
            NSLog(@"网络出错,请稍后再试");
        }
        else
        {
            //用单例类 NSFileManager的对象,将文件写入本地
            BOOL isSuccess = [fileManage createFileAtPath:path contents:data attributes:nil];
            if (isSuccess)
            {
                NSLog(@"视频下载成功");
                // 保存视频到相册
                ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
                [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:path]
                   
                                            completionBlock:^(NSURL *assetURL, NSError *error) {
                                                  
                                                if (error) {
                                                      
                                                    NSLog(@"Save video fail:%@",error);
                                                      
                                                } else {
                                                    //2018-09-13 20:03:33.870 WeChat[6484:1077151] [MMVideoCompressHelper getCacheFilePathFrom:file:///var/mobile/Media/DCIM/100APPLE/IMG_0041.mp4 ]
                                                    NSLog(@"Save video succeed.:%@",assetURL);//assets-library://asset/asset.mp4?id=45C3D675-C625-4C52-B133-66D0A709AC57&ext=mp4
                                                      
                                                    // 获取相册的最新一条视频的path,进行SightDraft的创建
                                                      
                                                }
                                                  
                                            }];
            }
            else
            {
                NSLog(@"视频下载失败");
            }
复制代码

3.2 NSFileManager类对文件的操作:删除、修改、移动、复制

  • [在sb tweak 中 拷贝特定文件到特定app的沙盒路径]

<script src="https://gist.github.com/zhangkn/74ce4737a33221228244b9b18f8e545a.js"></script>

%new 
- (void)setupkeyword{// /var/mobile/Media/keyword.txt -> sanboxpath/Documents/keyword.txt
	SBApplicationController *sbApplicationCtrl=[%c(SBApplicationController) sharedInstance];
	id app = [sbApplicationCtrl applicationWithBundleIdentifier:@"com.tencent.xin"];
	NSString *contentUserIDURL =  [app sandboxPath];
        //Library 
          //Documents
        //tmp keyword.txt
	NSString *realFile = [[contentUserIDURL stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"keyword.txt"];
        //拷贝文件到这个地方,即可
	//从某个路径读取文件内容 最好放在 /var/mobile/Media/keyword.txt -> realFile
	NSLog(@"knrealFile %@",realFile);
	NSString *tmpfile = @"/var/mobile/Media/keyword.txt";
	NSString *content = [NSString stringWithContentsOfFile:tmpfile encoding:NSUTF8StringEncoding error:nil];
	NSData *data = [content dataUsingEncoding: NSUTF8StringEncoding]; 
        //写到目标文件
              	 [data writeToFile:realFile atomically:YES];//覆盖
 }

复制代码
  • 利用enumeratorAtPath,遍历NSDirectoryEnumerator 字典
  • 利用contentsOfDirectoryAtPath,遍历files数组
#import "KNdelateDirTool.h"

@implementation KNdelateDirTool

//利用enumeratorAtPath,便利NSDirectoryEnumerator 字典
static id setupdeletedir(NSString* path) {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError* err = nil;
    NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:path];//获取NSDictionary
    NSString *file;
    while ((file = [dirEnum nextObject]))//遍历NSDictionary
        //        if ([file hasSuffix:@"/Documents"] || [file hasSuffix:@"/Library"] || [file hasSuffix:@"/tmp"] || [file hasSuffix:@"/StoreKit"]) 过滤条件
    {
        [fileManager removeItemAtPath:[path stringByAppendingPathComponent:file] error:&err];
        //            [fileManager createDirectoryAtPath:[path stringByAppendingPathComponent:file] withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:@"mobile", NSFileOwnerAccountName, @"mobile", NSFileGroupOwnerAccountName, nil] error:nil];
        if (err) {
            NSLog(@"setupdeletedir err:%@", err);
            return @[@(NO), err];// 失败和错误信息
        }
    }
    return @[@(YES)];// 成功
}

//利用contentsOfDirectoryAtPath,遍历files数组
static id kncleanDir(NSString* path, NSString* reg) {
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *files = [fm contentsOfDirectoryAtPath:path error:NULL];
    for (NSString* file in files) {
        if (knmathFile(file, reg)) {// 正则表达式进行过滤,利用NSPredicate 实现,更多信息请看这里:谓词NSPredicate技术的应用。https://blog.csdn.net/z929118967/article/details/74066170
            NSString* fullpath = [path stringByAppendingPathComponent:file];//路径的拼接
            NSError* err = nil;
            [fm removeItemAtPath:fullpath error:&err];//移除
            if (err) {
                NSLog(@"kncleanDir err:%@", err);
                return @[@(NO), err];
            }
        }
    }
    return @[@(YES)];
}
//谓词技术的使用 evaluateWithObject
static BOOL knmathFile(NSString* file, NSString* reg) {
    if (!reg)
        return YES;
    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",reg];
    return [predicate evaluateWithObject:file];
}
@end

复制代码
  • 其他代码片段

github.com/kunnan/KNio… gist.github.com/zhangkn/cd3…

code: KNiosreTool存储一些逆向分析的工具代码片段: 清理文件、自动登录Wi-Fi

github.com/kunnan/KNio… 获取资源可关注公众号:iOS逆向

猜你喜欢

转载自juejin.im/post/7085888108125749255