Token导航 LogoToken导航

Agent Skill · 研究检索

ios-networking(iOS networking 搜索)

ios-networking 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

ios-networking 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为接触敏感数据;许可证信息还不明确,第三方扫描有提醒项,按安装量在研究检索类的 73,675 个 Skill 里排第 4,842。

总安装 29,376周安装 1,182GitHub Stars 531下载 9,408核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:ios-networking(iOS networking 搜索)
来源仓库:https://github.com/dpearson2699/swift-ios-skills
仓库路径:skills/ios-networking
安装命令:
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill ios-networking
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill ios-networking

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

适用于 iOS 15+ 的现代 URLSession 网络,使用异步/等待和结构化并发。

涵盖核心异步/等待模式:数据请求、JSON 解码、下载、上传和带有响应验证的流式传输 包括基于协议的 API 客户端架构、用于身份验证的请求中间件、令牌刷新流程以及结构化错误类型的错误处理 提供分页模式、通过 NWPathMonitor 进行网络可达性监控、具有指数退避的重试逻辑以及 URLSession 配置最佳实践 广泛的审查清单和常见错误部分,涵盖取消、钥匙串存储、大文件处理和测试策略

来源仓库内路径:skills/ios-networking

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/dpearson2699/swift-ios-skills --skill ios-netw…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要接触敏感数据,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

ios-networking 怎么安装?

在终端执行 npx skills add https://github.com/dpearson2699/swift-ios-skills --skill ios-networking。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

ios-networking 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

ios-networking 需要什么权限?

权限级别是接触敏感数据。该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

ios-networking 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

ios-networking 用的人多吗?

公开数据是累计安装 29,376 次,近一周安装 1,182 次,下载 9,408 次,GitHub 531 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

ios-networking 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 需要接触敏感数据,装到常用环境前要先评估影响面。
  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 环境里有大量密钥、凭证,不方便给第三方 Skill 读取的人。
  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
ios-networking

iOS networking 搜索 · 本页

29,376531接触敏感数据未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

iOS Networking

Modern networking patterns for iOS 26+ using URLSession with async/await and structured concurrency. All examples target Swift 6.3. No third-party dependencies required -- URLSession covers the vast majority of networking needs.

Contents

Core URLSession async/await

URLSession gained native async/await overloads in iOS 15. These are the only networking APIs to use in new code. Never use completion-handler variants in new projects.

Data Requests

// Basic GET
let (data, response) = try await URLSession.shared.data(from: url)

// With a configured URLRequest
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONEncoder().encode(payload)
request.timeoutInterval = 30
request.cachePolicy = .reloadIgnoringLocalCacheData

let (data, response) = try await URLSession.shared.data(for: request)

Response Validation

Always validate the HTTP status code before decoding. URLSession does not throw for 4xx/5xx responses -- it only throws for transport-level failures.

guard let httpResponse = response as? HTTPURLResponse else {
    throw NetworkError.invalidResponse
}

guard (200..<300).contains(httpResponse.statusCode) else {
    throw NetworkError.httpError(
        statusCode: httpResponse.statusCode,
        data: data
    )
}

JSON Decoding with Codable

func fetch<T: Decodable>(_ type: T.Type, from url: URL) async throws -> T {
    let (data, response) = try await URLSession.shared.data(from: url)

    guard let httpResponse = response as? HTTPURLResponse,
          (200..<300).contains(httpResponse.statusCode) else {
        throw NetworkError.invalidResponse
    }

    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    return try decoder.decode(T.self, from: data)
}

Downloads and Uploads

Use download(for:) for large files -- it streams to disk instead of loading the entire payload into memory.

// Download to a temporary file
let (localURL, response) = try await URLSession.shared.download(for: request)

// Move from temp location before the method returns
let destination = documentsDirectory.appendingPathComponent("file.zip")
try FileManager.default.moveItem(at: localURL, to: destination)
// Upload data
let (data, response) = try await URLSession.shared.upload(for: request, from: bodyData)

// Upload from file
let (data, response) = try await URLSession.shared.upload(for: request, fromFile: fileURL)

Streaming with AsyncBytes

Use bytes(for:) for streaming responses, progress tracking, or line-delimited data (e.g., server-sent events).

let (bytes, response) = try await URLSession.shared.bytes(for: request)

for try await line in bytes.lines {
    // Process each line as it arrives (e.g., SSE stream)
    handleEvent(line)
}

API Client Architecture

Protocol-Based Client

Define a protocol for testability. This lets you swap implementations in tests without mocking URLSession directly.

protocol APIClientProtocol: Sendable {
    func fetch<T: Decodable & Sendable>(
        _ type: T.Type,
        endpoint: Endpoint
    ) async throws -> T

    func send<T: Decodable & Sendable>(
        _ type: T.Type,
        endpoint: Endpoint,
        body: some Encodable & Sendable
    ) async throws -> T
}
struct Endpoint: Sendable {
    let path: String
    var method: String = "GET"
    var queryItems: [URLQueryItem] = []
    var headers: [String: String] = [:]

