Swift 2.0 - stringByAppendingPathComponent error conversion [duplicate] - xcode

This question already has answers here:
stringByAppendingPathComponent is unavailable
(11 answers)
Closed 7 years ago.
I have updated Xcode to 7 all my apps, after the conversion from swift to swift 2.0, got errors that after a bit of research I was able to manually fix them.
However, I have an error with 'stringByAppendingPathComponent' that I cannot solve. It seems that swift 2.0 removed this method.
The picture attached shows the error I am tiling about.
Any Idea how to solve this issue?
func loadNotes(){
let plistPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let DocumentsDirectory = plistPath[0] as! String
let path = DocumentsDirectory.stringByAppendingPathComponent("notes.plist")
let fileManager = NSFileManager.defaultManager()
if (!fileManager.fileExistsAtPath(path)) {
if let bundlePath = NSBundle.mainBundle().pathForResource("notes", ofType: "plist") {
let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
println("Bundle notes.plist file is --> \(resultDictionary?.description)")
fileManager.copyItemAtPath(bundlePath, toPath: path, error: nil)
println("copy")
} else {
println("notes.plist not found")
}
}else {
println("note.plist already exists")
//fileManager.removeItemAtPath(path, error: nil)
}
let resultDictionary = NSMutableDictionary(contentsOfFile: path)
println("Loaded notes.plist file is --> \(resultDictionary?.description)")
var myDict = NSDictionary(contentsOfFile: path)
if let dict = myDict {
//load values
} else {
println("worning ccould not create dictionary from notes.plist, default values will be used")
}
}

Apple wants you to use URLs instead of paths so they have made it unavailable in Swift 2. If you don't want to use NSURL, you can temporarily cast it to NSString instead:
let path = (DocumentsDirectory as NSString).stringByAppendingPathComponent("notes.plist")

Related

SceneKit Swift3 compiler-error

I'm trying to run animated "DAE" model in SceneKit:
let url = Bundle.main.url(forResource: "art.scnassets/Player(walking)", withExtension: "dae")
let sceneSource = SCNSceneSource(url: url!, options: [SCNSceneSource.LoadingOption.animationImportPolicy: SCNSceneSource.AnimationImportPolicy.playRepeatedly] )
let animationIds: NSArray = sceneSource?.identifiersOfEntries(withClass: CAAnimation)
for eachId in animationIds {
let animation: CAAnimation = (sceneSource?.entryWithIdentifier(eachId as! String, withClass: CAAnimation.self))!
animations.add(animation)
}
character?._walkAnimations = animations
But compiler It throws on the line:
let animationIds: NSArray = sceneSource?.identifiersOfEntries(withClass: CAAnimation)
and writes an error:
Cannot convert value of type '[String]?' to specified type 'NSArray'
Please help me to fix that problem.
Thanks in advance.
Why you are converting [String]? to NSArray and then convert each element to String again, no need of it simply use Swift native Array and wrapped the optional value with if let or guard let.
guard let animationIds = sceneSource?.identifiersOfEntries(withClass: CAAnimation) else {
return
}
for eachId in animationIds {
if let animation = sceneSource?.entryWithIdentifier(eachId, withClass: CAAnimation.self) {
animations.add(animation)
}
}
character?._walkAnimations = animations

Ambiguous reference to member 'insert(_:completionHandler:)' xcode 8 beta 2

Hello with the new beta 2 i got a new problem that i couldn't solve.
var message = MSMessage()
var template = MSMessageTemplateLayout()
viewDidLoad() {
if let filePath2 =
Bundle.main().pathForResource("synth", ofType: "wav") {
let fileUrl = NSURL(string: filePath2)
let URL2 = fileUrl as! URL
template.mediaFileURL = URL2
}
message.layout = template
guard let conversation = activeConversation else {
fatalError("Expected a conversation") } conversation.insert(message,
localizedChangeDescription: nil) { error in
if let error = error {
print(error)
}
}
}
anyone else have the same problem? there's something wrong with conversation
There is no MSConversation method insert(_:localizedChangeDescription:). Look at the docs and see.
Did you mean insert(_:completionHandler:)? If so, just delete the second parameter.

Is it possible to check if a directory is empty in Swift 2.1? [duplicate]

