Skip to content

Commit 0a5d5c5

Browse files
committed
Release 1.0.0
1 parent 660a330 commit 0a5d5c5

7 files changed

Lines changed: 326 additions & 116 deletions

File tree

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 5.10
1+
// swift-tools-version: 5.9
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription

Package@swift-6.0.swift.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "NetworkConnectivityKit",
8+
platforms: [
9+
.iOS(.v13),
10+
.macOS(.v10_15),
11+
.macCatalyst(.v13),
12+
.watchOS(.v6),
13+
.tvOS(.v13),
14+
.visionOS(.v1),
15+
],
16+
products: [
17+
// Products define the executables and libraries a package produces, making them visible to other packages.
18+
.library(
19+
name: "NetworkConnectivityKit",
20+
targets: ["NetworkConnectivityKit"]
21+
),
22+
],
23+
targets: [
24+
// Targets are the basic building blocks of a package, defining a module or a test suite.
25+
// Targets can depend on other targets in this package and products from dependencies.
26+
.target(
27+
name: "NetworkConnectivityKit"
28+
),
29+
.testTarget(
30+
name: "NetworkConnectivityKitTests",
31+
dependencies: ["NetworkConnectivityKit"]
32+
),
33+
],
34+
swiftLanguageModes: [.v6]
35+
)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// ConnectivityConfiguration.swift
3+
// NetworkConnectivityKit
4+
//
5+
// Created by CodingIran on 2025/3/27.
6+
//
7+
8+
import Foundation
9+
10+
// MARK: - ConnectivityConfiguration
11+
12+
public extension NetworkConnectivityKit {
13+
struct ConnectivityConfiguration: Sendable {
14+
public let urlSession: URLSession
15+
16+
public init(urlSession: URLSession) {
17+
self.urlSession = urlSession
18+
}
19+
20+
public init(urlSessionConfig: URLSessionConfiguration) {
21+
self.init(urlSession: URLSession(configuration: urlSessionConfig))
22+
}
23+
24+
public init(timeout: TimeInterval? = 3,
25+
cachePolicy: ConnectivityConfiguration.CachePolicy = .ignoreCache,
26+
allowsCellularAccess: Bool = true)
27+
{
28+
let config = URLSessionConfiguration.default
29+
config.setTimeout(timeout)
30+
config.setCachePolicy(cachePolicy)
31+
config.setAllowsCellularAccess(allowsCellularAccess)
32+
self.init(urlSessionConfig: config)
33+
}
34+
35+
/// Default configuration for URLSession
36+
/// Using 3 seconds timeout and ignore cache
37+
public static let `default` = ConnectivityConfiguration()
38+
}
39+
}
40+
41+
// MARK: - CachePolicy
42+
43+
public extension NetworkConnectivityKit.ConnectivityConfiguration {
44+
enum CachePolicy {
45+
case ignoreCache
46+
case useCache(policy: URLRequest.CachePolicy, urlCache: URLCache?)
47+
}
48+
}
49+
50+
// MARK: - Method chaining
51+
52+
public extension NetworkConnectivityKit.ConnectivityConfiguration {
53+
func timeout(_ timeout: TimeInterval?) -> Self {
54+
let urlSessionConfig = urlSession.configuration
55+
urlSessionConfig.setTimeout(timeout)
56+
return .init(urlSessionConfig: urlSessionConfig)
57+
}
58+
59+
func cachePolicy(_ cachePolicy: NetworkConnectivityKit.ConnectivityConfiguration.CachePolicy) -> Self {
60+
let urlSessionConfig = urlSession.configuration
61+
urlSessionConfig.setCachePolicy(cachePolicy)
62+
return .init(urlSessionConfig: urlSessionConfig)
63+
}
64+
65+
func ignoreCache() -> Self {
66+
cachePolicy(.ignoreCache)
67+
}
68+
}
69+
70+
private extension URLSessionConfiguration {
71+
func setTimeout(_ timeout: TimeInterval?) {
72+
if let timeout {
73+
timeoutIntervalForRequest = timeout
74+
timeoutIntervalForResource = timeout
75+
} else {
76+
timeoutIntervalForRequest = NetworkConnectivityKit.defaultTimeoutIntervalForRequest
77+
timeoutIntervalForResource = NetworkConnectivityKit.defaultTimeoutIntervalForResource
78+
}
79+
}
80+
81+
func setCachePolicy(_ policy: NetworkConnectivityKit.ConnectivityConfiguration.CachePolicy) {
82+
switch policy {
83+
case .ignoreCache:
84+
requestCachePolicy = .reloadIgnoringCacheData
85+
urlCache = nil
86+
case .useCache(let policy, let urlCache):
87+
requestCachePolicy = policy
88+
self.urlCache = urlCache
89+
}
90+
}
91+
92+
func setAllowsCellularAccess(_ allowsCellularAccess: Bool) {
93+
self.allowsCellularAccess = allowsCellularAccess
94+
}
95+
}
96+
97+
private extension NetworkConnectivityKit {
98+
/// Default timeout interval of URLSession, Apple doc:
99+
/// https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1408259-timeoutintervalforrequest
100+
/// https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1408153-timeoutintervalforresource
101+
static let defaultTimeoutIntervalForRequest: TimeInterval = 60.0
102+
static let defaultTimeoutIntervalForResource: TimeInterval = 7 * 24 * 60 * 60.0
103+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// ConnectivityMethod.swift
3+
// NetworkConnectivityKit
4+
//
5+
// Created by CodingIran on 2025/3/27.
6+
//
7+
8+
import Foundation
9+
10+
// MARK: - ConnectivityMethod
11+
12+
public extension NetworkConnectivityKit {
13+
struct ConnectivityMethod: Sendable {
14+
public let urlRequest: URLRequest
15+
public let validation: ConnectivityValidation
16+
public let configuration: ConnectivityConfiguration
17+
18+
public init(urlRequest: URLRequest, validation: ConnectivityValidation, configuration: ConnectivityConfiguration = .default) {
19+
self.urlRequest = urlRequest
20+
self.validation = validation
21+
self.configuration = configuration
22+
}
23+
24+
public init(url: URL, validation: ConnectivityValidation, configuration: ConnectivityConfiguration = .default) {
25+
self.init(urlRequest: URLRequest(url: url, configuration: configuration), validation: validation, configuration: configuration)
26+
}
27+
28+
public init?(urlString: String, validation: ConnectivityValidation, configuration: ConnectivityConfiguration = .default) {
29+
guard let url = URL(string: urlString) else {
30+
return nil
31+
}
32+
self.init(url: url, validation: validation, configuration: configuration)
33+
}
34+
}
35+
}
36+
37+
// MARK: - Built-in ConnectivityMethod
38+
39+
// refer: https://en.wikipedia.org/wiki/Captive_portal
40+
41+
public extension NetworkConnectivityKit.ConnectivityMethod {
42+
static let appleCaptive = Self(urlString: "http://captive.apple.com", validation: .generate200Validation)
43+
44+
static let appleLibrary = Self(urlString: "http://www.apple.com/library/test/success.html", validation: .generate200Validation)
45+
46+
static let googleGstatic = Self(urlString: "http://www.gstatic.com/generate_204", validation: .generate204Validation)
47+
48+
static let cloudflare = Self(urlString: "http://cp.cloudflare.com/generate_204", validation: .generate204Validation)
49+
50+
static let microsoft = Self(urlString: "http://www.msftconnecttest.com/connecttest.txt", validation: .generate200Validation)
51+
52+
static let vivoWifi = Self(urlString: "http://wifi.vivo.com.cn/generate_204", validation: .generate204Validation)
53+
54+
static let miuiConnect = Self(urlString: "http://connect.rom.miui.com/generate_204", validation: .generate204Validation)
55+
}
56+
57+
// MARK: - Perform Request
58+
59+
extension NetworkConnectivityKit.ConnectivityMethod {
60+
func performRequest() async -> Bool {
61+
do {
62+
let response = try await configuration.urlSession.data(for: urlRequest)
63+
guard let httpResponse = response.1 as? HTTPURLResponse else {
64+
return false
65+
}
66+
return validation.validation(urlRequest, httpResponse, response.0)
67+
} catch {
68+
return false
69+
}
70+
}
71+
}
72+
73+
// MARK: - Hashable & Equatable
74+
75+
extension NetworkConnectivityKit.ConnectivityMethod: Hashable, Equatable {
76+
public func hash(into hasher: inout Hasher) {
77+
hasher.combine(urlRequest)
78+
}
79+
80+
public static func == (lhs: NetworkConnectivityKit.ConnectivityMethod, rhs: NetworkConnectivityKit.ConnectivityMethod) -> Bool {
81+
lhs.urlRequest == rhs.urlRequest
82+
}
83+
}
84+
85+
private extension URLRequest {
86+
init(url: URL, configuration: NetworkConnectivityKit.ConnectivityConfiguration) {
87+
let configuration = configuration.urlSession.configuration
88+
var request = URLRequest(url: url,
89+
cachePolicy: configuration.requestCachePolicy,
90+
timeoutInterval: configuration.timeoutIntervalForRequest)
91+
request.allowsCellularAccess = configuration.allowsCellularAccess
92+
self = request
93+
}
94+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// ConnectivityValidation.swift
3+
// NetworkConnectivityKit
4+
//
5+
// Created by CodingIran on 2025/3/27.
6+
//
7+
8+
import Foundation
9+
10+
// MARK: - ConnectivityValidation
11+
12+
public extension NetworkConnectivityKit {
13+
struct ConnectivityValidation: Sendable {
14+
public typealias Validation = @Sendable (URLRequest, HTTPURLResponse, Data) -> Bool
15+
16+
let validation: Validation
17+
18+
public init(validation: @escaping Validation) {
19+
self.validation = validation
20+
}
21+
22+
public init(statusCode: Int) {
23+
self.init { _, response, _ in
24+
response.statusCode == statusCode
25+
}
26+
}
27+
28+
public static func validation(_ validation: @escaping Validation) -> Self {
29+
ConnectivityValidation(validation: validation)
30+
}
31+
32+
public static let generate204Validation = ConnectivityValidation(statusCode: 204)
33+
34+
public static let generate200Validation = ConnectivityValidation(statusCode: 200)
35+
}
36+
}

0 commit comments

Comments
 (0)