RORK LABJP
PUBLISH — Rork Max handles code signing and provisioning so you can submit to the App Store in two clicksSIMULATOR — A browser streaming simulator feels close to real hardware, and a QR code installs to your device without TestFlightMAX — Rork Max generates native Swift apps, powered by Claude Code and Claude Opus 4.6NATIVE — Rork Max reaches Xcode-class territory: AR/LiDAR, Metal 3D, widgets, Live Activities, HealthKit, and Core MLFUNDING — Rork raised $15M to power the next generation of App Store entrepreneursPRICE — Plans start free, paid tiers from $25/month, and Rork Max at $200/monthPUBLISH — Rork Max handles code signing and provisioning so you can submit to the App Store in two clicksSIMULATOR — A browser streaming simulator feels close to real hardware, and a QR code installs to your device without TestFlightMAX — Rork Max generates native Swift apps, powered by Claude Code and Claude Opus 4.6NATIVE — Rork Max reaches Xcode-class territory: AR/LiDAR, Metal 3D, widgets, Live Activities, HealthKit, and Core MLFUNDING — Rork raised $15M to power the next generation of App Store entrepreneursPRICE — Plans start free, paid tiers from $25/month, and Rork Max at $200/month
Articles/Dev Tools
Dev Tools/2026-07-08Advanced

Working Around Rork Max's 20-Geofence Wall with Dynamic Re-registration

In a native Swift app generated by Rork Max, geofences you registered quietly stop firing past a certain count — and it's almost always iOS's silent limit of 20 monitored regions per app. Here's a dynamic re-registration design that keeps only the nearest 20 live, plus a Swift implementation you can drop in.

Rork Max217Core Locationgeofencingregion monitoringSwift43iOS106

Premium Article

I was adding a small location-aware feature to one of my indie apps: when you arrive at a place, show a quiet image chosen for that place. Nothing more. To power it, I registered about 30 spots across the country as geofences.

On my own iPhone, the handful of spots near me fired correctly. But the spots later in the list stayed silent even when I physically walked to them. No error in the logs. The CLLocationManager code Rork Max generated looked perfectly intact.

The cause wasn't the code — it was an iOS ceiling. Region monitoring can watch at most 20 regions per app. Anything past the 20th is ignored with no exception and no warning. This article covers a design built around that ceiling — keeping only the nearest 20 registered at any moment — and the implementation you add on top of what Rork Max gives you.

Why the 21st Region Goes Quiet

CLLocationManager region monitoring (startMonitoring(for:)) carries a limit Apple states plainly: a single app can monitor at most 20 regions. Try to register past that, and startMonitoring(for:) neither crashes nor returns false. The excess simply never joins monitoredRegions, and didEnterRegion never fires for it.

So the symptom looks like this:

Registration orderJoins monitoredRegions?didEnterRegion fires?
1st–20thYesYes
21st onwardNo (silently)No

Tell Rork Max "I want geofence notifications for 10 places," and it writes a straightforward for loop passing each one to startMonitoring(for:). At 10, nothing breaks. Only as your registration count grows — without anyone flagging the ceiling — does this surface as a low-reproducibility bug where "only the later ones don't respond."

For me, the part that ate the most time was that nothing errors. Core Location doesn't treat exceeding the limit as a failure, so even with print statements you only ever see "registered" logs. The first thing to check is manager.monitoredRegions.count right after registration. If it caps at 20 instead of climbing past it, the cause is confirmed as the limit, not a bug.

for region in regions {
    manager.startMonitoring(for: region)
}
// Always reconcile what you asked for against what's actually monitored
print("requested: \(regions.count) / actually monitoring: \(manager.monitoredRegions.count)")

The moment you see requested: 30 / actually monitoring: 20, the question changes from "why won't it fire" to "which 20 should I pick."

Don't Remove the Limit — Rotate Through It

You can't raise the 20-region ceiling from app configuration. Since there's no way to grow it, you change the design instead: hold as many logical geofences as you like in your own store, and hand CLLocationManager only the 20 nearest to the user at any moment. When the user moves, swap the lineup. This dynamic re-registration is the heart of it.

The question is when to swap. That's where startMonitoringSignificantLocationChanges() comes in. It's a separate mechanism from region monitoring, delivering location updates at a coarse grain — roughly every 500 meters, no more than once every few minutes. The coarseness keeps power draw low, and the OS wakes your app to deliver updates even after it has been terminated. That's far too coarse for the arrival test itself (radii around 100m), but it's exactly the right grain for deciding when to rotate the 20.

Laid out, the roles are:

RoleAPIGrain / traits
Actual arrival detectionregion monitoring~100m radius, max 20
Trigger to rotate the 20significant location change~500m, low power, relaunches after termination
Holding all geofencesyour own store (array or DB)unlimited count

It's a two-tier arrangement: reserve high-precision monitoring for a small set, and delegate the swapping to a coarse, power-frugal monitor. Even with hundreds of spots nationwide, only the nearest 20 are ever loaded into CLLocationManager.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You'll understand why the 21st geofence is silently ignored, and be able to tell that the symptom is an iOS design limit rather than a bug in your code
You get a dynamic re-registration manager that always keeps the 20 targets nearest the user live, shaped to drop into Rork Max's generated code
You'll know exactly where to fill in the parts that only surface on a real device — significant location changes, didDetermineState, and Always authorization
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-07-06
Opening Your Rork Max App to Apple Intelligence — Designing App Intents Assistant Schemas and Handling What Doesn't Fit
How to make actions in a Rork Max-generated Swift app callable from Apple Intelligence using App Intents Assistant Schemas — mapping to the fixed schemas, routing what doesn't fit, availability fallbacks, and on-device testing.
Dev Tools2026-07-04
Your Rork Max App Loses the Photos a User Picked After Relaunch — The Trap of Holding Onto URLs Under Limited Photo Access
In a native Swift app generated by Rork Max, photos picked via PHPickerViewController become unreadable after relaunch — because holding onto a URL or PHAsset no longer works in the age of limited access. Here's a design that copies the actual bytes into your own storage the instant they're picked.
Dev Tools2026-07-04
Start a Live Activity Without Launching Your Rork Max App — Designing Around a push-to-start Token That Never Arrives
In a native Swift app generated by Rork Max, you want to start a Live Activity from your server without the user ever opening the app. But the push-to-start token is never observed and it fails silently. Here's the cause and an observation layer that reliably captures the token.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →