浅析iOS沙盒(SandBox)及常见操作(目录读取、文件读写、文件夹操作等)

沙盒概念:

iOS 中的沙盒是一个较为独立和封闭的安全体系。每个应用程序在安装时会生成唯一一个文件夹。在该文件下存在着一个常见的媒体资源、代码、配置文件等。每个应用程序都只能被允许访问自己的沙盒,不能访问其它沙盒。下面是其主要沙盒存在的目录。

  • 1、Documents 目录:应用程序主要和必备的数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备份的信息。用户自己保存的文件在documents文件里

  • 2、AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。

  • 3、Library 目录:这个目录下有两个子目录:Caches 和 Preferences
    Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.
    Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。

  • 4 、temp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。

以及最后一个非常不常见的NSBundle。该东西系AppName.app对外封装的一个隐蔽文件,但其内部是为普通的文件夹,即为AppName.app的内容。常使用如下方法获取到对象或文件:

let path = Bundle.main.path(forResource: "lover", ofType: "mp3")

沙盒目录读取:

下面用一个工具类直接把调用方法标注出来。常见的使用目录包括应用程序主目录、Document目录、library目录、temp目录、Prefrences目录等。

import Foundation

class SandBoxUtil {
    
    // Get home path.
    static func homePath() -> String {
       return NSHomeDirectory();
    }

    // Get document path.
    static func documentPath() -> String {
        return NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0];
    }

    // Get library path.
    static func libraryPath() -> String {
        return NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]
    }

    // Get temp path.
    static func tempPath() -> String {
       return NSTemporaryDirectory()
    }

    // Get cache path.
    static func cachesPath() -> String {
        return NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0];
    }

    // Get prefrences path.
    static func perferencesPath() -> String {
        let lib = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0]
       return lib + "/Preferences"
    }

}

UserDefaults操作:

存:

    func saveWithNSUserDefaults() {
        let defaults = NSUserDefaults.standardUserDefaults();
        defaults.set("my_content", forKey: "key");
        defaults.synchronize();
    }

读:

    func readWithNSUserDefaults() {
        let defaults = NSUserDefaults.standardUserDefaults();
        let content = defaults.objectForKey("key") as NSString;
        println("\(content)");
    }

UserDefaults文件存储于

文件操作:

存:

    func saveWithFile() {
        let home = NSHomeDirectory() as NSString;
        let docPath = home.appendingPathComponent("Documents") as NSString;
        let filePath = docPath.appendingPathComponent("test.plist");
        var dataSource = NSMutableArray();
        dataSource.add("AppleiPhoneiPadMaciOS");
        dataSource.add("CC++JAVAC#SWIFTOC");
        // Wirite data into file.
        dataSource.write(toFile: filePath, atomically: true);
        print("\(filePath)");
    }

读:

    func readWithFile() {
        let home = NSHomeDirectory() as NSString;
        let docPath = home.appendingPathComponent("Documents") as NSString;
        let filePath = docPath.appendingPathComponent("test.plist");
        let dataSource = NSArray(contentsOfFile: filePath);
        print("\(dataSource!)");
    }

当然也可以一气呵成(随便写的)

    func createFile() {
        let fileManager = FileManager.default
        let createFilePath = "\(SandBoxUtil.documentPath())/kicinio.txt"
        let result = try! fileManager.createFile(atPath: createFilePath, contents: nil, attributes: nil)
        print("------> RESULT\(result)")
        let appendContent = "Keovast.Conga.Eldest"
        try! appendContent.write(toFile: createFilePath, atomically: true, encoding: String.Encoding.utf8)
        
        let path = NSHomeDirectory() + "/Documents/kicinio.txt"
        let readHandler =  FileHandle(forReadingAtPath: path)
        let data = readHandler?.readDataToEndOfFile()
        let readString = String(data: data!, encoding: String.Encoding.utf8)
        print("文件内容: \(String(describing: readString))")
    }

资源文件操作:

资源文件种类很多,这里以UIIMage示例读写。
存:

    private func saveImage(currentImage: UIImage, persent: CGFloat, imageName: String){
        if let imageData = currentImage.jpegData(compressionQuality: persent) as NSData? {
            let fullPath = NSHomeDirectory().appending("/Documents/").appending(imageName)
            imageData.write(toFile: fullPath, atomically: true)
            print("fullPath=\(fullPath)")
        }
    }

