Skip to content

Commit 4efb90d

Browse files
committed
refactor: 消除强制解包并统一类型语义
- 将仅作命名空间的结构体改为枚举,防止实例化 - 将约束属性改为可选并在激活时 compactMap - 重构 STHTTPSession 生命周期,支持惰性重建并修复循环引用 - 为父类 IUO 重写属性添加 swiftlint 豁免 - 调整属性 getter/setter 顺序与冗余 rawValue
1 parent 2f5595f commit 4efb90d

21 files changed

Lines changed: 187 additions & 132 deletions

‎Sources/STBaseView/STBaseView.swift‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -639,10 +639,10 @@ open class STSection: UIView {
639639
}
640640
private let stackView: UIStackView
641641
// 持有 stackView 的 4 条边约束引用,便于改 inset 时直接改 constant,避免约束泄漏
642-
private var topConstraint: NSLayoutConstraint!
643-
private var leadingConstraint: NSLayoutConstraint!
644-
private var trailingConstraint: NSLayoutConstraint!
645-
private var bottomConstraint: NSLayoutConstraint!
642+
private var topConstraint: NSLayoutConstraint?
643+
private var leadingConstraint: NSLayoutConstraint?
644+
private var trailingConstraint: NSLayoutConstraint?
645+
private var bottomConstraint: NSLayoutConstraint?
646646

647647
public init(inset: UIEdgeInsets = .zero, spacing: CGFloat = 0) {
648648
self.inset = inset
@@ -673,7 +673,7 @@ open class STSection: UIView {
673673
self.leadingConstraint = self.stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: self.inset.left)
674674
self.trailingConstraint = self.stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -self.inset.right)
675675
self.bottomConstraint = self.stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -self.inset.bottom)
676-
NSLayoutConstraint.activate([self.topConstraint, self.leadingConstraint, self.trailingConstraint, self.bottomConstraint])
676+
NSLayoutConstraint.activate([self.topConstraint, self.leadingConstraint, self.trailingConstraint, self.bottomConstraint].compactMap { $0 })
677677
}
678678

679679
/// Add multiple views (arranged) to this section (chainable)

‎Sources/STHUD/STAlertController.swift‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public struct STAlertActionItem {
4646
}
4747

4848
// MARK: - 布局常量
49-
private struct STAlertLayoutConstant {
49+
private enum STAlertLayoutConstant {
5050
static let alertWidth: CGFloat = 270
5151
static let buttonHeight: CGFloat = 44
5252
static let separatorHeight: CGFloat = 0.5
@@ -91,7 +91,7 @@ public struct STAlertInfo {
9191
open class STAlertController: UIViewController {
9292

9393
private var isPresented: Bool = false
94-
private var newConstraint: NSLayoutConstraint!
94+
private var newConstraint: NSLayoutConstraint?
9595
private var backgroundColor = UIColor.white
9696
private var alertInfo = STAlertInfo()
9797
private var actionItems: [STAlertActionItem] = []
@@ -240,14 +240,14 @@ open class STAlertController: UIViewController {
240240
NSLayoutConstraint(item: self.alertView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0),
241241
NSLayoutConstraint(item: self.alertView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: STAlertLayoutConstant.alertWidth),
242242
self.newConstraint
243-
])
243+
].compactMap { $0 })
244244
} else {
245245
self.view.addConstraints([
246246
NSLayoutConstraint(item: self.alertView, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0),
247247
NSLayoutConstraint(item: self.alertView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: 0),
248248
NSLayoutConstraint(item: self.alertView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: STAlertLayoutConstant.alertWidth),
249249
self.newConstraint
250-
])
250+
].compactMap { $0 })
251251
}
252252

253253
if self.alertInfo.title.text != "" && self.alertInfo.message.text != "" {
@@ -421,9 +421,9 @@ open class STAlertController: UIViewController {
421421
}
422422
self.view.layoutIfNeeded()
423423
if self.alertInfo.message.text != "" {
424-
self.newConstraint.constant = self.messageLabel.frame.maxY + 54
424+
self.newConstraint?.constant = self.messageLabel.frame.maxY + 54
425425
} else if self.alertInfo.title.text != "" {
426-
self.newConstraint.constant = self.titleLabel.frame.maxY + 54
426+
self.newConstraint?.constant = self.titleLabel.frame.maxY + 54
427427
}
428428
UIView.animate(withDuration: 0.3) {
429429
self.view.layoutIfNeeded()

‎Sources/STMedia/STImage.swift‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ public enum STImageError: LocalizedError {
2020
}
2121

2222
public enum STImageFormat: String, CaseIterable {
23-
case png = "png"
24-
case gif = "gif"
25-
case jpeg = "jpeg"
26-
case tiff = "tiff"
27-
case webp = "webp"
28-
case heic = "heic"
29-
case heif = "heif"
30-
case undefined = "undefined"
23+
case png
24+
case gif
25+
case jpeg
26+
case tiff
27+
case webp
28+
case heic
29+
case heif
30+
case undefined
3131

3232
public var mimeType: String { return "image/\(rawValue)" }
3333
public var fileExtension: String { return rawValue }

‎Sources/STNetwork/STHTTPSession.swift‎

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
import Network
1111
import UIKit
1212

13-
public final class STParameterEncoder {
13+
public enum STParameterEncoder {
1414

1515
public enum EncodingType {
1616
case url
@@ -126,7 +126,11 @@ open class STHTTPSession: NSObject {
126126
public let interceptor: STInterceptor?
127127
public let eventMonitor: STCompositeEventMonitor
128128

129-
private var urlSession: URLSession!
129+
private let urlSessionConfiguration: URLSessionConfiguration
130+
/// 底层 URLSession。init 中立即创建,避免 deinit 触发 lazy 初始化时把正在析构的
131+
/// self 注册为新 session 的 delegate(生命周期逃逸)。使用 Optional 存储:
132+
/// st_invalidate() 后置 nil,下次请求经 session 访问器惰性重建。
133+
private var urlSession: URLSession?
130134
private let delegateQueue: OperationQueue
131135
private let stateLock = NSLock()
132136
private var requestsByTaskID: [Int: STRequest] = [:]
@@ -156,6 +160,7 @@ open class STHTTPSession: NSObject {
156160
eventMonitors: [STEventMonitor] = [],
157161
sslPinningConfig: STSSLPinningConfig = STSSLPinningConfig(enabled: false)
158162
) {
163+
self.urlSessionConfiguration = configuration
159164
self.defaultRequestConfig = defaultRequestConfig
160165
self.defaultRequestHeaders = defaultRequestHeaders
161166
self.interceptor = interceptor
@@ -177,11 +182,35 @@ open class STHTTPSession: NSObject {
177182
self.delegateQueue = queue
178183

179184
super.init()
180-
self.urlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: self.delegateQueue)
185+
self.urlSession = URLSession(configuration: self.urlSessionConfiguration, delegate: self, delegateQueue: self.delegateQueue)
181186
}
182187

183188
deinit {
184-
self.urlSession.invalidateAndCancel()
189+
// 直接读取 Optional 存储,避免析构期触发 session 访问器的惰性重建。
190+
self.urlSession?.invalidateAndCancel()
191+
}
192+
193+
/// 返回当前可用的 URLSession;若已被 st_invalidate() 销毁则重建。
194+
/// 读取/创建/赋值与 st_invalidate() 经 stateLock 互斥,避免并发首次重建
195+
/// 产生多个 session,或取得刚被置空的旧 session。
196+
private var session: URLSession {
197+
self.withStateLock {
198+
if let session = self.urlSession {
199+
return session
200+
}
201+
let session = URLSession(configuration: self.urlSessionConfiguration, delegate: self, delegateQueue: self.delegateQueue)
202+
self.urlSession = session
203+
return session
204+
}
205+
}
206+
207+
/// 显式销毁底层 URLSession 并释放其对 self 的 delegate 强引用,
208+
/// 打破 self ⇄ session 循环引用。调用后再次发起请求会重建一个新的 session。
209+
public func st_invalidate() {
210+
self.withStateLock {
211+
self.urlSession?.invalidateAndCancel()
212+
self.urlSession = nil
213+
}
185214
}
186215

187216
@discardableResult
@@ -370,7 +399,7 @@ open class STHTTPSession: NSObject {
370399
}
371400
request.urlRequest = adapted
372401

373-
let task = self.urlSession.dataTask(with: adapted)
402+
let task = self.session.dataTask(with: adapted)
374403
request.task = task
375404
let restart: () -> Void = { [weak self] in
376405
Task { await self?.executeData(request, initial: initial, interceptor: interceptor, config: config) }
@@ -428,7 +457,7 @@ open class STHTTPSession: NSObject {
428457
}
429458
request.urlRequest = adapted
430459

431-
let task = self.urlSession.uploadTask(with: adapted, from: body)
460+
let task = self.session.uploadTask(with: adapted, from: body)
432461
request.task = task
433462
let restart: () -> Void = { [weak self] in
434463
Task { await self?.executeUpload(request, initial: initial, body: body, interceptor: interceptor, config: config) }
@@ -483,9 +512,9 @@ open class STHTTPSession: NSObject {
483512

484513
let task: URLSessionDownloadTask
485514
if let resumeData = resumeData {
486-
task = self.urlSession.downloadTask(withResumeData: resumeData)
515+
task = self.session.downloadTask(withResumeData: resumeData)
487516
} else {
488-
task = self.urlSession.downloadTask(with: adapted)
517+
task = self.session.downloadTask(with: adapted)
489518
}
490519
request.task = task
491520
let restart: () -> Void = { [weak self, weak request] in
@@ -542,7 +571,7 @@ open class STHTTPSession: NSObject {
542571
}
543572
request.urlRequest = adapted
544573

545-
let task = self.urlSession.dataTask(with: adapted)
574+
let task = self.session.dataTask(with: adapted)
546575
request.task = task
547576
let restart: () -> Void = { [weak self, weak request] in
548577
Task {

‎Sources/STSecurity/STEncrypt.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ public extension Data {
280280
}
281281

282282
// MARK: - 加密工具类
283-
public struct STEncryptionUtils {
283+
public enum STEncryptionUtils {
284284

285285
/// 生成随机密钥
286286
/// - Parameter length: 密钥长度(字节)

‎Sources/STSecurity/STKeychainHelper.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public enum STKeychainError: Error, LocalizedError {
114114
}
115115
}
116116

117-
public class STKeychainHelper {
117+
public enum STKeychainHelper {
118118

119119
private static let service = Bundle.main.bundleIdentifier ?? "com.STBaseProject.app"
120120
private static let accessGroup: String? = nil // 可以设置为 App Group 标识符

‎Sources/STSecurity/STSecurityModels.swift‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ public enum STSecurityIssue: String, Codable {
138138

139139
// MARK: - 安全严重程度
140140
public enum STSecuritySeverity: String, Codable {
141-
case low = "low"
142-
case medium = "medium"
143-
case high = "high"
144-
case critical = "critical"
141+
case low
142+
case medium
143+
case high
144+
case critical
145145
}

‎Sources/STTimer/STTimeProfiler.swift‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
import Foundation
99
import QuartzCore
1010

11-
public class STTimeProfiler {
11+
public enum STTimeProfiler {
1212

1313
private static let lock = NSLock()
1414
private static var startTimes: [String: CFTimeInterval] = [:]
1515

1616
/// 开始计时
1717
/// - Parameter tag: 计时任务标识,用于区分不同的计时任务
18-
public class func st_start(tag: String = "default") {
18+
public static func st_start(tag: String = "default") {
1919
self.lock.lock()
2020
defer { self.lock.unlock() }
2121
let startTime = CACurrentMediaTime()
@@ -27,7 +27,7 @@ public class STTimeProfiler {
2727
/// - Parameters:
2828
/// - tag: 计时任务标识,默认为 "default"
2929
/// - message: 自定义消息,会显示在耗时信息中
30-
public class func st_end(tag: String = "default", message: String? = nil) {
30+
public static func st_end(tag: String = "default", message: String? = nil) {
3131
self.lock.lock()
3232
defer { self.lock.unlock() }
3333
guard let startTime = self.startTimes[tag] else {
@@ -45,7 +45,7 @@ public class STTimeProfiler {
4545
/// 获取当前耗时(不结束计时)
4646
/// - Parameter tag: 计时任务标识,默认为 "default"
4747
/// - Returns: 耗时(秒),如果未找到开始时间则返回 nil
48-
public class func st_elapsedTime(tag: String = "default") -> Double? {
48+
public static func st_elapsedTime(tag: String = "default") -> Double? {
4949
self.lock.lock()
5050
defer { self.lock.unlock() }
5151
guard let startTime = self.startTimes[tag] else {
@@ -59,7 +59,7 @@ public class STTimeProfiler {
5959
/// - Parameters:
6060
/// - tag: 计时任务标识,默认为 "default"
6161
/// - message: 自定义消息
62-
public class func st_logElapsed(tag: String = "default", message: String? = nil) {
62+
public static func st_logElapsed(tag: String = "default", message: String? = nil) {
6363
guard let elapsed = self.st_elapsedTime(tag: tag) else {
6464
STLog("⚠️ [\(tag)] 未找到对应的开始时间,请先调用 st_start(tag:)")
6565
return
@@ -76,7 +76,7 @@ public class STTimeProfiler {
7676
/// - block: 要执行的代码块
7777
/// - Returns: 代码块的返回值
7878
@discardableResult
79-
public class func st_measure<T>(tag: String = "default", message: String? = nil, block: () throws -> T) rethrows -> T {
79+
public static func st_measure<T>(tag: String = "default", message: String? = nil, block: () throws -> T) rethrows -> T {
8080
self.st_start(tag: tag)
8181
defer {
8282
self.st_end(tag: tag, message: message)
@@ -89,7 +89,7 @@ public class STTimeProfiler {
8989
/// - tag: 计时任务标识,默认为 "default"
9090
/// - message: 自定义消息
9191
/// - block: 要执行的异步代码块
92-
public class func st_measureAsync(tag: String = "default", message: String? = nil, block: @escaping () async throws -> Void) {
92+
public static func st_measureAsync(tag: String = "default", message: String? = nil, block: @escaping () async throws -> Void) {
9393
self.st_start(tag: tag)
9494
Task {
9595
do {
@@ -102,7 +102,7 @@ public class STTimeProfiler {
102102
}
103103

104104
/// 清除所有计时任务
105-
public class func st_clearAll() {
105+
public static func st_clearAll() {
106106
self.lock.lock()
107107
defer { self.lock.unlock() }
108108
self.startTimes.removeAll()
@@ -111,7 +111,7 @@ public class STTimeProfiler {
111111

112112
/// 清除指定标签的计时任务
113113
/// - Parameter tag: 计时任务标识
114-
public class func st_clear(tag: String) {
114+
public static func st_clear(tag: String) {
115115
self.lock.lock()
116116
defer { self.lock.unlock() }
117117
self.startTimes.removeValue(forKey: tag)
@@ -121,7 +121,7 @@ public class STTimeProfiler {
121121
/// 格式化耗时显示
122122
/// - Parameter duration: 耗时(秒)
123123
/// - Returns: 格式化后的字符串
124-
private class func st_formatDuration(_ duration: Double) -> String {
124+
private static func st_formatDuration(_ duration: Double) -> String {
125125
if duration < 0.001 {
126126
// 小于1毫秒,显示微秒
127127
return String(format: "%.2f μs", duration * 1_000_000)

‎Sources/STTools/STData.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ public extension String {
401401

402402
}
403403

404-
public struct STDataUtils {
404+
public enum STDataUtils {
405405
/// 创建随机数据
406406
/// - Parameter length: 数据长度
407407
/// - Returns: 随机数据

‎Sources/STTools/STDeviceInfo.swift‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Network
1010
import SystemConfiguration
1111
import UIKit
1212

13-
public struct STDeviceInfo {
13+
public enum STDeviceInfo {
1414

1515
public struct STAppInfo: Sendable {
1616
public let version: String
@@ -592,24 +592,24 @@ public enum STDeviceType: String, Sendable {
592592
}
593593

594594
public enum STNetworkConnectionType: String, Sendable {
595-
case wifi = "wifi"
596-
case cellular = "cellular"
597-
case ethernet = "ethernet"
598-
case unknown = "unknown"
595+
case wifi
596+
case cellular
597+
case ethernet
598+
case unknown
599599
}
600600

601601
public enum STDevicePerformanceLevel: String, Sendable {
602-
case low = "low"
603-
case medium = "medium"
604-
case high = "high"
602+
case low
603+
case medium
604+
case high
605605
}
606606

607607
public enum STThermalState: String, Sendable {
608-
case nominal = "nominal"
609-
case fair = "fair"
610-
case serious = "serious"
611-
case critical = "critical"
612-
case unknown = "unknown"
608+
case nominal
609+
case fair
610+
case serious
611+
case critical
612+
case unknown
613613

614614
fileprivate init(_ state: ProcessInfo.ThermalState) {
615615
switch state {

0 commit comments

Comments
 (0)