I try to get the date (creation/last modified) of a file. The name of it I've already got from NSFileManager. Then I try to access attributes:
var attr : NSDictionary? =
NSFileManager.defaultManager().attributesOfItemAtPath(file.absoluteString!, error: nil)
But I always get nil for "attr". "file" is set:
file NSURL "file:///Users/dirk/Desktop/Bildschirmfoto%202015-02-01%20um%2014.07.41.png" 0x00006000000b3ec0
Any idea? What's wrong?
I got it by myself! :-) The prefix "file://" was the reason. If I remove it, it works.
Just for info.
Related
I am having difficulty grabbing a fileURL in a DropDelegate in SwiftUI, when dragging a file from my desktop into my app.
I am using the async loadItem call on NSItemProvider which returns an NSSecureCoding. I assumed that I could cast the result to an NSURL but it always fails.
let url = try await (urlProvider
.loadItem(forTypeIdentifier: UTType.url.identifier) as? NSURL
If I try to force the cast I get the following error:
Could not cast value of type 'Foundation.__NSSwiftData' to 'NSURL'.
I am successfully using the same call and casting to an NSDictionary elsewhere in my code.
This is in Xcode 13.4, Swift 5.
I have read access to user selected files in my sandbox capabilities.
Can anyone help point out what I am doing wrong?
Thank you.
I had to cast to Data and then construct the URL from that:
if let data = try await urlProvider
.loadItem(forTypeIdentifier: UTType.fileURL.identifier) as? Data {
url = URL(dataRepresentation: data, relativeTo: nil) }
I have been working on an audio application where I can seek to a specific point in an ExtAudioFile and load a specific number of frames that represent a particular length (time) of playback into an AVAudioPCMBuffer and start playing it. If the user selects a checkbox during playback of that audio segment, the buffer is then fed the remaining contents of the audio file so it will play to the end.
However, I have hit a roadblock. I have found older examples of code that loads these resources. They way they're declaring the calls is not working in Swift 5 for me. I am getting errors. Specifically:
import Cocoa
import AVFoundation
import AudioToolbox
do {
var err:OSStatus = noErr
let url = URL(fileURLWithPath: "./audio files/myAudioFile.mp3")
let track = try AVAudioFile(forReading: url)
var trackRef = ExtAudioFileRef?
err = try ExtAudioFileOpenURL(url as CFURL, trackRef)
} catch {
print(error)
}
The first error I am getting is for trackRef. The editor is flagging this line as "Expected member name or constructor call after type name." But the example I was following only had the property declared as shown in the code above.
The next line err = try ExtAudioFileOpenURL(orl as CFURL, trackRef) has error "Cannot convert value of type 'ExtAudioFileRef?.Type' (aka 'Optional.Type') to expected argument type 'UnsafeMutablePointer<ExtAudioFileRef?>' (aka 'UnsafeMutablePointer<Optional>')."
The editor is suggesting I change trackRef declaration to ver trackRef = ExtAudioFileRef?() or var trackRef = ExtAudioFileRef?.self but neither of those are any help because if I try using the first suggestion I then get "Cannot invoke initializer for type 'ExtAudioFileRef?' with no arguments" and a gray note showing "1. Overloads for 'ExtAudioFileRef?' exist with these partially matching parameter lists: (Wrapped), (from: Decoder), (nilLiteral: ())." But the error for err = ExtAudioFileOpenURL(url as CFURL, trackRef) goes away. If I try using the second suggestion let trackRef = ExtAudioFileRef?.self there is no error on that line, but then I get an error on the err = ExtAudioFileOpenURL(url as CFURL, trackRef) line that reads "Cannot convert value of type 'ExtAudioFileRef?.Type' (aka 'Optional.Type') to expected argument type 'UnsafeMutablePointer<ExtAudioFileRef?>' (aka 'UnsafeMutablePointer<Optional>')"
I am not versed enough to know what these errors mean as I don't know what UnsafeMutablePointer is. I was just following the example code to try and achieve what I want to do. Unfortunately I've not been able to get any of the audio tools in Swift to do what I want to do and this is the next rabbit hole for me.
Thanks for any help.
I finally found some recent code that uses this in later Swift.
I do not need to initialize the trackRef property, which was what was causing the errors to appear in the declarations. I also didn't need the try method.
Here's the proper way to declare it:
var trackRef: ExtAudioFileRef?
err = ExtAudioFileOpenURL(url as CFURL, &trackRef)
Now for the next rabbit hole...
I was previously using RxSwift and I decided I did not want to use it anymore and was able to convert everything over to Bond which I am much more familiar with. Since the new changes though to Bond v5, I cannot seem to figure out how to observe values in UserDefaults. The following code ends up giving me a fatal error.
userDefaults.reactive
.keyPath(LocationManager.HomeLocationKey, ofType: String.self, context: .immediateOnMain)
.map(self.initLocation(from:))
.bind(to: self.homeLocation)
userDefaults is a reference to UserDefaults.standard and LocationManager.HomeLocationKey is a string. I am providing the initLocation function below as I know it will be asked for. Below that function I will post the error that I am receiving after the app starts up.
func initLocation(from string: String?) -> Location?
{
guard let dataString = string
else { log.warning("Location data did not exist, returning nil"); return nil }
let json = JSON.parse(dataString)
return Location(from: json)
}
Error:
fatal error: Could not convert nil to String. Maybe `dynamic(keyPath:ofExpectedType:)` method might be of help?): file /Users/sam/Documents/iOS Apps/Drizzle/Pods/Bond/Sources/Shared/NSObject+KVO.swift, line 58
It might not be obvious, but if the observed value can be nil, the ofType argument must be an Optional type. In your case, that would be:
userDefaults.reactive
.keyPath(LocationManager.HomeLocationKey, ofType: Optional<String>.self, context: .immediateOnMain)
...
I'm new to Swift and Xcode. Do I need to change how the path is accessed in some way using NSString or NSUrl? Problems with file path notation (file://)?
#IBAction func buttonPressed(sender: AnyObject) {
let filepath1 = "/Applications/Con.app/Contents/Resources/iTunes.icns"
let filepath2 = "~/Desktop/".stringByExpandingTildeInPath
let fileManager = NSFileManager.defaultManager()
var error: NSError?
fileManager.copyItemAtPath(filepath1, toPath: filepath2, error: nil)
button1.title = "Icon changed"
}
You seem to be using an obsolete version of Swift, but your problem is you're not specifying a filename in your destination path. Change "~/Desktop/" to "~/Desktop/iTunes.icns", for instance. copyItemAtPath(_:toPath:) will by default fail if the destination file already exists, and "~/Desktop/" obviously does.
place the error that you defined before the copyItemAtPath in the parameter list and see what the error coming back is. ie-....error:&error) instead of error:nil)
Also add the file name to the destination string.
I'm new to coding and picked up some open source project to get the idea.
I'm getting the error:
Ambiguous reference to member 'subscript'
in the code below:
let pictures = ( selectedRestaurant["Pictures"] as! NSArray ) // Error
let picture = ( pictures[zoomedPhotoIndex] as! NSDictionary )
let pictureURL = picture["url"] as! String
let imageURL = NSURL(string: pictureURL)
let urlRequest = NSURLRequest(URL: imageURL!)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) {
response, data, error in
if error == nil && data != nil {
self.imageView.image = UIImage(data: data!)
self.imageView.contentMode = UIViewContentMode.ScaleAspectFit
}
}
Just specify explicitly what is the type of pictures:
So instead of:
let pictures = selectedRestaurant["Pictures"] as! NSArray
Write:
let pictures: NSArray = selectedRestaurant["Pictures"] as! NSArray
For me the answer was to specifically state the type of array I was casting to:
if let foo = dictionary["bar"] as? [String]
It means that "Pictures" is not a valid subscript. It looks like you are creating a constant named pictures and you are trying to assign it a value of selectedRestaraunt["Pictures"] and then trying to cast it as an NSArray. If selectedrestaraunt is already an array, then what goes in the [] brackets after selectedRestaraunt should be an integer value which will refer to an index in the selectedRestaraunt array. Obviosuly "Pictures" is not an integer, it is a string.
If you are trying to access an array within an array. Meaning that Pictures is an array stored within the selectedRestarauntarray then you can access it by using selectedRestaraunt[index of Pictures array] where [index of pictures array] is an integer which is equal to the index number in which the Picutres array resides within the selectedRestaraunt array
I managed to get this error in a somewhat weird way. I had code like this:
cell.textLabel = anArrayOfStrings[indexPath.item].uppercased()
And I was stumped as to why it couldn't figure out that this was an array, even though I very clearly declared its type. I broke the line in two and finally got a helpful error message:
let name = anArrayOfStrings[indexPath.item].uppercased()
cell.textLabel = name
I was trying to assign a String to a UILabel, but somehow the point at which the type inference engine failed was at the subscript.
So my advice to anyone stumped by this is to try to break up your statement into bite-sized chunks that the Swift type inference engine can more easily digest.
As Eric and Eugene mentioned in their comments it is impossible to review the issue you are having without knowing the selectedRestaurant type. That is after all why you are getting the compiler ambiguity error.
I have to respectfully disagree with MikeG though. The problem is not one of a valid subscript. You'd be getting that kind of error, if for example you had a selectedRestaurant type of [NSNumber:AnyObject], where clearly String is no longer valid since the dictionary key could only be an NSNumber.