Install
$ agentstack add skill-faimin-zdappledevelopskills-objective-c-patterns ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Objective-C Patterns
When to Use
Use this skill when the task involves Objective-C language behavior rather than app-specific product logic:
- Writing or reviewing Objective-C classes, categories, or protocols
- Debugging ownership bugs, leaks, or
EXC_BAD_ACCESS - Choosing between delegates, blocks, target-action, KVO, or runtime hooks
- Evaluating swizzling, forwarding, associated objects, or other dynamic behavior
- Designing Objective-C and Swift boundaries for mixed-language codebases
Start with the router, then open only the references needed for the current question.
Operating Rules
- Prefer simple Objective-C language features before reaching for runtime mutation.
- Nil-check optional blocks before invocation, for example
if (completion) { completion(...); }. - Treat retain cycles as ownership design bugs, not cleanup chores.
- Prefer inheritance, composition, or explicit integration points before any hook or swizzle.
- Use swizzling only when a direct override, wrapper, delegate, or explicit integration point is unavailable.
- Prefix category APIs with a project-specific abbreviation (e.g.
xx_), keep categories lightweight, and move complex stateful logic into real classes. - Prefix private methods with
_. - In getter methods, build the object into a local variable and assign
_ivaras the final statement; seereferences/coding-conventions.md. - Wrap multi-property object initialization in a
({ })statement expression to group creation and configuration; seereferences/coding-conventions.md. - Check
respondsToSelector:before invoking any optional delegate method; seereferences/coding-conventions.md. - Prefer
RACObserveover raw KVO when the project depends onReactiveObjC; seereferences/kvc-kvo-and-associations.md. - Group methods with
#pragma mark -and split very large implementations into focused categories when it improves readability. - Place
- (void)deallocnear the top of@implementationso teardown stays visible during reviews. - Guard uncertain collection indexing before subscripting, and prefer
firstObjectorlastObjectfor boundary access. - Use early returns for nil, invalid state, or failed preconditions instead of nesting conditionals.
- Route bridging questions to the interop reference before proposing mixed-language APIs.
- Keep dynamic behavior local and easy to remove. If a pattern cannot be explained in a few sentences, it is probably the wrong default.
- For crash or leak triage, confirm the symptom first, then narrow to ownership, threading, or runtime mutation before editing code.
Topic Router
Consult the matching reference before giving implementation advice:
| Topic | Reference | | --- | --- | | Blocks, captures, ARC ownership | references/blocks-and-memory.md | | Runtime APIs and swizzling | references/runtime-and-swizzling.md | | Forwarding and dynamic dispatch | references/message-forwarding.md | | KVC, KVO, RAC observation | references/kvc-kvo-and-associations.md | | Coding conventions, getter patterns, delegate guards | references/coding-conventions.md | | Queues, locks, legacy async work | references/threading-and-gcd.md | | Swift bridging boundaries | references/objc-swift-interop.md | | Crash and leak triage | references/diagnostics.md |
Memory Checklist
Use this checklist when ownership or lifecycle is unclear:
- Identify who owns the object now, and who should own it after the change.
- Check whether the relationship is one-shot, repeated, or long-lived.
- Keep delegates
weakunless the platform contract says otherwise. - Treat stored blocks as owners of the objects they capture.
- Break cycles by redesigning the relationship first, not by sprinkling
nilassignments later. - Verify notification, KVO, timer, display link, and dispatch source teardown paths.
- For bridged Swift APIs, confirm nullability and collection element types are explicit.
Retain-Cycle Workflow
- Find the strong ownership loop.
- Name the expected owner for each node in the loop.
- Decide which edge should become non-owning or shorter-lived.
- Replace the pattern with a better boundary:
- delegate for long-lived callbacks
- block for one-shot completion
- injected coordinator or service for shared orchestration
- Use
weakcapture only where the ownership model truly requires it. - Re-check deallocation with a breakpoint, Instruments, or a temporary
dealloclog.
Typical loop shapes:
- controller -> view model -> completion block -> controller
- owner -> timer or display link -> target -> owner
- object A -> object B -> delegate-like property -> object A
- object -> associated object -> block -> object
Quick Diagnostics
| Symptom | Likely cause | Reference | | --- | --- | --- | | Object never deallocates | Block capture or delegate ownership bug | references/blocks-and-memory.md | | EXC_BAD_ACCESS after async callback | Object deallocated earlier than expected | references/diagnostics.md | | Strange behavior after adding category hooks | Swizzle collision or wrong method exchange timing | references/runtime-and-swizzling.md | | Message sent to wrong helper object | Forwarding chain too broad or incomplete | references/message-forwarding.md | | Observer crash on property change | KVO lifecycle mismatch | references/kvc-kvo-and-associations.md | | UI state updates from background queue | Missing main-thread hop | references/threading-and-gcd.md | | Swift sees awkward Objective-C API | Missing nullability or poor naming surface | references/objc-swift-interop.md |
Common Mistakes
- Using associated objects to avoid creating a real subclass or stored property owner.
- Swizzling framework methods without collision guards, original implementation checks, or a rollback plan.
- Assuming
[weak self]is always correct. Weak capture is a tool, not the ownership model. - Using blocks for long-lived relationships that should be delegates or explicit collaborators.
- Invoking optional blocks without checking whether they are non-nil.
- Hiding complex behavior in broad categories instead of a subclass or helper object.
- Using raw subscripting on uncertain arrays or sets when
firstObject,lastObject, or bounds checks would make the contract explicit. - Forwarding selectors broadly enough to hide missing APIs or typos.
- Mixing KVO, manual ivar mutation, and direct setter bypasses without understanding notification behavior.
- Exposing Swift generics, structs, or async-only APIs directly to Objective-C callers that cannot consume them safely.
- Treating intermittent crashes as "ARC bugs" before checking lifetime, queueing, and swizzle interactions.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: faimin
- Source: faimin/ZDAppleDevelopSkills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.