swift
✓Verified·Scanned 2/18/2026
This skill provides Swift coding guidance covering optionals, memory management, concurrency, Codable, and common runtime pitfalls. No security-relevant behaviors detected.
from clawhub.ai·v2c74d4c·4.2 KB·0 installs
Scanned from 1.0.0 at 2c74d4c · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/swift
Swift Gotchas
Optional Traps
- Force unwrap
!crashes on nil — useguard letorif letinstead - Implicitly unwrapped optionals
String!still crash if nil — only use for IBOutlets - Optional chaining returns optional —
user?.name?.countisInt?notInt ??default value evaluates eagerly — use?? { expensive() }()for lazy- Comparing optionals:
nil < 1is true — unexpected sort behavior
Memory Leaks
- Closures capturing
selfstrongly create retain cycles — use[weak self]in escaping closures - Delegates must be
weak— strong delegate = object never deallocates - Timer retains target strongly — invalidate in
deinitwon't work, useweakorblockAPI - NotificationCenter observers retained until removed — remove in
deinitor useaddObserver(forName:using:)with token - Nested closures: each level needs own
[weak self]— inner closure captures outer's strong ref
Concurrency Traps
async letstarts immediately — not when youawait- Actor isolation: accessing actor property from outside requires
await— even for reads @MainActordoesn't guarantee immediate main thread — it's queuedTask.detachedloses actor context — inherits nothing from caller- Sendable conformance: mutable class properties violate thread safety silently until runtime crash
Value vs Reference
- Structs copied on assign, classes shared — mutation affects only copy or all references
- Large structs copying is expensive — profile before assuming copy-on-write saves you
- Mutating struct in collection requires reassignment —
array[0].mutate()doesn't work, extract, mutate, replace inoutparameters: changes visible only after function returns — not during
Codable Pitfalls
- Missing key throws by default — use
decodeIfPresentor custom init - Type mismatch throws —
"123"won't decode toIntautomatically - Enum raw value must match exactly —
"status": "ACTIVE"fails for.activecase - Nested containers need manual
CodingKeysat each level - Custom
init(from:)must decode ALL properties or provide defaults
Protocol Gotchas
- Protocol extensions don't override — static dispatch ignores subclass implementation
Selfrequirement prevents use as type —protocol Animalvsany Animal@objcrequired for optional protocol methods- Associated types can't use with
anywithout constraints — use generics or type erasure - Witness matching is exact —
func foo(_: Int)doesn't satisfyfunc foo(_: some Numeric)
String Traps
- Characters can be multiple Unicode scalars — emoji count isn't byte count
- Subscripting is O(n) — use indices, not integers
String.Indexfrom one string invalid on another — even if contents match- Empty string is not nil — check
.isEmpty, not== nil contains()is case-sensitive — uselocalizedCaseInsensitiveContainsfor user search
Collection Edge Cases
firstandlastare optional — empty collection returns nilremoveFirst()crashes on empty,popFirst()returns nilindex(of:)is O(n) — for frequent lookups use Set or Dictionary- Mutating while iterating crashes — copy first or use
reversed()for removal ArraySliceindices don't start at 0 — usestartIndex
Error Handling
try?swallows error details — use only when error type doesn't mattertry!crashes on any error — never use in production paths- Throwing from closure requires explicit
throwsin closure type rethrowsonly works if closure throws — prevents unnecessarytryat callsite- Error must conform to
Error— plainthrow "message"doesn't compile
Build and Runtime
- Generic code bloat — specialized for each type, increases binary size
@inlinableexposes implementation to other modules — ABI stability consideration- Dynamic casting
as?can be slow — prefer static typing - Reflection with
Mirroris slow — not for hot paths print()builds strings even in release — remove or use os_log