Token导航 LogoToken导航TokenDH.com
待分类执行命令github未标认证来源可访问许可证需确认审计通过

axiom-timer-patterns-refAxiom 计时器模式参考

Agent Skill

axiom-timer-patterns-ref 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

2,151

周安装

87

GitHub Stars

868

下载量

675
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

请帮我安装这个 Agent Skill:axiom-timer-patterns-ref(Axiom 计时器模式参考)
来源仓库:https://github.com/charleswiltgen/axiom
仓库路径:skills/axiom-timer-patterns-ref
安装命令:
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-timer-patterns-ref
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

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

skills.shnpx skills
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-timer-patterns-ref

简介

axiom-timer-patterns-ref 列出 Timer 与 DispatchSourceTimer 的完整 API 参数与返回值定义。

  • 适用于查阅 scheduledTimer 方法签名、add(to:modes:) 模式列表及 invalidate 行为说明。
  • 包含 NSTimer 的 retain 风险警告及 GCD timer 的取消与重启机制详解。
  • 决策树建议参见 axiom-timer-patterns,本参考仅提供接口级信息不作最佳实践推荐。
  • 部分高级功能如 timer coalescing 仅在特定系统版本支持,需注意运行时兼容性检查。

SKILL.md

Timer Patterns Reference

Complete API reference for iOS timer mechanisms. For decision trees and crash prevention, see axiom-timer-patterns.


Part 1: Timer API

Timer.scheduledTimer (Block-Based)

// Most common — block-based, auto-added to current RunLoop
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
    self?.updateProgress()
}

Key detail: Added to .default RunLoop mode. Stops during scrolling. See Part 1 RunLoop modes table below.

Timer.scheduledTimer (Selector-Based)

// Objective-C style — RETAINS TARGET (leak risk)
let timer = Timer.scheduledTimer(
    timeInterval: 1.0,
    target: self,       // Timer retains self!
    selector: #selector(update),
    userInfo: nil,
    repeats: true
)

Danger: This API retains target. If self also holds the timer, you have a retain cycle. The block-based API with [weak self] is always safer.

Timer.init (Manual RunLoop Addition)

// Create timer without adding to RunLoop
let timer = Timer(timeInterval: 1.0, repeats: true) { [weak self] _ in
    self?.updateProgress()
}

// Add to specific RunLoop mode
RunLoop.current.add(timer, forMode: .common)  // Survives scrolling

timer.tolerance

timer.tolerance = 0.1  // Allow 100ms flexibility for system coalescing

System batches timers with similar fire dates when tolerance is set. Minimum recommended: 10% of interval. Reduces CPU wakes and energy consumption.

RunLoop Modes

ModeConstantWhen ActiveTimer Fires?
Default.default / RunLoop.Mode.defaultNormal user interactionYes
Tracking.tracking / RunLoop.Mode.trackingScroll/drag gesture activeOnly if added to .common
Common.common / RunLoop.Mode.commonPseudo-mode (default + tracking)Yes (always)

timer.invalidate()

timer.invalidate()  // Stops timer, removes from RunLoop
// Timer is NOT reusable after invalidate — create a new one
timer = nil          // Release reference

Key detail: invalidate() must be called from the same thread that created the timer (usually main thread).

timer.isValid

if timer.isValid {
    // Timer is still active
}

Returns false after invalidate() or after a non-repeating timer fires.

Timer.publish (Combine)

Timer.publish(every: 1.0, tolerance: 0.1, on: .main, in: .common)
    .autoconnect()
    .sink { [weak self] _ in
        self?.updateProgress()
    }
    .store(in: &cancellables)

See Part 3 for full Combine timer details.


Part 2: DispatchSourceTimer API

Creation

// Create timer source on a specific queue
let queue = DispatchQueue(label: "com.app.timer")
let timer = DispatchSource.makeTimerSource(flags: [], queue: queue)

flags: Usually empty ([]). Use .strict for precise timing (disables system coalescing, higher energy cost).

Schedule

// Relative deadline (monotonic clock)
timer.schedule(
    deadline: .now() + 1.0,     // First fire
    repeating: .seconds(1),     // Interval
    leeway: .milliseconds(100)  // Tolerance (like Timer.tolerance)
)