    func url(relativeTo baseURL: URL) -> URL {
        guard let components = URLComponents(
            url: baseURL.appendingPathComponent(path),
            resolvingAgainstBaseURL: true
        ) else {
            preconditionFailure("Invalid URL components for path: \(path)")
        }
        var mutableComponents = components
        if !queryItems.isEmpty {
            mutableComponents.queryItems = queryItems
        }
        guard let url = mutableComponents.url else {
            preconditionFailure("Failed to construct URL from components")
        }
        return url
    }
}

The client accepts a baseURL, optional custom URLSession, JSONDecoder, and an array of RequestMiddleware interceptors. Each method builds a URLRequest from the endpoint, applies middleware, executes the request, validates the status code, and decodes the result. See references/urlsession-patterns.md for the complete APIClient implementation with convenience methods, request builder, and test setup.

Lightweight Closure-Based Client

For apps using the MV pattern, use closure-based clients for testability and SwiftUI preview support. See references/lightweight-clients.md for the full pattern (struct of async closures, injected via init).

Request Middleware / Interceptors

Middleware transforms requests before they are sent. Use this for authentication, logging, analytics headers, and similar cross-cutting concerns.

protocol RequestMiddleware: Sendable {
    func prepare(_ request: URLRequest) async throws -> URLRequest
}
struct AuthMiddleware: RequestMiddleware {
    let tokenProvider: @Sendable () async throws -> String

    func prepare(_ request: URLRequest) async throws -> URLRequest {
        var request = request
        let token = try await tokenProvider()
        request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        return request
    }
}

Token Refresh Flow

Handle 401 responses by refreshing the token and retrying once.

func fetchWithTokenRefresh<T: Decodable & Sendable>(
    _ type: T.Type,
    endpoint: Endpoint,
    tokenStore: TokenStore
) async throws -> T {
    do {
        return try await fetch(type, endpoint: endpoint)
    } catch NetworkError.httpError(statusCode: 401, _) {
        try await tokenStore.refreshToken()
        return try await fetch(type, endpoint: endpoint)
    }
}

Error Handling

Structured Error Types

enum NetworkError: Error, Sendable {
    case invalidResponse
    case httpError(statusCode: Int, data: Data)
    case decodingFailed(Error)
    case noConnection
    case timedOut
    case cancelled

    /// Map a URLError to a typed NetworkError
    static func from(_ urlError: URLError) -> NetworkError {
        switch urlError.code {
        case .notConnectedToInternet, .networkConnectionLost:
            return .noConnection
        case .timedOut:
            return .timedOut
        case .cancelled:
            return .cancelled
        default:
            return .httpError(statusCode: -1, data: Data())
        }
    }
}

Key URLError Cases

URLError CodeMeaningAction
.notConnectedToInternetDevice offlineShow offline UI, queue for retry
.networkConnectionLostConnection dropped mid-requestRetry with backoff
.timedOutServer did not respond in timeRetry once, then show error
.cancelledTask was cancelledNo action needed; do not show error
.cannotFindHostDNS failureCheck URL, show error
.secureConnectionFailedTLS handshake failedCheck cert pinning, ATS config
.userAuthenticationRequired401 from proxyTrigger auth flow

Decoding Server Error Bodies

struct APIErrorResponse: Decodable, Sendable {
    let code: String
    let message: String
}

func decodeAPIError(from data: Data) -> APIErrorResponse? {
    try? JSONDecoder().decode(APIErrorResponse.self, from: data)
}

// Usage in catch block
catch NetworkError.httpError(let statusCode, let data) {
    if let apiError = decodeAPIError(from: data) {
        showError("Server error: \(apiError.message)")
    } else {
        showError("HTTP \(statusCode)")
    }
}

Retry with Exponential Backoff

Use structured concurrency for retries. Respect task cancellation between attempts. Skip retries for cancellation and 4xx client errors (except 429).

func withRetry<T: Sendable>(
    maxAttempts: Int = 3,
    initialDelay: Duration = .seconds(1),
    operation: @Sendable () async throws -> T
) async throws -> T {
    var lastError: Error?
    for attempt in 0..<maxAttempts {
        do {
            return try await operation()
        } catch {
            lastError = error
            if error is CancellationError { throw error }
            if case NetworkError.httpError(let code, _) = error,
               (400..<500).contains(code), code != 429 { throw error }
            if attempt < maxAttempts - 1 {
                try await Task.sleep(for: initialDelay * Int(pow(2.0, Double(attempt))))
            }
        }
    }
    throw lastError!
}

Pagination

Build cursor-based or offset-based pagination with AsyncSequence. Always check Task.isCancelled between pages. See references/urlsession-patterns.md for complete CursorPaginator and offset-based implementations.

Network Reachability

Use NWPathMonitor from the Network framework — not third-party Reachability libraries. Wrap in AsyncStream for structured concurrency.

import Network

func networkStatusStream() -> AsyncStream<NWPath.Status> {
    AsyncStream { continuation in
        let monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { continuation.yield($0.status) }
        continuation.onTermination = { _ in monitor.cancel() }
        monitor.start(queue: DispatchQueue(label: "NetworkMonitor"))
    }
}

