stringByAppendingPathComponent está indisponível

132

Meu aplicativo compartilha foto no Instagram; para isso, ele primeiro é salvo em um diretório temporário:

let writePath = NSTemporaryDirectory().stringByAppendingPathComponent("instagram.igo")

Ele estava trabalhando Swift 1.2, mas não funciona Swift 2.0.

A mensagem de erro fornecida é:

stringByAppendingPathComponent está indisponível: use URLByAppendingPathComponent em NSURL.

Maysam
fonte

Respostas:

145

Parece que o método stringByAppendingPathComponentfoi removido no Swift 2.0, então o que a mensagem de erro sugere é usar:

let writePath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("instagram.igo")

Atualizar:

URLByAppendingPathComponent()foi substituído por appendingPathComponent()então faça:

let writePath = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("instagram.igo")
Dániel Nagy
fonte
se você for usar esse design, terá problemas como converter espaço em% 20Application%20Support
Roman
não, o Swift 2.0 pode usar stringByAppendingPathComponent, veja minha resposta abaixo.
Jeffrey Neo
2
@JeffreyNeo sim, mas isso não é um NSURLmétodo, mas sim um #NSString
Dániel Nagy 5/15
@ DánielNagy Quero dizer que você disse que " stringByAppendingPathComponentfoi removido no Swift 2.0" não está correto, e o @Maysam não pediu apenas o NSURLmétodo.
Jeffrey Neo
4
@JeffreyNeo, na verdade, está correto, já que no String do Swift 1.2 havia um método chamado stringByAppendingPathComponent, mas o String do Swift 2.0 não. E o NSString não faz parte da linguagem Swift, faz parte da estrutura da Foundation.
Dániel Nagy
75

Está funcionando para NSStringque você possa usá-lo assim:

extension String {
    func stringByAppendingPathComponent(path: String) -> String {
        let nsSt = self as NSString
        return nsSt.stringByAppendingPathComponent(path)
    }
}

Agora você pode usar esta extensão que irá converter o seu Stringem NSStringprimeiro e depois executar a operação.

E seu código será:

let writePath = NSTemporaryDirectory().stringByAppendingPathComponent("instagram.igo")

Aqui estão alguns outros métodos para uso:

extension String {  

    var lastPathComponent: String {  
        return (self as NSString).lastPathComponent  
    }  
    var pathExtension: String {  
        return (self as NSString).pathExtension  
    }  
    var stringByDeletingLastPathComponent: String {  
        return (self as NSString).stringByDeletingLastPathComponent  
    }  
    var stringByDeletingPathExtension: String {  
        return (self as NSString).stringByDeletingPathExtension  
    }  
    var pathComponents: [String] {  
        return (self as NSString).pathComponents  
    }  
    func stringByAppendingPathComponent(path: String) -> String {  
        let nsSt = self as NSString  
        return nsSt.stringByAppendingPathComponent(path)  
    }  
    func stringByAppendingPathExtension(ext: String) -> String? {  
        let nsSt = self as NSString  
        return nsSt.stringByAppendingPathExtension(ext)  
    }  
}

Referência AQUI .

Para o Swift 3.0:

extension String {
    func stringByAppendingPathComponent1(path: String) -> String {
        let nsSt = self as NSString
        return nsSt.appendingPathComponent(path)
    }
}

let writePath = NSTemporaryDirectory().stringByAppendingPathComponent(path: "instagram.igo")


extension String {

    var lastPathComponent: String {
        return (self as NSString).lastPathComponent
    }
    var pathExtension: String {
        return (self as NSString).pathExtension
    }
    var stringByDeletingLastPathComponent: String {
        return (self as NSString).deletingLastPathComponent
    }
    var stringByDeletingPathExtension: String {
        return (self as NSString).deletingPathExtension
    }
    var pathComponents: [String] {
        return (self as NSString).pathComponents
    }
    func stringByAppendingPathComponent(path: String) -> String {
        let nsSt = self as NSString
        return nsSt.appendingPathComponent(path)
    }
    func stringByAppendingPathExtension(ext: String) -> String? {
        let nsSt = self as NSString
        return nsSt.appendingPathExtension(ext)
    }
}
Dharmesh Kheni
fonte
12
Embora essa seja uma solução válida, há uma razão pela qual a Apple removeu esses métodos - o uso de caminhos para localizar recursos é descontinuado e NSURLdeve ser usado s. Apenas dizendo.
Charlie Monroe
trecho: String (NSString (string: caminho) .stringByAppendingPathComponent (imageName)) ... caso contrário, bastante concordou com @CharlieMonroe
Bobjt
1
@CharlieMonroe, se esse é realmente o caso, por que ainda existem vários métodos que não aceitam uma URL como caminho no SDK?
precisa saber é o seguinte
@JorisMans Geralmente, são métodos mais antigos (disponíveis desde 10.0 ou mais cedo). Desde que o sandboxing foi introduzido, não há como passar por um caminho com, por exemplo, marcador de appscope - você precisa de um URL. A Apple é lenta na atualização de APIs que apenas poucas pessoas usam. Ou você tem um exemplo de uma API adicionada recentemente (nos últimos 3 a 4 anos)?
Charlie Monroe
1
@IulianOnofrei - Porque você deve estar usando checkResourceIsReachable()ou checkPromisedItemIsReachable()em URLvez disso. FileManagerainda é uma classe ObjC NSFileManagercom o NSprefixo removido para Swift e fileExistsAtPathexiste desde o OS X 10.0. O mundo evoluiu desde que, e como os aplicativos estão em área restrita (o que é menos óbvio no iOS), o arquivo pode existir, você pode não ter permissão para visualizá-lo; além disso, o arquivo pode estar na nuvem etc. É por isso que o BOOLmétodo simples é substituído por algo mais complexo URL, mas mais semanticamente correto.
Charlie Monroe
30