// Wall clock deadline (survives device sleep)
timer.schedule(
    wallDeadline: .now() + 1.0,
    repeating: .seconds(1),
    leeway: .milliseconds(100)
)

deadline vs wallDeadline: deadline uses monotonic clock (pauses when device sleeps). wallDeadline uses wall clock (continues across sleep). Use deadline for most cases.

Event Handler

timer.setEventHandler { [weak self] in
    self?.performWork()
}

Before cancel: Set handler to nil to break retain cycles:

timer.setEventHandler(handler: nil)
timer.cancel()

Lifecycle Methods

timer.activate()   // Start — can only call ONCE (idle → running)
timer.suspend()    // Pause (running → suspended)
timer.resume()     // Unpause (suspended → running)
timer.cancel()     // Stop permanently (must NOT be suspended)

State Machine Lifecycle

                    activate()
        idle ──────────────► running
                               │  ▲
                    suspend()  │  │  resume()
                               ▼  │
                            suspended
                               │
                    resume() + cancel()
                               │
                               ▼
                           cancelled

Critical rules:

  • activate() can only be called once (idle → running)
  • cancel() requires non-suspended state (resume first if suspended)
  • cancelled is terminal — no further operations allowed
  • Dealloc requires non-suspended state (cancel first if needed)

Leeway (Tolerance)

// Leeway values
timer.schedule(deadline: .now(), repeating: 1.0, leeway: .milliseconds(100))
timer.schedule(deadline: .now(), repeating: 1.0, leeway: .seconds(1))
timer.schedule(deadline: .now(), repeating: 1.0, leeway: .never)  // Strict — high energy

Leeway is the DispatchSourceTimer equivalent of Timer.tolerance. Allows system to coalesce timer firings for energy efficiency.

End-to-End Example

Complete DispatchSourceTimer lifecycle in one block:

let queue = DispatchQueue(label: "com.app.polling")
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline: .now() + 1.0, repeating: .seconds(5), leeway: .milliseconds(500))
timer.setEventHandler { [weak self] in
    self?.fetchUpdates()
}
timer.activate()  // idle → running

// Later — pause:
timer.suspend()   // running → suspended

// Later — resume:
timer.resume()    // suspended → running

// Cleanup — MUST resume before cancel if suspended:
timer.setEventHandler(handler: nil)  // Break retain cycles
timer.resume()    // Ensure non-suspended state
timer.cancel()    // running → cancelled (terminal)

For a safe wrapper that prevents all crash patterns, see axiom-timer-patterns Part 4: SafeDispatchTimer.


Part 3: Combine Timer

Timer.publish

import Combine

// Create publisher — RunLoop mode matters here too
let publisher = Timer.publish(
    every: 1.0,          // Interval
    tolerance: 0.1,      // Optional tolerance
    on: .main,           // RunLoop
    in: .common          // Mode — use .common to survive scrolling
)

.autoconnect()

// Starts immediately when first subscriber attaches
Timer.publish(every: 1.0, on: .main, in: .common)
    .autoconnect()
    .sink { date in
        print("Fired at \(date)")
    }
    .store(in: &cancellables)

.connect() (Manual Start)

// Manual control over when timer starts
let timerPublisher = Timer.publish(every: 1.0, on: .main, in: .common)
let cancellable = timerPublisher
    .sink { date in
        print("Fired at \(date)")
    }

// Start later
let connection = timerPublisher.connect()

// Stop
connection.cancel()

Cancellation

// Via AnyCancellable storage — cancelled when Set is cleared or object deallocs
private var cancellables = Set<AnyCancellable>()

// Manual cancellation
cancellables.removeAll()  // Cancels all subscriptions

SwiftUI Integration

class TimerViewModel: ObservableObject {
    @Published var elapsed: Int = 0
    private var cancellables = Set<AnyCancellable>()

    func start() {
        Timer.publish(every: 1.0, tolerance: 0.1, on: .main, in: .common)
            .autoconnect()
            .sink { [weak self] _ in
                self?.elapsed += 1
            }
            .store(in: &cancellables)
    }

    func stop() {
        cancellables.removeAll()
    }
}

Part 4: AsyncTimerSequence (Swift Concurrency)

ContinuousClock.timer