Check path.isExpensive (cellular) and path.isConstrained (Low Data Mode) to adapt behavior (reduce image quality, skip prefetching).

Configuring URLSession

Create a configured session for production code. URLSession.shared is acceptable only for simple, one-off requests.

let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 300
configuration.waitsForConnectivity = true
configuration.requestCachePolicy = .returnCacheDataElseLoad
configuration.httpAdditionalHeaders = [
    "Accept": "application/json",
    "Accept-Language": Locale.preferredLanguages.first ?? "en"
]

let session = URLSession(configuration: configuration)

waitsForConnectivity = true is valuable -- it makes the session wait for a network path instead of failing immediately when offline. Combine with urlSession(_:taskIsWaitingForConnectivity:) delegate callback for UI feedback.

App Transport Security (ATS)

ATS enforces HTTPS for all connections by default. Do not disable it.

Requirements

  • TLS 1.2 or later
  • Forward secrecy cipher suites (ECDHE)
  • SHA-256 or better certificates
  • 2048-bit or greater RSA keys (or 256-bit ECC)

Exception Domains (Last Resort)

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>legacy-api.example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
        </dict>
    </dict>
</dict>

Rules:

  • Never set NSAllowsArbitraryLoads to true in production. App Review will reject it without justification.
  • Exception domains require justification in App Review notes.
  • Use exception domains only for third-party servers you cannot upgrade to HTTPS.
  • NSAllowsLocalNetworking is acceptable for local device communication (Bonjour, IoT).

Common Mistakes

DON'T: Use URLSession.shared with custom configuration needs. DO: Create a configured URLSession with appropriate timeouts, caching, and delegate for production code.

DON'T: Force-unwrap URL(string:) with dynamic input. DO: Use URL(string:) with proper error handling. Force-unwrap is acceptable only for compile-time-constant strings.

DON'T: Decode JSON on the main thread for large payloads. DO: Keep decoding on the calling context of the URLSession call, which is off-main by default. Only hop to @MainActor to update UI state.

DON'T: Ignore cancellation in long-running network tasks. DO: Check Task.isCancelled or call try Task.checkCancellation() in loops (pagination, streaming, retry). Use .task in SwiftUI for automatic cancellation.

DON'T: Use Alamofire or Moya when URLSession async/await handles the need. DO: Use URLSession directly. With async/await, the ergonomic gap that justified third-party libraries no longer exists. Reserve third-party libraries for genuinely missing features (e.g., image caching).

DON'T: Mock URLSession directly in tests. DO: Use URLProtocol subclass for transport-level mocking, or use protocol-based clients that accept a test double.

DON'T: Use data(for:) for large file downloads. DO: Use download(for:) which streams to disk and avoids memory spikes.

DON'T: Fire network requests from body or view initializers. DO: Use .task or .task(id:) to trigger network calls.

DON'T: Hardcode authentication tokens in requests. DO: Inject tokens via middleware so they are centralized and refreshable.

DON'T: Ignore HTTP status codes and decode blindly. DO: Validate status codes before decoding. A 200 with invalid JSON and a 500 with an error body require different handling.

Review Checklist

  • All network calls use async/await (not completion handlers)
  • Error handling covers URLError cases (.notConnectedToInternet,.timedOut,.cancelled)
  • Requests are cancellable (respect Task cancellation via .task modifier or stored Task references)
  • Authentication tokens injected via middleware, not hardcoded
  • Response HTTP status codes validated before decoding
  • Large downloads use download(for:) not data(for:)
  • Network calls happen off @MainActor (only UI updates on main)
  • URLSession configured with appropriate timeouts and caching
  • Retry logic excludes cancellation and 4xx client errors
  • Pagination checks Task.isCancelled between pages
  • Sensitive tokens stored in Keychain (not UserDefaults or plain files)
  • No force-unwrapped URLs from dynamic input
  • Server error responses decoded and surfaced to users
  • Ensure network response model types conform to Sendable; use @MainActor for UI-updating completion paths

References

  • See references/urlsession-patterns.md for complete API client implementation, multipart uploads, download progress, URLProtocol mocking, retry/backoff, certificate pinning, request logging, and pagination implementations.
  • See references/background-websocket.md for background URLSession configuration, background downloads/uploads, WebSocket patterns with structured concurrency, and reconnection strategies.
  • See references/lightweight-clients.md for the lightweight closure-based client pattern (struct of async closures, injected via init for testability and preview support).
  • See references/network-framework.md for Network.framework (NWConnection, NWListener, NWBrowser, NWPathMonitor) and low-level TCP/UDP/WebSocket patterns.
  • See references/file-storage-patterns.md for file system directory selection, FileProtectionType, backup exclusion, and storage pressure handling.

平台分布

Codex

35.89%
按下载量换算3,377

Claude

33.47%
按下载量换算3,149

Cursor

17.26%
按下载量换算1,624

Gemini CLI

9.28%
按下载量换算873

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

接触敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills