Difference between SDWebImageDownloader and SDWebImageManager.shared.imageLoader in SDWebImage5.x? - swift

I want to know what is the difference between using SDWebImageDownLoader and SDWebImageManager.shared.imageLoader. Recently I update SdWebImage from 4.x to 5.14.3, and I found that SDWebImage.shared().imageDownloader has been renamed to SDWebImageManager.shared.imageLoader, and it's type change from SDWebImageDownloader to SDImageLoader.
In this case, I want to know if I get the same effect using func SDImageLoader.requestImage instead of using func SDWebImageDownloader.downloadImage. I was wondering these two line below works the same:
let urls = "https://somerandomUrl"
SDWebImageManager.shared.imageLoader.requestImage(with: url, context: nil, progress: nil)
SDWebImageDownloader.shared.downloadImage(with: url, progress: nil)

Related

UIDocumentPicker function for under IOS.14

I'm beginner in Swift. I have made a document picker at my task. But I see the documentation it was deprecated to used open var documentPickerMode: UIDocumentPickerMode { get }. While the project in my task runs with minimum deployment of IOS13.
Is there a solution for this feature that can be used on IOS14 and below? Or is this normal, where users need to update IOS?. Forgive me for my ignorance, as I'm new to swift world.
If you look at the docs:
https://developer.apple.com/documentation/uikit/uidocumentpickerviewcontroller
...you'll see the list of four initializers introduced in iOS 14. Each one configures the picker for one specific type of task. There is no need for a "mode" because you cannot not know how your picker is configured, because you configured it. That is the modern architecture.
At the bottom of the same page you will see the three deprecated initializers from iOS 13 and before, each of which takes a "mode" as a parameter. That is what you must use if you insist upon supporting iOS 13, even though they are deprecated in later systems. And that's fine. "Deprecated" means discouraged and superseded; it does not mean illegal. What you're getting is just a warning, not (as your title wrongly stated) an error.
just try this one code
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
guard url.startAccessingSecurityScopedResource() else {
return
}
defer { url.stopAccessingSecurityScopedResource() }
var error: NSError? = nil
NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { (url) in
let _ : [URLResourceKey] = [.nameKey, .isDirectoryKey]
let documentFileData = NSData(contentsOf: (url)) as Data?
pickImageCallback?(nil, url.lastPathComponent, documentFileData)
}
}

How do I get image file name from UIImagePickerController

I am trying to get file name from PHAsset reference provided by UIImagePickerController,How do I retrieve the image file name when choose from library and take photo with camera?
I am using Xcode 11.4 and Swift 5.
Given, you already have the PHAsset object, PHAssetResource is what you need to work retrieve the filename.
let assetResources = PHAssetResource.assetResources(for: asset)
This will return you an array of PHAssetResource instances, among which one of them is the current image.
Inspecting the PHAssetResource instances on the debugger, you can see it contains multiple files. This may include adjustment data, represented by .plist, and one or more photos.
To get the file that is currently accessible, what you need to look for is a key isCurrent. Apple hasn't exposed this key as a variable for PHAssetResource, however, they don't take any effort hiding the value. And I assume, querying this value doesn't result in an app rejection.
You can query this value directly, or can do it more cleanly by extending PHAssetResource.
extension PHAssetResource {
var isCurrent: Bool? {
self.value(forKey: "isCurrent") as? Bool
}
}
Now, you can ask the [PHAssetResource], for the first item that isCurrent as well as a photo or video.
let resourceTypes: [PHAssetResourceType] = [.photo, .video, .audio, .fullSizePhoto]
let currentAssetResource = assetResources.first(
where: { $0.isCurrent == true && resourceTypes.contains($0.type)
})
And, finally for the filename.
let fileName = currentAssetResource?.originalFilename
Note
PhotoKit expects the developer to work with the abstract asset resource, and not to deal with the underlying files or data. The usage of isCurrent seems to be allowed. However, the value can be altered or removed with an iOS update. Do it only if you have a strong use-case for extracting the filename.
There are two approaches:
You can retrieve the URL of the temporary file that UIImagePickerController creates for you using info[.imageURL]. If you only need, for example, the extension of the asset, this is sufficient.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
// url of temporary file provided by image picker
if let url = info[.imageURL] as? URL {
print("temp URL", url) // file:///private/var/mobile/Containers/Data/Application/.../tmp/FAC0D82B-85A9-4C7A-B69C-58BB53F74CDC.jpeg
}
dismiss(animated: true)
}
But the filename, itself, bears no relationship to the original asset.
You can retrieve the original asset URL from the Photos framework. We used to be able to use PHImageManager, call requestImageDataForAsset, and then use "PHImageFileURLKey" in the resulting info dictionary, but that doesn’t work anymore.
But as suggested elsewhere, you can asset.requestContentEditingInput, and that includes the URL of the asset:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
// url of the original asset
if let asset = info[.phAsset] as? PHAsset {
asset.requestContentEditingInput(with: nil) { input, info in
if let fileURL = input?.fullSizeImageURL {
print("original URL", fileURL) // file:///var/mobile/Media/DCIM/100APPLE/IMG_0135.HEIC
}
}
}
dismiss(animated: true)
}
If you do this, you obviously need to request permissions for the photos library, notably:
if PHPhotoLibrary.authorizationStatus() == .notDetermined {
PHPhotoLibrary.requestAuthorization { granted in
print(granted)
}
}
And you need to supply a NSPhotoLibraryUsageDescription usage string in your Info.plist.
Personally, it feels wrong to request content editing input when you don’t really need to edit, but AFAIK, that’s the only way to get the original asset name nowadays. (There’s got to be a better way: If you browse the PHAsset in the debugger, the asset name is actually buried in there, but not exposed ... maybe they did that to avoid confusion with the HEIC extension.)
Bottom line, it just depends upon what you need the name for. If you just need the path for the temporary file, then use .imageURL. If you need information about the original asset, use .phAsset and the Photos/PhotoKit framework.

Swift 4+: Issues copying a String to Clipboard using NSPasteboard

I had this all working in Swift 3 and earlier but with Swift 4 no matter what variation I use this code will instead output text as a URL. If I put in "This is my sample text" the output after pasting the clipboard will be "This%20is%20my%20sample%20text". I have tried KuTTypeFileURL but that doesn't appear to make any difference either. What am I missing here? I have seen posts and discussions about how Apple is changing Pboards and other issues with sandboxing but I can't seem to figure this out at all.
original code what was working in swift 3 and earlier
private func copyToClipBoard(textToCopy: String) {
let pasteBoard = NSPasteboard.general()
pasteBoard.clearContents()
pasteBoard.setString(textToCopy, forType: NSStringPboardType)
}
This gives an error of
'NSStringPboardType' is unavailable in Swift: use 'PasteboardType.string'
After searching online I came across these posts that describe the same issue and the workaround was to use the kuTTypeUrl as String
Found here stackoverflow.com/questions/44537356/… and here forums.developer.apple.com/thread/79144
When I try it this way it simply outputs as a URL when I just need a String.
#IBOutlet weak var nameTextField: NSTextField!
#IBAction func nameCopy(_ sender: Any) {
copyToClipBoard(textToCopy: nameTextField.stringValue)
}
let NSStringPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String)
private func copyToClipBoard(textToCopy: String) {
let pasteBoard = NSPasteboard.general
pasteBoard.clearContents()
pasteBoard.setString(textToCopy, forType: NSStringPboardType)
}
You are pasting an URL because you created a PasteboardType kUTTypeURL.
The solution is much simpler, there is a predefined string type
private func copyToClipBoard(textToCopy: String) {
let pasteBoard = NSPasteboard.general
pasteBoard.clearContents()
pasteBoard.setString(textToCopy, forType: .string)
}
The note in the documentation
Apps that adopt App Sandbox cannot access files identified using the string pasteboard type. Instead, use an NSURL object, a bookmark, or a filename pasteboard type.
is related to files (aka string paths), not to regular strings
I just ran into a similar issue. My code looked like this:
NSPasteboard.general.setString("Hello World", forType: .string)
Unfortunately, this didn't work. But I figured there is a bug that if you don't store the NSPasteboard.general into a variable, the object created as part of the general computed property gets deinitialized before the setString change is propagated to the system.
So if you tried doing this in one line like me, just split it up to two instead, which worked for me:
let pasteboard = NSPasteboard.general
pasteboard.setString("Hello World", forType: .string)
I reported this bug via Feedback Assistant to Apple (FB9988062).
UPDATE:
Apple answered my bug report, stating that you need to call declareTypes before setting a value, like so:
NSPasteboard.general.declareTypes([.string], owner: nil)

How to determine file URL from DVTSourceTextView

I’m writing a plugin to Xcode 7. I have the DVTSourceTextView and can manipulate it just fine. One of the things I want to find is which file is related to this. Unfortunately, DVTSourceTextView doesn’t appear to offer that information - or if it does, it is buried in a way I fail to see.
I’m sure it is rather trivial, I’m just missing something.
Okay, this was easier than I thought it was. I was approaching it from a different (although almost correct) way.
class func currentEditorView() -> (NSURL?, NSView?) {
let currentWindowController = NSApp.keyWindow?.windowController
guard currentWindowController!.className == "IDEWorkspaceWindowController" else { return (nil, nil) }
let filename = currentWindowController!.valueForKey("editorArea")!.valueForKey("lastActiveEditorContext")!.valueForKey("originalRequestedDocumentURL")
let editor = currentWindowController!.valueForKey("editorArea")!.valueForKey("lastActiveEditorContext")!.valueForKey("editor")!.valueForKey("textView")
return (filename as? NSURL, editor as? NSView)
}
This gives me both the filename as an NSURL as well as the DVTSourceTextView as an NSView without the need of including private headers. Spiffy.
Now not only do I know the name of the file I’m editing, but I can also determine if it is a swift, objc, c or c++ file! THAT is coolness!

Does not conform to protocol AFURLResponseSerialization

Im kinda stuck in a problem with Alamofire & AlamofireImage.
The main idea is to make a custom imageResponseSerializer, becouse my pics are coded in base64, so i need to uncode it first, so can't use default imageResponseSerializer. To do this i read manual and find that i could use a custom-response-serializer , so i just tried a provided example with XML serialization (pasted it to my class).
Then im trying to provide it as an imageResponseSerializer like this way:
func configureCellWithURLString(URLString: String, placeholderImage: UIImage) {
let size = imageView.frame.size
imageView.imageResponseSerializer = Request.XMLResponseSerializer()
imageView.af_setImageWithURL(
NSURL(string: URLString)!,
placeholderImage: placeholderImage,
filter: AspectScaledToFillSizeWithRoundedCornersFilter(size: size, radius: 20.0),
imageTransition: .CrossDissolve(0.2)
)
}
But getting the error on this line:
imageView.imageResponseSerializer = Request.XMLResponseSerializer()
Value of type ResponseSerializer<ONOXMLDocument, NSError> does not conform to AFURLResponseSerialization in assignment
And now can't figure out why it is not conform or i just doing it wrong ?