9

I'm a relatively new user to swift and now, I need to take advantage of the proximity sensor of an iPhone. I don't matter the distance, but I want to know when something is near the iPhone.

So I found this code in Objective-C that worked, but I need it in Swift. I have tried some ways, but any worked. So here is the code I need:

- (void) activateProximitySensor {
    UIDevice *device = [UIDevice currentDevice];
    device.proximityMonitoringEnabled = YES;
    if (device.proximityMonitoringEnabled == YES) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityChanged:) name:@"UIDeviceProximityStateDidChangeNotification" object:device];
    }
}

- (void) proximityChanged:(NSNotification *)notification {
    UIDevice *device = [notification object];
    NSLog(@"Detectat");

    //DO WHATEVER I WANT
}

EDIT 1: What I tried was this:

override func viewDidLoad() {
        super.viewDidLoad()
        UIDevice.currentDevice().proximityMonitoringEnabled = true;

        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector(proximityStateDidChange()), name:UIDeviceProximityStateDidChangeNotification, object: nil);
}

and the function:

func proximityStateDidChange() {
        //DO WHATEVER I WANT
}

What I put in the function it's executed always when the app is executed.

EDIT 2: Trying the code of Eric D. comment

let sensor = MySensor() //declared in the VC but globally

override func viewDidLoad() {
        super.viewDidLoad()
        sensor.activateProximitySensor()
}

Throws me the exception: exception xcode throw me

Hope someone can help,

Thanks in advance!

Dani G.
  • 577
  • 8
  • 21
  • Show what you tried? Maybe you were close to a solution. – Eric Aya Jun 10 '15 at 15:04
  • Yes, I edit the question now! :) – Dani G. Jun 10 '15 at 15:06
  • For your Edit2: yeah, the problem is that you declare `let sensor = MySensor()` inside `viewDidLoad`, but as soon as `viewDidLoad` ends its execution, your `sensor` is freed from memory, and later when the notification observer fires the notification, it can't find your object, so it crashes. You should declare `let sensor = MySensor()` outside of `viewDidLoad`, either globally or in a class you can reach anytime. – Eric Aya Jun 10 '15 at 15:38
  • Hi, I've tried and edited my EDIT2 and the error is the same :( – Dani G. Jun 10 '15 at 15:42
  • Ok. I don't have any other advice then. Although I'm quite sure this error message is triggered by the notification inside `sensor` firing when the object has been released. If my code didn't work at all, the notification wouldn't be triggered and nothing would happen (no crash, just nothing). I hope you will find a solution, I'm curious about this. – Eric Aya Jun 10 '15 at 15:46
  • Now it throws me this error: 2015-06-10 17:48:32.054 MyApp[4142:1083793] *** NSForwarding: warning: object 0x17000b3a0 of class 'MyApp.MySensor' does not implement methodSignatureForSelector: -- trouble ahead Unrecognized selector -[MyApp.MySensor proximityChanged:] (lldb) – Dani G. Jun 10 '15 at 15:50
  • So we *know* that the notification is triggered, good thing. :) Now you "just" have to fix this selector error (and for that I can't help). I'm sure you're close to a working solution now (because we know the code for the proximity detector is indeed working, it's the notification that crashes). – Eric Aya Jun 10 '15 at 15:52
  • Hope someone can help! Thanks :D – Dani G. Jun 10 '15 at 15:54
  • Just a guess: try putting the method `proximityChanged` elsewhere (not in the MySensor class). Also try by using `activateProximitySensor` *not* inside `MySensor`. Maybe adding the two funcs in a class like I did is the problem (in your example the two funcs weren't included in their own class). – Eric Aya Jun 10 '15 at 15:58
  • 1
    Finally worked TT hahahah I putted inside the VC and called the function and pum! it works :D Thank you so much! Merci ;) – Dani G. Jun 10 '15 at 16:03
  • I know this is an old question but I do hope that you are able to answer this. I have followed everything said here... except for MySensor()... where is this declared? I do not see anything related to it in any question or even in the answer.. it just appears and I do not understand what It means – Julian Silvestri Dec 31 '19 at 15:16

5 Answers5

11

Swift 3 Version

(Based on Eric Aya's answer)

func setProximitySensorEnabled(_ enabled: Bool) {
    let device = UIDevice.current
    device.isProximityMonitoringEnabled = enabled
    if device.isProximityMonitoringEnabled {
        NotificationCenter.default.addObserver(self, selector: #selector(proximityChanged), name: .UIDeviceProximityStateDidChange, object: device)
    } else {
        NotificationCenter.default.removeObserver(self, name: .UIDeviceProximityStateDidChange, object: nil)
    }
}

func proximityChanged(_ notification: Notification) {
    if let device = notification.object as? UIDevice {
        print("\(device) detected!")
    }
}
Community
  • 1
  • 1
Warpling
  • 2,024
  • 2
  • 22
  • 38
8

Here's my take on this.

func activateProximitySensor() {
    let device = UIDevice.currentDevice()
    device.proximityMonitoringEnabled = true
    if device.proximityMonitoringEnabled {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "proximityChanged:", name: "UIDeviceProximityStateDidChangeNotification", object: device)
    }
}

func proximityChanged(notification: NSNotification) {
    if let device = notification.object as? UIDevice {
        println("\(device) detected!")
    }
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • Thanks! I will try it now and tell you something! – Dani G. Jun 10 '15 at 15:14
  • I've made a little modification: changed class methods to instance methods, to better follow your original code example. – Eric Aya Jun 10 '15 at 15:19
  • I've tried it and when I put my hand in front of the proximty sensor then the xCode goes to the AppDelegate telling me: Thread 1 : EXC_BAD_ACCESS (code=1, address=0x0) – Dani G. Jun 10 '15 at 15:24
  • On which line does the error occur? This error usually means that your app tried to access an object (a variable, for example) that wasn't in memory anymore. – Eric Aya Jun 10 '15 at 15:26
  • It doesn't tell me. The first code you put, happened the same but with an error, now, it seems to work but throw the exception I told you. I can tell you that the println doesn't execute :( – Dani G. Jun 10 '15 at 15:28
  • You should edit your question and add your new piece of code where you're using my example. That way I (or someone else) could maybe spot the problem. – Eric Aya Jun 10 '15 at 15:29
  • Hi, I followed this answer but got another issue. The selector is called once, but second time it does not fire again. – Bill Chan Oct 05 '17 at 14:58
6

Finally I get it working with the answer of Eric D.

Here is the code:

func proximityChanged(notification: NSNotification) {
  if let device = notification.object as? UIDevice {
    println("\(device) detected!")
  }
}
        
func activateProximitySensor() {
  let device = UIDevice.currentDevice()
  device.proximityMonitoringEnabled = true
  if device.proximityMonitoringEnabled {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "proximityChanged:", name: "UIDeviceProximityStateDidChangeNotification", object: device)
    }
  }
}

and in the viewDidLoad:

override func viewDidLoad() {
  super.viewDidLoad()
  activateProximitySensor()
}

Hope it helps!

aturan23
  • 4,798
  • 4
  • 28
  • 52
Dani G.
  • 577
  • 8
  • 21
  • Done, I did it because I didn't know that you would edit it. One more thing, do you know if it's possible that one time it has detected something, I can disable it (not only this device.proximityMonitoringEnabled = false). That works but if I maintain something near the proximity sensor, then my phone turns off until i take my hand out of the sensor. Theres any way to not to do it? Thanks another time! – Dani G. Jun 10 '15 at 16:16
5

Swift 4.2

Activate or deactivate ProximitySensor:

func activateProximitySensor(isOn: Bool) {
    let device = UIDevice.current
    device.isProximityMonitoringEnabled = isOn
    if isOn {
        NotificationCenter.default.addObserver(self, selector: #selector(proximityStateDidChange), name: UIDevice.proximityStateDidChangeNotification, object: device)
    } else {
        NotificationCenter.default.removeObserver(self, name: UIDevice.proximityStateDidChangeNotification, object: device)
    }
}

Selector:

@objc func proximityStateDidChange(notification: NSNotification) {
    if let device = notification.object as? UIDevice {
        print(device)
    }
}
Ivan Kholod
  • 111
  • 2
  • 5
3

Swift 4

//MARK:- Sensor deduct when hide and show the screen when call
func activateProximitySensor() {
    let device = UIDevice.current
    device.isProximityMonitoringEnabled = true
    if device.isProximityMonitoringEnabled {
        NotificationCenter.default.addObserver(self, selector: #selector(proximityChanged(notification:)), name: NSNotification.Name(rawValue: "UIDeviceProximityStateDidChangeNotification"), object: device)
    }
}

@objc func proximityChanged(notification: NSNotification) {
    if let device = notification.object as? UIDevice {
        print("\(device) detected!")
    }
}

For Removing Observer

 NotificationCenter.default.removeObserver(self, name: .UIDeviceProximityStateDidChange, object: nil)
Shakeel Ahmed
  • 5,361
  • 1
  • 43
  • 34