A Swift foundational toolkit for Apple platforms, covering networking, resilient decoding, concurrency safety, and practical development utilities.
pod'RYKit',:git=>'https://github.com/mithyer/RYKit.git',:tag=>'2.1.0'.package(url:"https://github.com/mithyer/RYKit.git", from:"2.1.0")A feature-rich Swift utility library providing common foundational modules for iOS, macOS, and tvOS applications.
- Current Version: 2.1.0
- Supported Platforms: iOS 13.0+, macOS 10.15+, tvOS 13.0+
- Swift Version: 5.0+
RYKit is a Swift foundational toolkit for Apple platforms, focused on providing stable, reusable building blocks for networking, data decoding, concurrency safety, and common utility scenarios.
Core capabilities at a glance:
- HTTP request abstraction: Encapsulates common request flows, response parsing, request strategies, and business error handling to reduce repetitive networking code.
- STOMP real-time messaging: Provides subscription management, reconnect handling, and message distribution for WebSocket-based real-time communication.
- Codable resilience tools: Uses property wrappers such as
@Default,@PreferValue, and@IgnoreValueto make model decoding more fault-tolerant and easier to maintain. - Thread safety primitives: Includes locks and thread-safe property wrappers for protecting shared state in concurrent code.
- Practical utilities and data structures: Offers common extensions, linked lists, queues, timeout task helpers, and version comparison utilities for everyday development.
Additional built-in modules include logging, network reachability monitoring, and associated object helpers. Detailed examples and module-specific usage are provided in the sections below.
Add RYKit to your Package.swift dependencies:
.dependencies([.package(url:"https://github.com/mithyer/RYKit.git", from:"2.1.0")])Then choose the product that fits your use case:
.target(
name:"YourTarget",
dependencies:[.product(name:"RYKit",package:"RYKit")])Available products:
RYKit: Aggregated product that re-exportsRYKitCore,RYKitNetworkHttp, andRYKitNetworkStompRYKitCore: Core utilities and foundational typesRYKitNetworkHttp: HTTP request moduleRYKitNetworkStomp: STOMP messaging module
Import examples:
import RYKit // Recommended: aggregated import
// or
import RYKitCore
import RYKitNetworkHttp
import RYKitNetworkStompAdd to your Podfile:
# Install all modulespod'RYKit'# Or install only needed submodulespod'RYKit/Core'pod'RYKit/NetworkHttp'pod'RYKit/NetworkStomp'Then run:
pod installletrequest=HttpRequest(
session:.shared,
queue:.main,
baseURL:"https://api.example.com",
method:.POST,
path:"/users",
params:.dic(["name":"John"]),
contentType:.applicationJson,
requestStrategy:.cancelIfRequesting,
baseHeaders:["Authorization":"Bearer token"],
businessCodeValidator:nil,
handlers: handlers
)
request.response(User.self){ result inswitch result {case.success(let user):print("User: \(user)")case.failure(let error):print("Error: \(error.localizedDescription)")}}letmanager=StompManager<YourChannel>(userToken:"user123")letsubscription=StompSubInfo(destination:"/topic/messages", identifier:"msg_subscriber", headers:nil)letholder= manager.subscribe(
dataType:Message.self,
subscription: subscription,
receiveMessageStrategy:.all
){ message, headers, raw inprint("Received message: \(message)")}// Log string
LogRecorder.shared.saveLog(content:"App launched", key:"app_lifecycle")
// Log object
structUserAction:Codable{letaction:StringletuserId:Int}letaction=UserAction(action:"login", userId:12345)LogRecorder.shared.saveLog(content: action, key:"user_action")
// Use interval limit (at least 60 seconds)
LogRecorder.shared.saveLog(
content:"Button tapped", key:"button_tap", minIntervalBetweenSameKey:60)
// Get log file path
iflet path =LogRecorder.shared.getCurrentLogFilePath(){print("Log file: \(path)")}Choose the public product that best fits your integration needs:
RYKit: Umbrella product that re-exportsRYKitCore,RYKitNetworkHttp, andRYKitNetworkStompRYKitCore: Foundational utilities for decoding resilience, concurrency safety, lightweight storage, async helpers, logging, and common reusable building blocks.Associatable: Attach associated objects to existing instances.Async: Provide lightweight async execution helpers.Codable: Improve resilient decoding and value conversion.Collections: Offer linked lists, queues, weak maps, and weak sets.Combine: Add practical Combine storage, callback throttling, and debouncing helpers.Extensions: Add convenience helpers for common Foundation and Swift types.KV: Simplify lightweight key-value storage and buffering.Lock: Protect shared state in concurrent code.Log: Persist and inspect runtime logs.Reachability: Monitor shared network reachability state.TimeoutTask: Manage delayed and timeout-based task execution.
RYKitNetworkHttp: HTTP request abstraction and response handlingRYKitNetworkStomp: STOMP-based real-time messaging over WebSocket
In CocoaPods, the public subspecs are
Core,NetworkHttp, andNetworkStomp. In Swift Package Manager, the corresponding public products areRYKitCore,RYKitNetworkHttp, andRYKitNetworkStomp.
finalclassSession:NSObject,Associatable{}letsession=Session()
session.setAssociated("traceId", value:"req-001")lettraceId:String?= session.associated("traceId")letexecutor=AsyncSerialExecutor()tryawait executor.run{
// run serial side effects
}structProfile:Codable{@Default.Empty<String>varname:String@Default.Zero<Int>varage:Int}structPayload:Codable{@PreferValuevarscore:Int?@FromStringValuevaramount:Double?}letqueue=Queue<Int>()
queue.enqueue(1)
queue.enqueue(2)letfirst= queue.dequeue()letmap=WeakMap<String,NSObject>()letretainedObject=NSObject() // keep a strong owner outside the weak map
map.insert(key:"item", retainedObject)letcached=map["item"]varcancellables=Set<AnyCancellable>()Just("value").sink{ value inprint(value)}.store(in:&cancellables)letdebounce=DebounceCallback(interval:.milliseconds(300))
debounce.send{
// execute once after quiet period
}letdefaults=UserDefaults.WithKeyExtended{"app.\($0)"}
defaults.set("dark", forKey:"theme")lettheme= defaults.string(forKey:"theme")letkv=TinyKV(dbName:"app", tableName:"cache")tryawait kv.set(value:"Alice", for:.string("user.name"))letname:String=tryawait kv.getValue(for:.string("user.name"))letbuffered=TinyBufferedKV(dbName:"app", tableName:"buffer")tryawait buffered.set(value:42, for:.string("counter"))tryawait buffered.flush()classStore{@ThreadSafevarcount:Int=0}letstore=Store()
store.$count.lock{ $0 +=1}letlock=ReadWriteLock()varvalue=0letcurrent= lock.read{ value }
lock.write{ value = current +1}lettoken=GlobalReachability.shared.listen{ status inprint("network:", status)}lettask=OnceTimeoutTask<String,Error>(
flag:"load-profile",
executionTimeoutInterval:.seconds(3),
stopTimeoutInterval:.seconds(1),
execute:{ complete incomplete(.success("ok"))},
stopWhenExecuting:{ stopped instopped()})stopWhenExecuting is only consulted when the task is already executing.
letqueue=OnceTimeoutTaskQueue<String,Error>(
executeQueue:.main,
defaultPreemptionStrategy:.waitCurrentCompletion
)letcancellable= queue.taskDidFinish.sink{ event inprint(event.flag, event.doneType)}
queue.addTask(task, priority:10)letpersistentTask=OnceTimeoutTask<String,Error>(
flag:"persistent",
executionTimeoutInterval:nil,
stopTimeoutInterval:nil,
execute:{ _ in
// Complete later, or keep running.
})
queue.addTask(persistentTask, priority:1)MIT License
Ray - GitHub
RYKit 是一个面向 Apple 平台的 Swift 基础能力工具库,重点覆盖网络通信、数据解码容错、并发安全以及常见开发工具场景,帮助你减少重复造轮子。
- 当前版本: 2.1.0
- 支持平台: iOS 13.0+, macOS 10.15+, tvOS 13.0+
- Swift 版本: 5.0+
核心能力包括:
- HTTP 请求封装:统一常见请求流程、响应解析、请求策略与业务错误处理,减少重复网络层代码。
- STOMP 实时通信:提供订阅管理、重连处理和消息分发能力,适合基于 WebSocket 的实时消息场景。
- Codable 容错工具:通过
@Default、@PreferValue、@IgnoreValue等属性包装器,让模型解码更稳健、更易维护。 - 线程安全原语:内置锁与线程安全属性包装器,便于在并发代码中保护共享状态。
- 常用扩展与数据结构:提供常见扩展、链表、队列、超时任务工具和版本比较等高频基础能力。
此外,库中还内置了日志记录、网络可达性监听和关联对象等实用模块。更详细的示例和模块说明请继续查看下方章节。
在你的 Podfile 中添加:
# 安装所有模块pod'RYKit'# 或者只安装需要的子模块pod'RYKit/Core'pod'RYKit/NetworkHttp'pod'RYKit/NetworkStomp'然后运行:
pod installletrequest=HttpRequest(
session:.shared,
queue:.main,
baseURL:"https://api.example.com",
method:.POST,
path:"/users",
params:.dic(["name":"John"]),
contentType:.applicationJson,
requestStrategy:.cancelIfRequesting,
baseHeaders:["Authorization":"Bearer token"],
businessCodeValidator:nil,
handlers: handlers
)
request.response(User.self){ result inswitch result {case.success(let user):print("User: \(user)")case.failure(let error):print("Error: \(error.localizedDescription)")}}letmanager=StompManager<YourChannel>(userToken:"user123")letsubscription=StompSubInfo(destination:"/topic/messages", identifier:"msg_subscriber", headers:nil)letholder= manager.subscribe(
dataType:Message.self,
subscription: subscription,
receiveMessageStrategy:.all
){ message, headers, raw inprint("收到消息: \(message)")}// 记录字符串
LogRecorder.shared.saveLog(content:"应用启动", key:"app_lifecycle")
// 记录对象
structUserAction:Codable{letaction:StringletuserId:Int}letaction=UserAction(action:"登录", userId:12345)LogRecorder.shared.saveLog(content: action, key:"user_action")
// 使用时间间隔限制(至少间隔 60 秒)
LogRecorder.shared.saveLog(
content:"按钮点击", key:"button_tap", minIntervalBetweenSameKey:60)
// 获取日志文件路径
iflet path =LogRecorder.shared.getCurrentLogFilePath(){print("日志文件: \(path)")}根据接入方式选择最适合你的对外产品:
RYKit:聚合产品,统一导出RYKitCore、RYKitNetworkHttp和RYKitNetworkStompRYKitCore:基础工具能力,重点覆盖解码容错、并发安全、轻量存储、异步辅助、日志以及常用可复用组件。Associatable:为现有实例附加关联对象能力。Async:提供轻量级异步执行辅助工具。Codable:提升解码容错与数值转换能力。Collections:提供链表、队列、弱引用映射和弱引用集合等数据结构。Combine:补充实用的 Combine 存储、回调节流与防抖辅助能力。Extensions:为常见 Foundation 和 Swift 类型补充便捷扩展能力。KV:简化轻量级键值存储及缓冲写入。Lock:用于在并发代码中保护共享状态。Log:用于持久化和查看运行日志。Reachability:用于监控共享网络可达性状态。TimeoutTask:用于管理延时任务和超时任务。
RYKitNetworkHttp:HTTP 请求封装与响应处理RYKitNetworkStomp:基于 WebSocket 的 STOMP 实时消息能力
在 CocoaPods 中,对外暴露的 subspec 为
Core、NetworkHttp和NetworkStomp;在 Swift Package Manager 中,对应的公开产品为RYKitCore、RYKitNetworkHttp和RYKitNetworkStomp。
finalclassSession:NSObject,Associatable{}letsession=Session()
session.setAssociated("traceId", value:"req-001")lettraceId:String?= session.associated("traceId")letexecutor=AsyncSerialExecutor()tryawait executor.run{
// 串行执行副作用任务
}structProfile:Codable{@Default.Empty<String>varname:String@Default.Zero<Int>varage:Int}structPayload:Codable{@PreferValuevarscore:Int?@FromStringValuevaramount:Double?}letqueue=Queue<Int>()
queue.enqueue(1)
queue.enqueue(2)letfirst= queue.dequeue()letmap=WeakMap<String,NSObject>()letobject=NSObject()
map.insert(key:"item", object)letcached=map["item"]varcancellables=Set<AnyCancellable>()Just("value").sink{ value inprint(value)}.store(in:&cancellables)letdebounce=DebounceCallback(interval:.milliseconds(300))
debounce.send{
// 静默窗口后触发一次
}letprefs=UserDefaults.WithKeyExtended{"app.\($0)"}
prefs.set("dark", forKey:"theme")lettheme= prefs.string(forKey:"theme")letkv=TinyKV(dbName:"app", tableName:"cache")tryawait kv.set(value:"Alice", for:.string("user.name"))letname:String=tryawait kv.getValue(for:.string("user.name"))letbuffered=TinyBufferedKV(dbName:"app", tableName:"buffer")tryawait buffered.set(value:42, for:.string("counter"))tryawait buffered.flush()classStore{@ThreadSafevarcount:Int=0}letstore=Store()
store.$count.lock{ $0 +=1}varvalue=0letlock=ReadWriteLock()
lock.write{ value +=1}lettoken=GlobalReachability.shared.listen{ status inprint("network:", status)}lettask=OnceTimeoutTask<String,Error>(
flag:"load-profile",
executionTimeoutInterval:.seconds(3),
stopTimeoutInterval:.seconds(1),
execute:{ complete incomplete(.success("ok"))},
stopWhenExecuting:{ stopped instopped()})letqueue=OnceTimeoutTaskQueue<String,Error>(
executeQueue:.main,
defaultPreemptionStrategy:.waitCurrentCompletion
)letcancellable= queue.taskDidFinish.sink{ event inprint(event.flag, event.doneType)}
queue.addTask(task, priority:10)letpersistentTask=OnceTimeoutTask<String,Error>(
flag:"persistent",
executionTimeoutInterval:nil,
stopTimeoutInterval:nil,
execute:{ _ in
// Complete later, or keep running.
})
queue.addTask(persistentTask, priority:1)MIT License
Ray - GitHub