FoundationX is a small Swift and Objective-C utility library for everyday Foundation-layer work: safer collection access, Codable helpers, file-size utilities, lightweight logging, app/device metadata, and a handful of Objective-C runtime macros.
- Swift 6.2+
- iOS 13.0+
- macOS 14.0+
Add FoundationX to your package dependencies:
dependencies: [
.package(url: "https://github.com/Lguanghui/FoundationX.git", from: "0.9.0")
]Then add the product to your target:
.target(
name: "YourTarget",
dependencies: ["FoundationX"]
)pod 'FoundationX'- Swift extensions for
Array,String,Optional,Mirror,DispatchQueue,FileManager, andURL. - Codable utilities including
AnyCodable,AnyEncodable,AnyDecodable, default-value property wrappers, andEncodable.dictionary. XLoggerfor lightweight debug logging with timestamps, source context, and custom flags.DeviceManagerfor app version, build number, app name, system version, and macOS device identifiers.- Objective-C helpers for method locking, swizzling, URL file sizes, URL parameter replacement, target checks, weak/strong macros, and safe block execution.
import FoundationX
let numbers = [1, 2, 3]
numbers[safe: 10] // nil
let word = "Foundation"
word[0] // Optional("F")
word[-1] // nil
let value: String? = ""
value.isNilOrEmpty // true
"\n Hello \n".trimWhitespacesAndNewlines() // "Hello"let url = "https://example.com/search"
let result = url.urlAddComponents(from: ["q": "FoundationX"])
// https://example.com/search?q=FoundationXUse default-value wrappers when server payloads may omit fields, return null, or send a compatible-but-different type.
import FoundationX
struct User: Codable, Sendable {
@DefaultEmptyString var name: String
@DefaultTrue var isActive: Bool
@DefaultIntZero var score: Int
@DefaultEmptyArray var tags: [String]
}Bool defaults also accept compatible integer and string values during decoding:
struct Feature: Codable, Sendable {
@DefaultFalse var enabled: Bool
}let payload: [String: AnyCodable] = [
"name": "FoundationX",
"count": 1,
"enabled": true,
"items": [AnyCodable("swift"), AnyCodable("objc")]
]
let raw = payload.rawValue
let data = try JSONEncoder().encode(payload)struct Profile: Encodable {
let name: String
let website: String
}
let dictionary = Profile(
name: "Guanghui Liang",
website: "https://github.com/Lguanghui"
).dictionaryXLogger.log("User signed in", flags: ["auth"])
XLogger.log("Only the message", pure: true)In debug builds, logs include timestamp, file/function context, and line information.
@MainActor
func printDeviceInfo() {
let device = DeviceManager.shared
XLogger.log(
device.appName,
device.appVsersion,
device.buildNumber,
device.systemVersion
)
}On macOS, DeviceManager also exposes macAddresses and serialNumber.
let fileSize = URL(fileURLWithPath: "/path/to/file").fileSize()
let appSize = FileManager.default.applicationSize()On macOS, security-scoped bookmarks can be saved and restored:
url.saveBookmarkData(for: "selected-folder")
let restored = URL.restoreFileAccess(key: "selected-folder")@MainActor
func configureOnce() {
DispatchQueue.once(token: "com.example.configure") {
XLogger.log("Configured once")
}
}FoundationX also ships Objective-C headers through the FoundationXObjc target.
#import <FoundationX/XCommonDefines.h>
#import <FoundationX/XMethodLock.h>
#import <FoundationX/NSObject+Swizzle.h>
#import <FoundationX/NSString+X.h>
#import <FoundationX/NSURL+File.h>Examples:
XWeak(self);
dispatch_main_async_safe(^{
XStrong(self);
XBlock_exec(completion, self);
});
if (NSStringCheck(value)) {
DLog(@"%@", value);
}- (void)loadData {
XMethodLockedReturn();
// Work that should not be re-entered.
XMarcoUnLock();
}Run the Swift package tests:
swift testRun CocoaPods lint:
pod lib lint --allow-warningsFoundationX is available under the MIT license. See LICENSE for details.