Short version
• With the iOS-7-and-earlier SDK there is no public (and therefore App-Store-legal) way to know when the hardware Ring/Silent switch is flipped or what position it is in.
• Every technique that really works relies on private frameworks or on polling side effects of those private frameworks; using any of them will get the application rejected.
• All you can (and should) do on iOS 7 is pick the proper audio-session category (Ambient / Solo-Ambient) so that your sound is automatically muted when the user moves the switch.
• If you also want to show a “muted” badge you simply cannot do that on iOS 7 because you have no event to drive the UI.
Details
Public API – nothing to listen to
• AVAudioSession does not change its current route when the switch is toggled.
• No NSNotification is posted (you already verified by observing “name:nil”).
• There is no KVO-able property whose value is affected by the switch.
• GSEvent constants you found are for lower-level, sandbox-inaccessible code.
Private API – why it is not a solution
• AVSystemController lives in the private Celestial framework. Any call to it is a private-API use and is a guaranteed App-Store rejection, whether or not you only read values.
• Even if you try it you will discover, as you already did, that the mute flag is not updated for the Ring/Silent switch; it is only for the software “Mute” in Control Centre / AirPlay.
• Intercepting GSEventRefs would require code injection at springboard level – this is possible only on a jail-broken device.
Polling tricks – unreliable and still not approved
• Playing an “inaudible” file and measuring the peak power, or looking at the return value of AudioServicesPlaySystemSound, or any of the other work-arounds that appear on the web are just polling private behaviour. None is documented, all are brittle, and they violate the review guideline “If you use non-public APIs your app will be rejected.”
“But Instagram does it!”
Big, popular apps sometimes ship with private calls, but that is not a precedent you can rely on—many such calls are whitelisted only for the bundle identifier in question. Apple’s stance in the developer documentation and in review is consistent: third-party applications are not allowed to query the Ring/Silent switch.
What changes in iOS 8 and later
In iOS 8 Apple introduced
• secondaryAudioShouldBeSilencedHint (BOOL property on AVAudioSession)
• AVAudioSessionSilenceSecondaryAudioHintNotification
These do fire when audio that is supposed to be “secondary” (games, bleeps, etc.) should silence itself, which includes the user flipping the Ring/Silent switch to silent.
Therefore, starting with iOS 8 you can do:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleSilenceHint:)
name:AVAudioSessionSilenceSecondaryAudioHintNotification
object:[AVAudioSession sharedInstance]];
- (void)handleSilenceHint:(NSNotification *)n {
BOOL silenced = [[n.userInfo objectForKey:AVAudioSessionSilenceSecondaryAudioHintTypeKey]
integerValue] == AVAudioSessionSilenceSecondaryAudioHintTypeBegin;
self.mutedBadge.hidden = !silenced;
}
or simply poll the property:
BOOL silenced = [AVAudioSession sharedInstance].secondaryAudioShouldBeSilencedHint;
But none of that is available on iOS 7. If you must support 7-series devices you have to live without the badge.
Conclusion
On iOS 7 and below it is impossible through public APIs to detect or to be notified of the Ring/Silent switch position. The only correct approach is to choose an audio-session category that honours the switch and not try to paint additional UI. On iOS 8+ you can use the new “secondary-audio” hint API introduced exactly for this purpose.
Was this answer helpful?
version: o3-pro-2025-06-10
Status: UQ Validated
Validated: 8 months ago
Status: Needs Human Verification
Loading model reviews...
Loading reviews...