Proximity sensor in Swift (from Objective-C)
Asked Answered
H

5

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!

Huygens answered 10/6, 2015 at 14:43 Comment(10)
Show what you tried? Maybe you were close to a solution.Megdal
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.Megdal
Hi, I've tried and edited my EDIT2 and the error is the same :(Huygens
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.Megdal
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)Huygens
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).Megdal
Hope someone can help! Thanks :DHuygens
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).Megdal
Finally worked TT hahahah I putted inside the VC and called the function and pum! it works :D Thank you so much! Merci ;)Huygens
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 meansAlvarado
M
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!")
    }
}
Megdal answered 10/6, 2015 at 15:9 Comment(7)
Thanks! I will try it now and tell you something!Huygens
I've made a little modification: changed class methods to instance methods, to better follow your original code example.Megdal
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)Huygens
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.Megdal
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 :(Huygens
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.Megdal
Hi, I followed this answer but got another issue. The selector is called once, but second time it does not fire again.Warmup
A
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!")
    }
}
Adelbert answered 28/4, 2017 at 2:40 Comment(0)
M
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!")
    }
}
Megdal answered 10/6, 2015 at 15:9 Comment(7)
Thanks! I will try it now and tell you something!Huygens
I've made a little modification: changed class methods to instance methods, to better follow your original code example.Megdal
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)Huygens
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.Megdal
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 :(Huygens
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.Megdal
Hi, I followed this answer but got another issue. The selector is called once, but second time it does not fire again.Warmup
H
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!

Huygens answered 10/6, 2015 at 16:6 Comment(1)
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!Huygens
B
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)
    }
}
Biosynthesis answered 27/3, 2019 at 14:26 Comment(2)
does this work on an IPAD ? I have tried implementing this in but the notification is never triggered. thoughts?Alvarado
iPad doesn't have proximity sensor.Biosynthesis
L
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)
Leathaleather answered 25/5, 2018 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.