// Monotonic clock — does NOT pause when app suspends
for await _ in ContinuousClock().timer(interval: .seconds(1)) {
    await updateData()
}
// Loop exits when task is cancelled

SuspendingClock.timer

// Suspending clock — pauses when app suspends
for await _ in SuspendingClock().timer(interval: .seconds(1)) {
    await processItem()
}

ContinuousClock vs SuspendingClock:

  • ContinuousClock: Time keeps advancing during app suspension. Use for absolute timing.
  • SuspendingClock: Time pauses when app suspends. Use for "user-perceived" timing.

Task Cancellation

// Timer automatically stops when task is cancelled
let timerTask = Task {
    for await _ in ContinuousClock().timer(interval: .seconds(1)) {
        await fetchLatestData()
    }
}

// Later: cancel the timer
timerTask.cancel()

Background Polling with Structured Concurrency

func startPolling() async {
    do {
        for try await _ in ContinuousClock().timer(interval: .seconds(30)) {
            try Task.checkCancellation()
            let data = try await api.fetchUpdates()
            await MainActor.run { updateUI(with: data) }
        }
    } catch is CancellationError {
        // Clean exit
    } catch {
        // Handle fetch error
    }
}

Part 5: Task.sleep Alternatives

One-Shot Delay

// Simple delay — NOT a timer
try await Task.sleep(for: .seconds(1))

// Deadline-based
try await Task.sleep(until: .now + .seconds(1), clock: .continuous)

When to Use Sleep vs Timer

NeedUse
One-shot delay before actionTask.sleep(for:)
Repeating actionContinuousClock().timer(interval:)
Delay with cancellationTask.sleep(for:) in a Task
Retry with backoffTask.sleep(for:) in a loop

Retry with Exponential Backoff

func fetchWithRetry(maxAttempts: Int = 3) async throws -> Data {
    var delay: Duration = .seconds(1)
    for attempt in 1...maxAttempts {
        do {
            return try await api.fetch()
        } catch where attempt < maxAttempts {
            try await Task.sleep(for: delay)
            delay *= 2  // Exponential backoff
        }
    }
    throw FetchError.maxRetriesExceeded
}

Part 6: LLDB Timer Inspection

Timer (NSTimer) Commands

# Check if timer is still valid
po timer.isValid

# See next fire date
po timer.fireDate

# See timer interval
po timer.timeInterval

# Force RunLoop iteration (may trigger timer)
expression -l objc -- (void)[[NSRunLoop mainRunLoop] run]

DispatchSourceTimer Commands

# Inspect dispatch source
po timer

# Break on dispatch source cancel (all sources)
breakpoint set -n dispatch_source_cancel

# Break on EXC_BAD_INSTRUCTION to catch timer crashes
# (Xcode does this automatically for Swift runtime errors)

# Check if a DispatchSource is cancelled
expression -l objc -- (long)dispatch_source_testcancel((void*)timer)

General Timer Debugging

# List all timers on the main RunLoop
expression -l objc -- (void)CFRunLoopGetMain()

# Break when any Timer fires
breakpoint set -S "scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:"

Part 7: Platform Availability Matrix

APIiOSmacOSwatchOStvOS
Timer2.0+10.0+2.0+9.0+
DispatchSourceTimer8.0+ (GCD)10.10+2.0+9.0+
Timer.publish (Combine)13.0+10.15+6.0+13.0+
AsyncTimerSequence16.0+13.0+9.0+16.0+
Task.sleep13.0+10.15+6.0+13.0+

Related Skills

  • axiom-timer-patterns — Decision trees, crash patterns, SafeDispatchTimer wrapper
  • axiom-energy — Timer tolerance as energy optimization (Pattern 1)
  • axiom-energy-ref — Timer efficiency APIs with WWDC code examples
  • axiom-memory-debugging — Timer as Pattern 1 memory leak

Resources

Skills: axiom-timer-patterns, axiom-energy-ref, axiom-memory-debugging

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

35.15%
按下载量换算237

Claude

29.38%
按下载量换算198

Cursor

20.23%
按下载量换算137

Gemini CLI

9.08%
按下载量换算61

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

执行命令

安装流程涉及命令执行,可能通过 npx skills add https://github.com/charleswiltgen/axiom --skill axiom-timer-patterns-ref 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills