Menu

The skip-foundation framework is available at https://github.com/skiptools/skip-foundation.git, which can be checked out and tested with skip test once Skip is installed.

SkipFoundation

Foundation support for Skip apps.

See what API is currently implemented here.

About

SkipFoundation vends the skip.foundation Kotlin package. It is a reimplementation of Foundation for Kotlin on Android. Its goal is to mirror as much of Foundation as possible, allowing Skip developers to use Foundation API with confidence.

SkipFoundation also implements portions of the CryptoKit API.

Dependencies

SkipFoundation depends on the skip transpiler plugin as well as the SkipLib package.

SkipFoundation is part of the core SkipStack and is not intended to be imported directly. The module is transparently adopted through the translation of import Foundation into import skip.foundation.* by the Skip transpiler.

Android Libraries

  • SkipFoundation includes source code from the UrlEncoderUtil library to implement percent escaping.

Status

SkipFoundation supports many of the Foundation framework’s most common APIs, but there are many more that are not yet ported. See Foundation Support.

When you want to use a Foundation API that has not been implemented, you have options. You can try to find a workaround using only supported API, embed Kotlin code directly as described in the Skip docs, or add support to SkipFoundation. If you choose to enhance SkipFoundation itself, please consider contributing your code back for inclusion in the official release.

Contributing

We welcome contributions to SkipFoundation. The Skip product documentation includes helpful instructions and tips on local Skip library development.

The most pressing need is to implement more of the most-used Foundation APIs. To help fill in unimplemented API in SkipFoundation:

  1. Find unimplemented API.
  2. Write an appropriate Kotlin implementation. See Implementation Strategy below.
  3. Edit the corresponding tests to make sure they are no longer skipped, and that they pass. If there aren’t existing tests, write some. See Tests.
  4. Submit a PR.

Other forms of contributions such as test cases, comments, and documentation are also welcome!

Implementation Strategy

The goal of SkipFoundation is to mirror the Foundation framework for Android. When possible, SkipFoundation types wrap corresponding Kotlin or Java foundation types. When a SkipFoundation type wraps a corresponding Kotlin or Java type, please conform to the skip.lib.KotlinConverting<T> protocol, which means adding a .kotlin() function:

#if SKIP
extension Calendar: KotlinConverting<java.util.Calendar> {
    public override func kotlin(nocopy: Bool = false) -> java.util.Calendar {
        return nocopy ? platformValue : platformValue.clone() as java.util.Calendar
    }
}
#endif

You should also implement a constructor that accepts the equivalent Kotlin or Java object.

Tests

SkipFoundation’s Tests/ folder contains the entire set of official Foundation framework test cases. Through the magic of SkipUnit, this allows us to validate our SkipFoundation API implementations on Android against the same test suite used by the Foundation team on iOS.

It is SkipFoundation’s goal to include - and pass - as much of the official test suite as possible.

Foundation Support

The following table summarizes SkipFoundation’s Foundation API support on Android. Anything not listed here is likely not supported. Note that in your iOS-only code - i.e. code within #if !SKIP blocks - you can use any Foundation API you want.

Support levels:

  • βœ… – Full
  • 🟒 – High
  • 🟑 – Medium
  • 🟠 – Low
SupportAPI
🟑
Bundle
  • static var main: Bundle
  • static var module: Bundle
  • init?(path: String)
  • init?(url: URL)
  • init(for forClass: AnyClass)
  • init()
  • var bundleURL: URL
  • var resourceURL: URL?
  • var bundlePath: String
  • var resourcePath: String?
  • func url(forResource: String? = nil, withExtension: String? = nil, subdirectory: String? = nil, localization: String? = nil) -> URL?
  • func path(forResource: String? = nil, ofType: String? = nil, inDirectory: String? = nil, forLocalization: String? = nil) -> String?
  • var developmentLocalization: String
  • var localizations: [String]
  • func localizedString(forKey key: String, value: String?, table tableName: String?) -> String
  • var localizations: [String]
🟑
Calendar
  • Only .gregorian and .iso8601 identifiers are supported
  • init(identifier: Calendar.Identifier)
  • static var current: Calendar
  • var locale: Locale
  • var timeZone: TimeZone
  • var identifier: Calendar.Identifier
  • var eraSymbols: [String]
  • var monthSymbols: [String]
  • var shortMonthSymbols: [String]
  • var weekdaySymbols: [String]
  • var shortWeekdaySymbols: [String]
  • var amSymbol: String
  • var pmSymbol: String
  • func date(from components: DateComponents) -> Date?
  • func dateComponents(in zone: TimeZone? = nil, from date: Date) -> DateComponents
  • func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents
  • func dateComponents(_ components: Set<Calendar.Component>, from date: Date) -> DateComponents
  • func date(byAdding components: DateComponents, to date: Date, wrappingComponents: Bool = false) -> Date?
  • func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = false) -> Date?
  • func isDateInWeekend(_ date: Date) -> Bool
🟠
CharacterSet
  • Vended character sets are not complete
  • static var whitespaces: CharacterSet
  • static var whitespacesAndNewlines: CharacterSet
  • static var newlines: CharacterSet
  • static var urlHostAllowed: CharacterSet
  • static var urlFragmentAllowed: CharacterSet
  • static var urlPathAllowed: CharacterSet
  • static var urlQueryAllowed: CharacterSet
  • init()
  • func insert(_ character: Unicode.Scalar) -> (inserted: Bool, memberAfterInsert: Unicode.Scalar)
  • func update(with character: Unicode.Scalar) -> Unicode.Scalar?
  • func remove(_ character: Unicode.Scalar) -> Unicode.Scalar?
  • func contains(_ member: Unicode.Scalar) -> Bool
  • func union(_ other: CharacterSet) -> CharacterSet
  • mutating func formUnion(_ other: CharacterSet)
  • func intersection(_ other: CharacterSet) -> CharacterSet
  • mutating func formIntersection(_ other: CharacterSet)
  • func subtracting(_ other: CharacterSet)
  • mutating func subtract(_ other: CharacterSet)
  • func symmetricDifference(_ other: CharacterSet) -> CharacterSet
  • mutating func formSymmetricDifference(_ other: CharacterSet)
  • func isSuperset(of other: CharacterSet) -> Bool
  • func isSubset(of other: CharacterSet) -> Bool
  • func isDisjoint(with other: CharacterSet) -> Bool
  • func isStrictSubset(of other: CharacterSet) -> Bool
  • func isStrictSuperset(of other: CharacterSet) -> Bool
  • var isEmpty: Bool
βœ… CocoaError
βœ… ComparisonResult
🟠
CryptoKit
  • See the CryptoKit topic for details on supported API.
βœ… CustomNSError
🟑
Data
  • Data does not conform to Collection protocols
  • init()
  • init(count: Int)
  • init(capacity: Int)
  • init(_ data: Data)
  • init(_ bytes: [UInt8], length: Int? = nil)
  • init(_ checksum: Digest)
  • init?(base64Encoded: String, options: Data.Base64DecodingOptions = [])
  • init(contentsOfFile filePath: String) throws
  • init(contentsOf url: URL, options: Data.ReadingOptions = [])
  • var count: Int
  • var isEmpty: Bool
  • var bytes: [UInt8]
  • var utf8String: String?
  • func base64EncodedString() -> String
  • func sha256() -> Data
  • func hex() -> String
  • mutating func reserveCapacity(_ minimumCapacity: Int)
  • mutating func append(_ other: Data)
  • mutating func append(contentsOf bytes: [UInt8])
  • mutating func append(contentsOf data: Data)
  • subscript(index: Int) -> UInt8
  • func write(to url: URL, options: Data.WritingOptions = []) throws
🟑
Date
  • Formatting functions not supported with the exception of:
  • func ISO8601Format(_ style: Date.ISO8601FormatStyle = .iso8601) -> String
🟒
DateComponents
  • nanosecond, weekdayOrdinal, quarter, yearForWeekOfYear are not supported
🟑
DateFormatter
  • var dateStyle: DateFormatter.Style
  • var timeStyle: DateFormatter.Style
  • var isLenient: Bool
  • var dateFormat: String
  • func setLocalizedDateFormatFromTemplate(dateFormatTemplate: String)
  • static func dateFormat(fromTemplate: String, options: Int, locale: Locale?) -> String?
  • static func localizedString(from date: Date, dateStyle: DateFormatter.Style, timeStyle: DateFormatter.Style) -> String
  • var timeZone: TimeZone?
  • var locale: Locale?
  • var calendar: Calendar?
  • func date(from string: String) -> Date?
  • func string(from date: Date) -> String
  • func string(for obj: Any?) -> String?
βœ… DateInterval
🟠
Decimal
  • Aliased to java.math.BigDecimal
🟠
DispatchQueue
  • static let main: DispatchQueue
  • func async(execute: () -> Void)
  • func asyncAfter(deadline: DispatchTime, execute: () -> Void)
  • func asyncAfter(wallDeadline: DispatchWallTime, execute: () -> Void)
🟒
FileManager
  • static let `default`: FileManager
  • let temporaryDirectory: URL
  • let currentDirectoryPath: String
  • func createSymbolicLink(at url: URL, withDestinationURL destinationURL: URL) throws
  • func createSymbolicLink(atPath path: String, withDestinationPath destinationPath: String) throws
  • func createDirectory(at url: URL, withIntermediateDirectories: Bool, attributes: [FileAttributeKey : Any]? = nil) throws
  • func createDirectory(atPath path: String, withIntermediateDirectories: Bool, attributes: [FileAttributeKey : Any]? = nil) throws
  • func destinationOfSymbolicLink(atPath path: String) throws
  • func attributesOfItem(atPath path: String) throws -> [FileAttributeKey: Any]
  • func setAttributes(_ attributes: [FileAttributeKey : Any], ofItemAtPath path: String) throws
  • func createFile(atPath path: String, contents: Data? = nil, attributes: [FileAttributeKey : Any]? = nil) -> Bool
  • func copyItem(atPath path: String, toPath: String) throws
  • func copyItem(at url: URL, to: URL) throws
  • func moveItem(atPath path: String, toPath: String) throws
  • func moveItem(at path: URL, to: URL) throws
  • func subpathsOfDirectory(atPath path: String) throws -> [String]
  • func subpaths(atPath path: String) -> [String]?
  • func removeItem(atPath path: String) throws
  • func removeItem(at url: URL) throws
  • func fileExists(atPath path: String) -> Bool
  • func isReadableFile(atPath path: String) -> Bool
  • func isExecutableFile(atPath path: String) -> Bool
  • func isDeletableFile(atPath path: String) -> Bool
  • func isWritableFile(atPath path: String) -> Bool
  • func contentsOfDirectory(at url: URL, includingPropertiesForKeys: [URLResourceKey]?) throws -> [URL]
  • func contentsOfDirectory(atPath path: String) throws -> [String]
  • func url(for directory: FileManager.SearchPathDirectory, in domain: FileManager.SearchPathDomainMask, appropriateFor url: URL?, create shouldCreate: Bool) throws -> URL
βœ… HTTPURLResponse
🟒
IndexPath
  • Cannot assign from an array literal
  • Cannot assign to a range subscript
🟑
IndexSet
  • This is an inefficient implementation using an internal Set
  • init(integersIn range: any RangeExpression<Int>)
  • init(integer: Int)
  • init()
  • func integerGreaterThan(_ integer: Int) -> Int?
  • func integerLessThan(_ integer: Int) -> Int?
  • func integerGreaterThanOrEqualTo(_ integer: Int) -> Int?
  • func integerLessThanOrEqualTo(_ integer: Int) -> Int?
  • func count(in range: any RangeExpression<Int>) -> Int
  • func contains(integersIn range: any RangeExpression<Int>) -> Bool
  • func contains(integersIn indexSet: IntSet) -> Bool
  • func intersects(integersIn range: any RangeExpression<Int>) -> Bool
  • mutating func insert(integersIn range: any RangeExpression<Int>)
  • mutating func remove(integersIn range: any RangeExpression<Int>)
  • func filteredIndexSet(in range: any RangeExpression<Int>, includeInteger: (Int) throws -> Bool) rethrows -> IndexSet
  • func filteredIndexSet(includeInteger: (Int) throws -> Bool) rethrows -> IndexSet
  • Supports the full SetAlgebra protocol
🟑
ISO8601DateFormatter
  • static func string(from date: Date, timeZone: TimeZone) -> String
  • var timeZone: TimeZone?
  • func date(from string: String) -> Date?
  • func string(from date: Date) -> String
  • func string(for obj: Any?) -> String?
🟒
JSONDecoder
  • Snake case key decoding is not supported
🟒
JSONEncoder
  • Snake case key encoding is not supported
βœ… JSONSerialization
βœ… Locale
βœ… LocalizedError
βœ… LocalizedStringResource
βœ… Logger
βœ… Notification
🟑
NotificationCenter
  • static let default: NotificationCenter
  • func addObserver(forName name: Notification.Name?, object: Any?, queue: OperationQueue?, using block: (Notification) -> Void) -> Any
  • func removeObserver(_ observer: Any)
  • func post(_ notification: Notification)
  • func post(name: Notification.Name, object: Any?, userInfo: [AnyHashable: Any]? = nil)
  • func notifications(named: Notification.Name, object: AnyObject? = nil) -> Notifications
  • Also see support for NotificationCenter.publisher in the SkipModel module
βœ… NSError
βœ… NSLock
βœ… NSLocalizedString
βœ… NSRecursiveLock
🟒
Number
  • init(value: Int8)
  • init(value: Int16)
  • init(value: Int32)
  • init(value: Int64)
  • init(value: UInt8)
  • init(value: UInt16)
  • init(value: UInt32)
  • init(value: UInt64)
  • init(value: Float)
  • init(value: Double)
  • init(_ value: Int8)
  • init(_ value: Int16)
  • init(_ value: Int32)
  • init(_ value: Int64)
  • init(_ value: UInt8)
  • init(_ value: UInt16)
  • init(_ value: UInt32)
  • init(_ value: UInt64)
  • init(_ value: Float)
  • init(_ value: Double)
  • var doubleValue: Double
  • var intValue: Int
  • var longValue: Int64
  • var int64Value: Int64
  • var int32Value: Int32
  • var int16Value: Int16
  • var int8Value: Int8
🟒
NumberFormatter
  • The following styles are supported: .none, .decimal, .currency, .percent
  • var numberStyle: NumberFormatter.Style
  • var locale: Locale?
  • var format: String
  • var groupingSize: Int
  • var generatesDecimalNumbers: Bool
  • var alwaysShowsDecimalSeparator: Bool
  • var usesGroupingSeparator: Bool
  • var multiplier: NSNumber?
  • var groupingSeparator: String?
  • var percentSymbol: String?
  • var currencySymbol: String?
  • var zeroSymbol: String?
  • var minusSign: String?
  • var exponentSymbol: String?
  • var negativeInfinitySymbol: String
  • var positiveInfinitySymbol: String
  • var internationalCurrencySymbol: String?
  • var decimalSeparator: String?
  • var currencyCode: String?
  • var currencyDecimalSeparator: String?
  • var notANumberSymbol: String?
  • var positiveSuffix: String?
  • var negativeSuffix: String?
  • var positivePrefix: String?
  • var negativePrefix: String?
  • var maximumFractionDigits: Int
  • var minimumFractionDigits: Int
  • var maximumIntegerDigits: Int
  • var minimumIntegerDigits: Int
  • func string(from number: NSNumber) -> String?
  • func string(from number: Int) -> String?
  • func string(for object: Any?) -> String?
  • func number(from string: String) -> NSNumber?
🟠
OperationQueue
  • static let main: OperationQueue
🟒
OSAllocatedUnfairLock
  • init()
  • init(initialState: State)
  • init(uncheckedState initialState: State)
  • func lock()
  • func unlock()
  • func lockIfAvailable() -> Bool
  • func withLockUnchecked<R>(_ body: (inout State) throws -> R) rethrows -> R
  • func func withLockUnchecked<R>(_ body: () throws -> R) rethrows -> R
  • func withLock<R>(_ body: (inout State) throws -> R) rethrows -> R
  • func withLock<R>(_ body: () throws -> R) rethrows -> R
  • func withLockIfAvailableUnchecked<R>(_ body: (inout State) throws -> R) rethrows -> R?
  • func withLockIfAvailableUnchecked<R>(_ body: () throws -> R) rethrows -> R?
  • func withLockIfAvailable<R>(_ body: @Sendable (inout State) throws -> R) rethrows -> R?
  • func withLockIfAvailable<R>(_ body: () throws -> R) rethrows -> R?
βœ… POSIXError
🟑
ProcessInfo
  • static let processInfo: ProcessInfo
  • var globallyUniqueString: String
  • var systemProperties: [String: String]
  • var environment: [String : String]
  • var processIdentifier: Int32
  • var arguments: [String]
  • var hostName: String
  • var processorCount: Int
  • var operatingSystemVersionString: String
  • var isMacCatalystApp: Bool
  • var isiOSAppOnMac: Bool
🟠
PropertyListSerialization
  • static func propertyList(from: Data, options: PropertyListSerialization.ReadOptions = [], format: Any?) throws -> [String: String]?
  • Ignores any given options and format
🟠
RunLoop
  • static let main: RunLoop
βœ… RecoverableError
🟒
String
  • Core String API is defined in SkipLib. These extensions are defined in SkipFoundation
  • init(data: Data, encoding: StringEncoding)
  • init(bytes: [UInt8], encoding: StringEncoding)
  • init(contentsOf: URL)
  • var capitalized: String
  • var deletingLastPathComponent: String
  • func replacingOccurrences(of search: String, with replacement: String) -> String
  • func components(separatedBy separator: String) -> [String]
  • func trimmingCharacters(in set: CharacterSet) -> String
  • func addingPercentEncoding(withAllowedCharacters: CharacterSet) -> String?
  • var removingPercentEncoding: String?
  • var utf8Data: Data
  • var utf8: [UInt8]
  • var utf16: [UInt8]
  • var utf32: [UInt8]
  • var unicodeScalars: [UInt8]
  • func data(using: StringEncoding, allowLossyConversion: Bool = true) -> Data?
  • func write(to url: URL, atomically useAuxiliaryFile: Bool, encoding enc: StringEncoding) throws
  • func write(toFile path: String, atomically useAuxiliaryFile: Bool, encoding enc: StringEncoding) throws
βœ… StringLocalizationValue
βœ… func strlen(_ string: String) -> Int
βœ… func strncmp(_ str1: String, _ str2: String) -> Int
🟑
Timer
  • init(timeInterval: TimeInterval, repeats: Bool, block: (Timer) -> Void)
  • static func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: (Timer) -> Void) -> Timer
  • var timeInterval: TimeInterval
  • func invalidate()
  • var isValid: Bool
  • var userInfo: Any?
  • Also see support for Timer.publish in the SkipModel module
🟒
TimeZone
  • static var current: TimeZone
  • static var autoupdatingCurrent: TimeZone
  • static var `default`: TimeZone
  • static var system: TimeZone
  • static var local: TimeZone
  • static var gmt: TimeZone
  • init?(identifier: String)
  • init?(abbreviation: String)
  • init?(secondsFromGMT seconds: Int)
  • var identifier: String
  • func abbreviation(for date: Date = Date()) -> String?
  • func secondsFromGMT(for date: Date = Date()) -> Int
  • func isDaylightSavingTime(for date: Date = Date()) -> Bool
  • func daylightSavingTimeOffset(for date: Date = Date()) -> TimeInterval
  • var nextDaylightSavingTimeTransition: Date?
  • func nextDaylightSavingTimeTransition(after date: Date) -> Date?
  • static var knownTimeZoneIdentifiers: [String]
  • static var knownTimeZoneNames: [String]
  • static var abbreviationDictionary: [String : String]
  • func localizedName(for style: NameStyle, locale: Locale?) -> String?
βœ… UnknownNSError
🟒
URL
  • init(_ url: URL)
  • init?(string: String, relativeTo baseURL: URL? = nil)
  • init(fileURLWithPath path: String, isDirectory: Bool? = nil, relativeTo base: URL? = nil)
  • static func currentDirectory() -> URL
  • static var homeDirectory: URL
  • static var temporaryDirectory: URL
  • static var cachesDirectory: URL
  • static var documentsDirectory: URL
  • let baseURL: URL?
  • var scheme: String?
  • var host: String?
  • func host(percentEncoded: Bool = true) -> String?
  • var port: Int?
  • var path: String?
  • func path(percentEncoded: Bool = true) -> String?
  • var hasDirectoryPath: Bool
  • var query: String?
  • func query(percentEncoded: Bool = true) -> String?
  • var fragment: String?
  • func fragment(percentEncoded: Bool = true) -> String?
  • var standardized: URL
  • var standardizedFileURL: URL
  • mutating func standardize()
  • var absoluteURL: URL
  • var absoluteString: String
  • var relativePath: String
  • var relativeString: String
  • var pathComponents: [String]
  • var lastPathComponent: String
  • var pathExtension: String
  • var isFileURL: Bool
  • func appendingPathComponent(_ pathComponent: String) -> URL
  • mutating func appendPathComponent(_ pathComponent: String)
  • func appendingPathComponent(_ pathComponent: String, isDirectory: Bool) -> URL
  • mutating func appendPathComponent(_ pathComponent: String, isDirectory: Bool)
  • func appendingPathExtension(_ pathExtension: String) -> URL
  • mutating func appendPathExtension(_ pathExtension: String)
  • func deletingLastPathComponent() -> URL
  • mutating func deleteLastPathComponent() -> URL
  • func deletingPathExtension() -> URL
  • mutating func deletePathExtension()
  • func resolvingSymlinksInPath() -> URL
  • mutating func resolveSymlinksInPath() -> URL
  • func checkResourceIsReachable() throws -> Bool
βœ… URLError
βœ… URLQueryItem
🟑
URLRequest
  • Many properties are currently ignored by URLSession
  • httpBodyStream is not supported
βœ… URLResponse
🟑
URLSession
  • static let shared: URLSession
  • init(configuration: URLSessionConfiguration, delegate: URLSessionDelegate? = nil, delegateQueue: OperationQueue? = nil)
  • var configuration: URLSessionConfiguration
  • var sessionDescription: String?
  • var delegate: URLSessionDelegate?
  • var delegateQueue: OperationQueue?
  • func data(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)
  • func data(from url: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)
  • func upload(for request: URLRequest, fromFile fileURL: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)
  • func upload(for request: URLRequest, from bodyData: Data, delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse)
  • func bytes(for request: URLRequest, delegate: URLSessionTaskDelegate? = nil) async throws -> (AsyncBytes, URLResponse)
  • func bytes(from url: URL, delegate: URLSessionTaskDelegate? = nil) async throws -> (AsyncBytes, URLResponse)
  • func dataTask(with url: URL, completionHandler: ((Data?, URLResponse?, Error?) -> Void)? = nil) -> URLSessionDataTask
  • func dataTask(with request: URLRequest, completionHandler: ((Data?, URLResponse?, Error?) -> Void)? = nil) -> URLSessionDataTask
  • func uploadTask(with: URLRequest, from: Data?, completionHandler: ((Data?, URLResponse?, Error?) -> Void)? = nil) -> URLSessionUploadTask
  • func uploadTask(with: URLRequest, fromFile: URL, completionHandler: ((Data?, URLResponse?, Error?) -> Void)?) -> URLSessionUploadTask
  • func webSocketTask(with url: URL) -> URLSessionWebSocketTask
  • func webSocketTask(with request: URLRequest) -> URLSessionWebSocketTask
  • func webSocketTask(with url: URL, protocols: [String]) -> URLSessionWebSocketTask
  • func finishTasksAndInvalidate()
  • func getTasksWithCompletionHandler(_ handler: ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void)
  • var tasks: ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask])
  • func getAllTasks(handler: ([URLSessionTask]) -> Void)
  • var allTasks: [URLSessionTask]
  • func invalidateAndCancel()
  • struct AsyncBytes: AsyncSequence
🟑
URLSessionConfiguration
  • Many properties are currently ignored by URLSession
🟒
URLSessionDataTask
  • static let defaultPriority: Float
  • static let lowPriority: Float
  • static let highPriority: Float
  • var taskIdentifier: Int
  • var taskDescription: String?
  • var originalRequest: URLRequest?
  • var delegate: URLSessionTaskDelegate?
  • var state: URLSessionTask.State
  • var error: Error?
  • var priority: Float
  • func suspend()
  • func resume()
  • func cancel()
🟒
URLSessionUploadTask
  • static let defaultPriority: Float
  • static let lowPriority: Float
  • static let highPriority: Float
  • var taskIdentifier: Int
  • var taskDescription: String?
  • var originalRequest: URLRequest?
  • var delegate: URLSessionTaskDelegate?
  • var state: URLSessionTask.State
  • var error: Error?
  • var priority: Float
  • func suspend()
  • func resume()
  • func cancel()
🟒
URLSessionWebSocketTask
  • static let defaultPriority: Float
  • static let lowPriority: Float
  • static let highPriority: Float
  • var taskIdentifier: Int
  • var taskDescription: String?
  • var originalRequest: URLRequest?
  • var delegate: URLSessionTaskDelegate?
  • var state: URLSessionTask.State
  • var error: Error?
  • var priority: Float
  • func suspend()
  • func resume()
  • func cancel()
  • func cancel(with closeCode: CloseCode, reason: Data?)
  • var maximumMessageSize: Int
  • var closeCode: CloseCode
  • var closeReason: Data?
  • func send(_ message: Message) async throws -> Void
  • func receive() async throws -> Message
🟒
UserDefaults
  • static var standard: UserDefaults
  • init(suiteName: String?)
  • func register(defaults registrationDictionary: [String : Any])
  • func set(_ value: Int, forKey defaultName: String)
  • func set(_ value: Boolean, forKey defaultName: String)
  • func set(_ value: Double, forKey defaultName: String)
  • func set(_ value: String, forKey defaultName: String)
  • func set(_ value: Any?, forKey defaultName: String)
  • func removeObject(forKey defaultName: String)
  • func object(forKey defaultName: String) -> Any?
  • func string(forKey defaultName: String) -> String?
  • func double(forKey defaultName: String) -> Double?
  • func integer(forKey defaultName: String) -> Int?
  • func bool(forKey defaultName: String) -> Bool?
  • func url(forKey defaultName: String) -> URL?
  • func data(forKey defaultName: String) -> Data?
  • func dictionaryRepresentation() -> [String : Any]
  • Array and dictionary values are not supported
🟒
UUID
  • init()
  • init?(uuidString: String)
  • static func fromString(uuidString: String) -> UUID?
  • var uuidString: String

Topics

CryptoKit

SkipFoundation vends portions of the CryptoKit framework by delegating to the built-in Java implementations:

  • SHA256
  • SHA256Digest
  • SHA384
  • SHA384Digest
  • SHA512
  • SHA512Digest
  • Insecure.MD5
  • Insecure.MD5Digest
  • Insecure.SHA1
  • Insecure.SHA1Digest
  • HMACMD5
  • HMACSHA1
  • HMACSHA256
  • HMACSHA384
  • HMACSHA512

Each supported algorithm includes the following API:

associatedtype Digest
    
public static func hash(data: Data) -> Digest
public func update(_ data: DataProtocol)
public func finalize() -> Digest

The returned Digest in turn acts as a sequence of UInt8 bytes.

Files

Skip implements much of Foundation.FileManager, which should be the primary interface for interacting with the file system.

The app-specific folder can be accessed like:

// on Android, this is Context.getFilesDir()
let folder = try FileManager.default.url(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask, appropriateFor: nil, create: false)

And to read and write to the cache folders:

// on Android, this is Context.getCachesDir()
let caches = try FileManager.default.url(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask, appropriateFor: nil, create: false)

And the system temporary folder can be accessed with:

let tmpdir = NSTemporaryDirectory()

None of the other FileManager.SearchPathDirectory enumerations are implemented in Skip.

Both Data and String have the ability to read and write to and from URLs and path strings.