This question already has answers here:
Getting list of files in documents folder
(7 answers)
Closed 7 years ago.
For example I'd like to check if: Users/username/Desktop/folder is empty, or better check if it has files with an .png extension?
I'm really new at all this but if anyone knows please help me :)
Use contentsOfDirectoryAtPath to get the list of all files in a directoly, then filter the array for .png files
let path = "/Users/username/Desktop/folder"
do {
let contents = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(path)
let images = contents.filter { $0.lowercaseString.hasSuffix(".png") }
} catch let error as NSError {
// Directory not exist, no permission, etc.
print(error.localizedDescription)
}
let fileManager = NSFileManager.defaultManager()
let folderPath = "/Users/username/Desktop/folder"
if let contentEnumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath) {
var numFilesWithSuffix = 0
let mySuffix = "png"
while let fileOrFolder = contentEnumerator.nextObject() as? String {
if fileOrFolder.hasSuffix(mySuffix) {
numFilesWithSuffix += 1 // count occurences
}
}
}

How to fix `Ambiguous use of 'subscript'` every time?

I'm using this class that was written in Swift 1.2 and now I want to use it with Swift 2.0.
I get an error: Ambiguous use of 'subscript' # let artist = result["name"] as! String
} else if let jsonArtists = jsonResult["artists"] as? NSDictionary {
if let results:NSArray = jsonArtists["items"] as? NSArray {
dispatch_async(dispatch_get_main_queue(), {
self.searching = false
var suggestionResults: [spotifySearchResult] = []
for result in results {
let artist = result["name"] as! String
var sugresult = spotifySearchResult()
sugresult.artist = artist
if !suggestionResults.contains(sugresult) {
suggestionResults.append(sugresult)
}
}
handler(suggestionResults)
})
}
}
}
I tried different fixes such as let artist = (result["name"] as! String) or let artist = (result["name"] as! String) as! String
But nothing worked.
I know that the question was already post 4 times but, I can't find anyone explaining how to fix it in every case, only case by case.
Can someone explain me how to investigate to fix it? Not just only a fix for my case. I would prefer fix it by myself with your hints!
BTW what does mean subscript? Is subscript the thing between quotation mark? IMHO the error message is a bit vague...
EDIT:
class spotifySearchResult : NSObject {
var artist=""
var track=""
var duration=0
var spotifyURL = NSURL()
var spotifyURI = NSURL()
override func isEqual(theObject: AnyObject?) -> Bool {
if let myObject = theObject as? spotifySearchResult {
return (myObject.artist.uppercaseString == self.artist.uppercaseString && myObject.track.uppercaseString == self.track.uppercaseString)
}
return false
}
}
Subscription means to use the shorter syntax item["key"] for item.objectForKey["key"]
results seems to be an array of dictionaries so I suggest to cast down to a more specific type
if let results = jsonArtists["items"] as? [[String:AnyObject]] {
or even, if all values are guaranteed to be strings
if let results = jsonArtists["items"] as? [[String:String]] {

Updated from Swift 1 to Swift 2

I wrote this code in the previous version of Swift and Xcode and now when I updated xcode to 7.0.1 and updated swift to another version I got a lot of errors. This is something I can't solve and it would be so nice if you could help me. The fat text is the error. The part from >>> to <<< is the part that I need help with so the > and < is not in the real code.
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
>>> var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)! <<<
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
Here, I made your code nicer and safe. This code (in theory) cannot crash whatever happens:
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
guard let
path = NSBundle.mainBundle().pathForResource(file, ofType: "sks"),
sceneData = try? NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe) else {
return nil
}
let archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
guard let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as? GameScene else {
return nil
}
archiver.finishDecoding()
return scene
}
}
If you don't know how the new error handling and guard works, you should check online.
Also if you really want to be fancy, you can use the new defer:
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
guard let
path = NSBundle.mainBundle().pathForResource(file, ofType: "sks"),
sceneData = try? NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe) else {
return nil
}
let archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
defer { archiver.finishDecoding() }
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
return archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as? GameScene
}
}
In swift 2.0 you have to manage errors thrown:
do {
var sceneData = try NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe)
} catch let error as NSError {
// manage error case
}
There is no longer an NSData.init(contentsOfFile:options:error:) constructor. Most Cocoa calls that returned an error this way are now throwing. The new way to do what you've done here is:
var sceneData = try! NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe)
Rather than getting back an optional and then force-unwrapping it, this uses a force-try to do the same thing. In both cases, this will crash if the read fails. Generally a normal try inside of a do/catch is preferred (just like you generally should not force-unwrap optionals).
You need to download the new version of the Swift language book. Enums that consist of bits that should be combined are now represented as sets, not as integer values. Everything is nicely explained in Apple's documentation.
Reading release notes is also very, very useful. At this point in time, Apple doesn't have the slightest scruples to modify the language in a way that breaks existing code. You need to keep up with it yourself.

Resources