277 lines
9.9 KiB
Swift
277 lines
9.9 KiB
Swift
//
|
|
// URLExtensions.swift
|
|
// EZSwiftExtensions
|
|
//
|
|
// Created by furuyan on 2016/01/11.
|
|
// Modified by mousavian on 2016/05/24.
|
|
// Copyright (c) 2016 Goktug Yilmaz. All rights reserved.
|
|
//
|
|
// swiftlint:disable line_length
|
|
|
|
#if os(iOS) || os(tvOS)
|
|
|
|
import UIKit
|
|
|
|
extension URL {
|
|
/// EZSE: Returns convert query to Dictionary
|
|
public var queryParameters: [String: String]? {
|
|
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), let queryItems = components.queryItems else {
|
|
return nil
|
|
}
|
|
|
|
var parameters = [String: String]()
|
|
for item in queryItems {
|
|
parameters[item.name] = item.value
|
|
}
|
|
|
|
return parameters
|
|
}
|
|
|
|
/// EZSE: Returns remote size of url, don't use it in main thread
|
|
public func remoteSize(_ completionHandler: @escaping ((_ contentLength: Int64) -> Void), timeoutInterval: TimeInterval = 30) {
|
|
let request = NSMutableURLRequest(url: self, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeoutInterval)
|
|
request.httpMethod = "HEAD"
|
|
request.setValue("", forHTTPHeaderField: "Accept-Encoding")
|
|
URLSession.shared.dataTask(with: request as URLRequest) { (_, response, _) in
|
|
let contentLength: Int64 = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
|
|
DispatchQueue.global(qos: .default).async(execute: {
|
|
completionHandler(contentLength)
|
|
})
|
|
}.resume()
|
|
}
|
|
|
|
/// EZSE: Returns server supports resuming or not, don't use it in main thread
|
|
public func supportsResume(_ completionHandler: @escaping ((_ doesSupport: Bool) -> Void), timeoutInterval: TimeInterval = 30) {
|
|
let request = NSMutableURLRequest(url: self, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeoutInterval)
|
|
request.httpMethod = "HEAD"
|
|
request.setValue("bytes=5-10", forHTTPHeaderField: "Range")
|
|
URLSession.shared.dataTask(with: request as URLRequest) { (_, response, _) -> Void in
|
|
let responseCode = (response as? HTTPURLResponse)?.statusCode ?? -1
|
|
DispatchQueue.global(qos: .default).async(execute: {
|
|
completionHandler(responseCode == 206)
|
|
})
|
|
}.resume()
|
|
}
|
|
|
|
/// EZSE: Compare two URLs
|
|
public func isSameWithURL(_ url: URL) -> Bool {
|
|
if self == url {
|
|
return true
|
|
}
|
|
if self.scheme?.lowercased() != url.scheme?.lowercased() {
|
|
return false
|
|
}
|
|
if let host1 = self.host, let host2 = url.host {
|
|
let whost1 = host1.hasPrefix("www.") ? host1 : "www." + host1
|
|
let whost2 = host2.hasPrefix("www.") ? host2 : "www." + host2
|
|
if whost1 != whost2 {
|
|
return false
|
|
}
|
|
}
|
|
let pathdelimiter = CharacterSet(charactersIn: "/")
|
|
if self.path.lowercased().trimmingCharacters(in: pathdelimiter) != url.path.lowercased().trimmingCharacters(in: pathdelimiter) {
|
|
return false
|
|
}
|
|
if (self as NSURL).port != (url as NSURL).port {
|
|
return false
|
|
}
|
|
if self.query?.lowercased() != url.query?.lowercased() {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
/// EZSE: Returns true if given file is a directory
|
|
public var fileIsDirectory: Bool {
|
|
var isdirv: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&isdirv, forKey: URLResourceKey.isDirectoryKey)
|
|
} catch _ {
|
|
}
|
|
return isdirv?.boolValue ?? false
|
|
}
|
|
|
|
/// EZSE: File modification date, nil if file doesn't exist
|
|
public var fileModifiedDate: Date? {
|
|
get {
|
|
var datemodv: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&datemodv, forKey: URLResourceKey.contentModificationDateKey)
|
|
} catch _ {
|
|
}
|
|
return datemodv as? Date
|
|
}
|
|
set {
|
|
do {
|
|
try (self as NSURL).setResourceValue(newValue, forKey: URLResourceKey.contentModificationDateKey)
|
|
} catch _ {
|
|
}
|
|
}
|
|
}
|
|
|
|
/// EZSE: File creation date, nil if file doesn't exist
|
|
public var fileCreationDate: Date? {
|
|
get {
|
|
var datecreatev: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&datecreatev, forKey: URLResourceKey.creationDateKey)
|
|
} catch _ {
|
|
}
|
|
return datecreatev as? Date
|
|
}
|
|
set {
|
|
do {
|
|
try (self as NSURL).setResourceValue(newValue, forKey: URLResourceKey.creationDateKey)
|
|
} catch _ {
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// EZSE: Returns last file access date, nil if file doesn't exist or not yet accessed
|
|
public var fileAccessDate: Date? {
|
|
_ = URLResourceKey.customIconKey
|
|
var dateaccessv: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&dateaccessv, forKey: URLResourceKey.contentAccessDateKey)
|
|
} catch _ {
|
|
}
|
|
return dateaccessv as? Date
|
|
}
|
|
|
|
/// EZSE: Returns file size, -1 if file doesn't exist
|
|
public var fileSize: Int64 {
|
|
var sizev: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&sizev, forKey: URLResourceKey.fileSizeKey)
|
|
} catch _ {
|
|
}
|
|
return sizev?.int64Value ?? -1
|
|
}
|
|
|
|
/// EZSE: File is hidden or not, don't care about files beginning with dot
|
|
public var fileIsHidden: Bool {
|
|
get {
|
|
var ishiddenv: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&ishiddenv, forKey: URLResourceKey.isHiddenKey)
|
|
} catch _ {
|
|
}
|
|
return ishiddenv?.boolValue ?? false
|
|
}
|
|
set {
|
|
do {
|
|
try (self as NSURL).setResourceValue(newValue, forKey: URLResourceKey.isHiddenKey)
|
|
} catch _ {
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/// EZSE: Checks if file is writable
|
|
public var fileIsWritable: Bool {
|
|
var isdirv: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&isdirv, forKey: URLResourceKey.isWritableKey)
|
|
} catch _ {
|
|
}
|
|
return isdirv?.boolValue ?? false
|
|
}
|
|
|
|
#if (OSX)
|
|
@available(OSX 10.10, *)
|
|
internal var fileThumbnailsDictionary: [String: NSImage]? {
|
|
get {
|
|
var thumbsData: AnyObject?
|
|
do {
|
|
try self.getResourceValue(&thumbsData, forKey: NSURLThumbnailDictionaryKey)
|
|
} catch _ {
|
|
}
|
|
return thumbsData as? [String: NSImage]
|
|
}
|
|
set {
|
|
do {
|
|
let dic = NSDictionary(dictionary: newValue ?? [:])
|
|
try self.setResourceValue(dic, forKey: NSURLThumbnailDictionaryKey)
|
|
} catch _ {
|
|
}
|
|
}
|
|
}
|
|
|
|
/// EZSE: File thubmnail saved in system or iCloud in form of 1024pxx1024px
|
|
@available(OSX 10.10, *)
|
|
public var fileThumbnail1024px: NSImage? {
|
|
get {
|
|
return fileThumbnailsDictionary?[NSThumbnail1024x1024SizeKey]
|
|
}
|
|
set {
|
|
assert(newValue == nil || (newValue?.size.height == 1024 && newValue?.size.width == 1024), "Image size set in fileThumbnail1024px is not 1024x1024")
|
|
fileThumbnailsDictionary?[NSThumbnail1024x1024SizeKey] = newValue
|
|
}
|
|
}
|
|
|
|
#else
|
|
@available(iOS 8.0, *)
|
|
internal var fileThumbnailsDictionary: [String: UIImage]? {
|
|
get {
|
|
var thumbsData: AnyObject?
|
|
do {
|
|
try (self as NSURL).getResourceValue(&thumbsData, forKey: URLResourceKey.thumbnailDictionaryKey)
|
|
} catch _ {
|
|
}
|
|
return thumbsData as? [String: UIImage]
|
|
}
|
|
set {
|
|
do {
|
|
let dic = NSDictionary(dictionary: newValue ?? [:])
|
|
try (self as NSURL).setResourceValue(dic, forKey: URLResourceKey.thumbnailDictionaryKey)
|
|
} catch _ {
|
|
}
|
|
}
|
|
}
|
|
|
|
/// EZSE: File thubmnail saved in system or iCloud in form of 1024pxx1024px
|
|
@available(iOS 8.0, *)
|
|
var fileThumbnail1024px: UIImage? {
|
|
get {
|
|
return fileThumbnailsDictionary?[URLThumbnailDictionaryItem.NSThumbnail1024x1024SizeKey.rawValue]
|
|
}
|
|
set {
|
|
assert(newValue == nil || (newValue?.size.height == 1024 && newValue?.size.width == 1024), "Image size set in fileThumbnail1024px is not 1024x1024")
|
|
fileThumbnailsDictionary?[URLThumbnailDictionaryItem.NSThumbnail1024x1024SizeKey.rawValue] = newValue
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/// EZSE: Set SkipBackup attrubute of file or directory in iOS. return current state if no value is set
|
|
public func skipBackupAttributeToItemAtURL(_ skip: Bool? = nil) -> Bool {
|
|
let keys = [URLResourceKey.isDirectoryKey, URLResourceKey.fileSizeKey]
|
|
let enumOpt = FileManager.DirectoryEnumerationOptions()
|
|
if FileManager.default.fileExists(atPath: self.path) {
|
|
if skip != nil {
|
|
if self.fileIsDirectory {
|
|
let filesList = (try? FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: keys, options: enumOpt)) ?? []
|
|
for fileURL in filesList {
|
|
_ = fileURL.skipBackupAttributeToItemAtURL(skip)
|
|
}
|
|
}
|
|
do {
|
|
try (self as NSURL).setResourceValue(NSNumber(value: skip! as Bool), forKey: URLResourceKey.isExcludedFromBackupKey)
|
|
return true
|
|
} catch _ {
|
|
return false
|
|
}
|
|
} else {
|
|
let dict = try? (self as NSURL).resourceValues(forKeys: [URLResourceKey.isExcludedFromBackupKey])
|
|
if let key: AnyObject = dict?[URLResourceKey.isExcludedFromBackupKey] as AnyObject? {
|
|
return key.boolValue
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
#endif
|