其中,persent为压缩比例,为1则不压缩,值越小则压缩效果越强。
读:

        if let savedImage = UIImage(contentsOfFile: "/Users/mac/Library/Developer/CoreSimulator/Devices/151891C3-D00C-4656-B1D3-3FA631AB8729/data/Containers/Data/Application/3C489D2F-00B3-4EE2-92A6-4E208B918822/Documents/apple") {
            self.imageView?.image = savedImage
        } else {
            print("文件不存在")
        }

其中contentsOfFile后跟的String类型参数即为被读取图片的路径。

文件夹操作:

文件夹是否存在:

通常为了避免异常,对文件/文件夹的操作是先判断其是否存在再进行。使用fileEists这个方法传入被判断的路径即返回布尔值。

let fileManager = FileManager.default
print("------> EXIST:\(fileManager.fileExists(atPath: delPath))

创建文件夹:

    func createFolder(){
        let newPath = "\(SandBoxUtil.documentPath())/Keovast"
        let fileManager = FileManager.default
        let createFolder = try! fileManager.createDirectory(atPath: newPath,withIntermediateDirectories: true, attributes: nil)
        print("------> CREATE FOLDER:\(createFolder)")
    }

删除文件夹:

    func deleteFolder() {
        let delPath = "\(SandBoxUtil.documentPath())/Keovast"
        let fileManager = FileManager.default
        print("------> EXIST:\(fileManager.fileExists(atPath: delPath))")
        try! fileManager.removeItem(atPath: delPath)
    }

移动文件至另外文件夹:

let fileManager = FileManager.default
let homeDirectory = NSHomeDirectory()
let srcUrl = homeDirectory + "/Documents/test.plist"
let toUrl = homeDirectory + "/Documents/moved/test.plist"
try! fileManager.moveItem(atPath: srcUrl, toPath: toUrl)

遍历文件夹:

func deepSearchAllFiles(folderName: NSString) -> NSArray
{
    let filePath = "\(folderName)"
    let exist = fileManager.fileExists(atPath: filePath)
    if (exist) {
       let contentsOfPathArray = fileManager.enumerator(atPath: filePath)
       return contentsOfPathArray!.allObjects as NSArray
    }else{
       return []
    }
}
iOS 上,应用沙盒目录是私有的,其他应用无法直接访问。因此,要从 JS 中获取 iOS 沙盒内的文件,需要通过 Native Bridge 的方式,即将 JS 中的请求传递给原生代码,由原生代码来实现文件读取并返回结果给 JS。 以下是一个简单的示例,假设你要获取沙盒内的一个名为 `example.txt` 的文件: 1. 在原生代码中实现文件读取逻辑,例如使用 `NSFileManager` 类读取文件内容: ```objc - (NSString *)readFileContentsAtPath:(NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; NSData *data = [fileManager contentsAtPath:path]; return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; } ``` 2. 在 JS 中定义一个函数,用于调用原生代码并获取文件内容: ```js function getExampleFileContents() { // 调用 Native Bridge 方法,传递路径参数 const path = 'path/to/example.txt'; const contents = NativeBridge.readFileContentsAtPath(path); return contents; } ``` 3. 在原生代码中实现 Native Bridge 方法,并将其暴露给 JS 环境: ```objc - (void)registerNativeBridgeMethods { [self.bridge registerNativeMethod:@"readFileContentsAtPath" handler:^(NSString *path) { NSString *contents = [self readFileContentsAtPath:path]; // 将结果返回给 JS 环境 [self.bridge callHandler:@"onFileContentsReceived" withArguments:@[contents]]; }]; } ``` 4. 在 JS 中注册 `onFileContentsReceived` 回调函数,用于接收原生代码返回的文件内容: ```js function onFileContentsReceived(contents) { // 处理文件内容 console.log(contents); } NativeBridge.registerEventHandler('onFileContentsReceived', onFileContentsReceived); ``` 注意:以上示例仅为演示 Native Bridge 的基本用法,具体实现方式可能因框架、平台、业务需求等因素而异。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值