ios - musical - eliminar lecciones e instrumentos de garageband
iOS: no se puede guardar el archivo en la carpeta ''Application Support'', pero sí en ''Documents'' (4)
A diferencia del directorio Documents
, el directorio de Application Support
no existe en la zona de pruebas de la aplicación de forma predeterminada. Necesitas crearlo antes de poder usarlo.
Y una forma mucho más sencilla de obtener una referencia al directorio es:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *appSupportDirectory = paths.firstObject;
Puedo descargar y guardar un archivo binario en la carpeta ''Documentos'' con un nombre personalizado perfectamente bien.
Si acabo de cambiar la URL a la carpeta ''Application Support'' en lugar de a la carpeta ''Documents'', no puedo escribir en esa URL diciendo que no existe.
Aquí está el código de construcción de la URL:
- ( NSURL * ) getSaveFolder
{
NSURL * appSupportDir = nil;
NSURL * appDirectory = nil;
NSArray * possibleURLs = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSAllDomainsMask];
if ( [possibleURLs count] >= 1 )
{
appSupportDir = [possibleURLs objectAtIndex:0];
}
if ( appSupportDir != nil)
{
NSString * appBundleID = [[NSBundle mainBundle] bundleIdentifier];
appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID];
}
return appSupportDir;
}
Aquí está el código de guardado:
- ( void ) writeOutDataToFile:( NSData * )data
{
NSURL * finalURL = [self.rootPathURL URLByAppendingPathComponent:self.aFileName];
[data writeToURL:finalURL atomically:YES];
}
Si cambio la NSArray a:
NSArray * possibleURLs = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
entonces se guarda bien.
He leído los documentos de Apple Docs on File y no puedo solucionarlo. ¿Qué me estoy perdiendo?
Aquí hay algunos códigos Swift para iOS que pueden escribir un archivo de datos binarios en el directorio de soporte de aplicaciones. Partes de esto se inspiraron en la respuesta de chrysAllwood.
/// Method to write a file containing binary data to the "application support" directory.
///
/// - Parameters:
/// - fileName: Name of the file to be written.
/// - dataBytes: File contents as a byte array.
/// - optionalSubfolder: Subfolder to contain the file, in addition to the bundle ID subfolder.
/// If this is omitted no extra subfolder is created/used.
/// - iCloudBackupForFolder: Specify false to opt out from iCloud backup for whole folder or
/// subfolder. This is only relevant if this method call results in
/// creation of the folder or subfolder, otherwise it is ignored.
/// - Returns: Nil if all OK, otherwise text for a couple of non-Error errors.
/// - Throws: Various errors possible, probably of type NSError.
public func writeBytesToApplicationSupportFile(_ fileName : String,
_ dataBytes : [UInt8],
optionalSubfolder : String? = nil,
iCloudBackupForFolder : Bool = true)
throws -> String? {
let fileManager = FileManager.default
// Get iOS directory for "application support" files
let appSupportDirectory =
fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first
if appSupportDirectory == nil {
return "Unable to determine iOS application support directory for this app."
}
// Add "bundle ID" as subfolder. This is recommended by Apple, although it is probably not
// necessary.
if Bundle.main.bundleIdentifier == nil {
return "Unable to determine bundle ID for the app."
}
var mySupportDirectory =
appSupportDirectory!.appendingPathComponent(Bundle.main.bundleIdentifier!)
// Add an additional subfolder if that option was specified
if optionalSubfolder != nil {
mySupportDirectory = appSupportDirectory!.appendingPathComponent(optionalSubfolder!)
}
// Create the folder and subfolder(s) as needed
if !fileManager.fileExists(atPath: mySupportDirectory.path) {
try fileManager.createDirectory(atPath: mySupportDirectory.path,
withIntermediateDirectories: true, attributes: nil)
// Opt out from iCloud backup for this subfolder if requested
if !iCloudBackupForFolder {
var resourceValues : URLResourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
try mySupportDirectory.setResourceValues(resourceValues)
}
}
// Create the file if necessary
let mySupportFile = mySupportDirectory.appendingPathComponent(fileName)
if !fileManager.fileExists(atPath: mySupportFile.path) {
if !fileManager.createFile(atPath: mySupportFile.path, contents: nil, attributes: nil) {
return "File creation failed."
}
}
// Write the file (finally)
let fileHandle = try FileHandle(forWritingTo: mySupportFile)
fileHandle.write(NSData(bytes: UnsafePointer(dataBytes), length: dataBytes.count) as Data)
fileHandle.closeFile()
return nil
}
En caso de que alguien no esté seguro de cómo hacer lo que describe rmaddy:
NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject];
//If there isn''t an App Support Directory yet ...
if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) {
NSError *error = nil;
//Create one
if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@"%@", error.localizedDescription);
}
else {
// *** OPTIONAL *** Mark the directory as excluded from iCloud backups
NSURL *url = [NSURL fileURLWithPath:appSupportDir];
if (![url setResourceValue:@YES
forKey:NSURLIsExcludedFromBackupKey
error:&error])
{
NSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription);
}
else {
NSLog(@"Yay");
}
}
}
Encontré el mismo problema y decidí usar un enfoque más conciso:
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask) as! [NSURL]
if let applicationSupportURL = urls.last {
fileManager.createDirectoryAtURL(applicationSupportURL, withIntermediateDirectories: true, attributes: nil, error: nil)
}
Esto funciona porque createDirectoryAtURL
usando withIntermediateDirectories: true
solo crea la carpeta si no existe.