Simplesmente enrole sua corda como NSString.

let writePath = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("instagram.igo")
Jeffrey Neo
fonte
cool one .. Stringclass não tem isso, mas NSStringexiste! faz sentido.
preetam 10/08/16
16

para Swift 3 :

let writePath = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(directoryname).path

ou melhor, crie esta extensão:

extension String {
    func appendingPathComponent(_ string: String) -> String {
        return URL(fileURLWithPath: self).appendingPathComponent(string).path
    }
}

uso:

 let writePath = NSTemporaryDirectory().appendingPathComponent(directoryname)
Vyacheslav
fonte
6

Solução Swift 3:

Aqui está uma função para obter o caminho do diretório de documentos

    func getDocumentsDirectory() -> URL {
         let paths = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask)
         let documentsDirectory = paths[0]
         return documentsDirectory
     }

Como usar:

    getDocumentsDirectory.appendingPathComponent("google.com")

Resultado:

    file:///var/folders/w1/3rcp2fvs1qv43hfsh5876s0h0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.MyPlayground-7CF9F706-509C-4D4C-997E-AB8FE9E4A6EA/Documents/google.com
Revanth
fonte
5

Para swift 2.0

// Get the documents Directory
    func documentsDirectory() -> String {
        let documentsFolderPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
        return documentsFolderPath
    }

// Get path for a file in the directory
func fileInDocumentsDirectory(filename: String) -> String {

    let writePath = (documentsDirectory() as NSString).stringByAppendingPathComponent("Mobile")

    if (!NSFileManager.defaultManager().fileExistsAtPath(writePath)) {
        do {
            try NSFileManager.defaultManager().createDirectoryAtPath(writePath, withIntermediateDirectories: false, attributes: nil) }
            catch let error as NSError {
                print(error.localizedDescription);
        }
    }
    return (writePath as NSString).stringByAppendingPathComponent(filename)
}

//# MARK: - Save Image in Doc dir
func saveImage (image: UIImage, path: String ) -> Bool{

    let pngImageData = UIImagePNGRepresentation(image)
    //        let jpgImageData = UIImageJPEGRepresentation(image, 1.0)   // if you want to save as JPEG
    let result = pngImageData!.writeToFile(path, atomically: true)

    print("\(result)")
    print("\(path)")

    return result

}
Mehul Chuahan
fonte
2

Você pode usar URLByAppendingPathComponent (). Observe que você deve aparar a cadeia de caminho para remover o prefixo "file: //":

let uniqueFileName = NSUUID().UUIDString
let documentsDirectory = getDocumentsDirectoryURL()
    if let path = documentsDirectory?.URLByAppendingPathComponent(uniqueFileName) {
        var pathString = path.absoluteString
        pathString = imagePathString.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "file://"))
}

func getDocumentsDirectoryURL() -> NSURL? {
    let fileManager = NSFileManager()
    if let docsDirectory = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first {
        return docsDirectory
    }
    return nil
}
user2374993 - Inbal Tish
fonte
0

Faça o seguinte:

(("\(fileName)" as NSString).lastPathComponent as NSString).stringByDeletingPathExtension
Mauro Delazeri
fonte
0

Eu tentei isso e resolveu o problema.

antes:

let localPath = documentDirectory.URLByAppendingPathComponent(imageName)

depois de:

let localPath = (documentDirectory as NSString).appendingPathComponent(imageName)
Miah G.
fonte
-1

Se o uso de NSStringmétodos de caminho (em vez de Stringmétodos de URL) for aceitável, é muito mais fácil estender Stringcom uma propriedade computada ou um método retornando seu valor como NSString(em vez de duplicar os métodos desejados na Stringextensão):

extension String
{
    var ns: NSString { return self as NSString }
}

e depois:

swiftStringPath.ns.appendingPathComponent("whateva")
swiftStringPath.ns.deletingPathExtension
russo
fonte
-2

Swift 4

extension String {

    var lastPathComponent: String {
        return (self as NSString).lastPathComponent
    }
    var pathExtension: String {
        return (self as NSString).pathExtension
    }
    var stringByDeletingLastPathComponent: String {
        return (self as NSString).deletingLastPathComponent
    }
    var stringByDeletingPathExtension: String {
        return (self as NSString).deletingPathExtension
    }
    var pathComponents: [String] {
        return (self as NSString).pathComponents
    }
    func stringByAppendingPathComponent(path: String) -> String {
        let nsSt = self as NSString
        return nsSt.appendingPathComponent(path)
    }
    func stringByAppendingPathExtension(ext: String) -> String? {
        let nsSt = self as NSString
        return nsSt.appendingPathExtension(ext)
    }
}
Duncan Groenewald
fonte