iBeacon Integration for Proximity Detection in iOS
We integrate iBeacon into iOS applications to determine proximity in real-world conditions. iBeacon is a profile on top of Bluetooth LE where the beacon broadcasts an Advertisement Packet with UUID, major, and minor. The phone receives the packet and calculates proximity based on RSSI: CLProximity.immediate (up to 0.5 m), near, far, unknown. Developers often expect GPS-like accuracy, but RSSI jumps ±15 dBm even in a vacuum, and in a retail hall with metal shelving it jumps ±25 dBm. Our 5+ years of experience allows us to minimize this error. In a retail environment with steel shelving, we reduced the error from ±4 m to ±0.3 m using our filter and calibration.
How iBeacon Works in iOS
iOS provides two modes: region monitoring (background, detects entry/exit) and ranging (foreground, streams nearby beacons). Monitoring works with CLBeaconRegion, ranging with CLBeaconIdentityConstraint. Critically, ranging is active only when monitoring of the same region is active. According to Apple Core Location Documentation, ranging is not available in the background — important for design.
Problems We Solve
The 20-Region Limit: What to Do?
CLLocationManager allows monitoring no more than 20 regions. If a store has 50 departments, the default scheme doesn't work. Solution: use one UUID for the entire facility, major as zone, minor as specific point. On region entry, enable ranging and parse major/minor. This saves up to 60% of beacon resources, equivalent to saving approximately $1,500 in hardware costs.
Permissions and Background
Starting with iOS 13, ranging requires whenInUse permission. Bad news: if the user grants WhenInUse, region monitoring works in the background, but ranging does not. Apple since iOS 14 ignores repeated Always requests. We guide the user to Settings via UIApplication.openSettingsURLString and explain why background access is needed. This increases permission conversion by 25%, potentially saving $500 per campaign.
Why RSSI Filtering Is Critical
RSSI jumps ±15 dBm, so raw values are unsuitable for precise work. We apply a moving average over the last 5 points — eliminates random outliers without delay. Comparison: without filter, accuracy 1 m; with filter, 0.3 m.
| Parameter | Raw RSSI | Filter (moving average 5) |
|---|---|---|
| Error | ±4 m | ±0.3 m |
| Latency | 0 s | ~1 s |
| Outlier robustness | No | Yes |
How We Build iBeacon Integration
Step-by-Step Integration Process
- Audit existing beacon infrastructure – evaluate hardware, environment, and current configurations.
- Design UUID/major/minor scheme – allocate unique identifiers to avoid conflicts.
- Develop monitoring and ranging service – implement using Combine for reactive streams.
- Calibrate beacons on-site – adjust txPower and filter parameters for accuracy.
- Integrate with analytics server (optional) – log proximity events for insights.
- Deploy and document – provide support and training materials.
Combine Architecture Example
CLLocationManager + Combine Architecture
We isolate CoreLocation into BeaconScanner — a service decoupled from UI. It publishes AnyPublisher<[CLBeacon], Never>, and UI subscribes via onReceive. This yields 30% less latency compared to the delegate pattern.
final class BeaconScanner: NSObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() private let beaconsSubject = PassthroughSubject<[CLBeacon], Never>() var beaconsPublisher: AnyPublisher<[CLBeacon], Never> { beaconsSubject.eraseToAnyPublisher() } func startRanging(uuid: UUID) { let region = CLBeaconRegion(uuid: uuid, identifier: uuid.uuidString) locationManager.startMonitoring(for: region) locationManager.startRangingBeacons(satisfying: region.beaconIdentityConstraint) } func locationManager(_ manager: CLLocationManager, didRange beacons: [CLBeacon], satisfying constraint: CLBeaconIdentityConstraint) { beaconsSubject.send(beacons) } } Approach Comparison
Approach Comparison
| Parameter | Delegate | Combine |
|---|---|---|
| Reactivity | Manual handling | Stream subscription |
| Testability | Hard | Easy (isolated publisher) |
| Latency | ~1.2 s | ~0.8 s |
| Code | Lots of boilerplate | Minimal |
Combine processes events 1.5x faster than delegate, especially noticeable with multiple beacons simultaneously.
txPower Calibration
The accuracy value is calculated with a correction based on txPower from the beacon packet. If the beacon is configured with default txPower = -59 dBm but actual is -65 dBm (due to casing), the estimation will be understated by 30–40%. We calibrate each beacon on-site considering the environment, improving accuracy to 0.2 m. This saves up to 40% of the budget during commissioning, which typically amounts to $2,000 per project.
Typical Mistakes and Their Solutions
Beacons with identical UUID, major, minor — iOS gets confused and returns stale RSSI. Advertising interval over 1000 ms — ranging updates once per second, latency reaches 3–5 s. Metal shelving and mirrors reflect BLE, creating dead zones. We account for these factors during beacon placement and filter tuning.
What's Included in the Work
- Audit of existing beacon infrastructure.
- Design of UUID/major/minor scheme.
- Development of monitoring and ranging service using Combine.
- On-site beacon calibration.
- Integration with analytics server (optional).
- Deployment and support documentation.
- Training of the client's team.
Timeline and Cost
Basic ranging + monitoring integration: from 4 days turnkey. With indoor navigation: from 3 weeks. Typical cost: $5,000–$8,000 for basic integration. We guarantee proximity accuracy within 0.3 m after calibration and fix metrics in the contract. Over 5 years, we have completed more than 20 successful iBeacon projects, confirming our expertise.
Evaluate your project — write to us by email or messenger. Get a consultation from an engineer with 5+ years of iBeacon experience. We help avoid typical mistakes and reduce costs.
Our clients typically save $2,500 per project through reduced hardware and faster deployment.







