Proximity Senzor addNotification call function mutliple times - swift

I activated the proximity senzor in application and now the function is calling multiple times.
I don't know what is wrong. Can you help me?
//MARK:- Activate Proximity Sensor
func activateProximitySensor() {
proximitySenzorActionStatus = true
device.isProximityMonitoringEnabled = true
if device.isProximityMonitoringEnabled {
NotificationCenter.default.removeObserver(self, name: UIDevice.proximityStateDidChangeNotification, object: device)
NotificationCenter.default.addObserver(self, selector: #selector(proximityStateDidChange), name:UIDevice.proximityStateDidChangeNotification, object: device)
}
}
func deactivateProximitySenzor() {
proximitySenzorActionStatus = false
device.isProximityMonitoringEnabled = false
NotificationCenter.default.removeObserver(self, name: UIDevice.proximityStateDidChangeNotification, object: device)
}
The methos in now called for 3 times:
#objc func proximityStateDidChange(notification: NSNotification) {
print("proximityStateDidChange")}
I activated the senzor in
viewWillAppear
and remove in
viewWillDisappear

You need to calculate the time of flight between every occlusion of the sensor.

Related

CoreData and CloudKit Sync works, but NSPersistentStoreRemoteChange notification never fires

I've updated an existing CoreData app to use CloudKit so that it can keep data synchronised across multiple devices (for the same iCloud account).
It works! The data sync's just fine.
But the primary UIViewController's view does not reflect the new data. To see the changes, I have to switch to a different view, then switch back to the primary view which has a refreshData() call in its viewWillAppear() function. It then re-reads from the data store and displays all the data (including whatever was updated on some other device.
The UIViewController should be observing the NSPersistentStoreRemoteChange notification as per the viewDidLoad() below:
override func viewDidLoad() {
super.viewDidLoad()
// NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: AppDelegate.appDelegate().persistentContainer.persistentStoreCoordinator)
NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: nil)
}
But the handler function never gets called:
#objc func handleRemoteChange(notification: Notification) {
print("Handling remote change to data in Collection Controller")
refreshData()
}
That print statement never prints anything, and a breakpoint set there never fires.
I have configured the managed object context to merge changes from parent as required immediately after the NSPersistentCloutKitContainer is created:
container.viewContext.automaticallyMergesChangesFromParent = true
The application has all the relevant iCloud capabilities and entitlements that I'm aware of after scouring the web (and Stack Overflow) for clues, including:
"Remote notifications" (Background Modes)
"CloudKit" (iCloud)
A container has been created and selected with an identifier of the
format: iCloud.reverse.domain.app
The Container's persistentStoreDescription has the NSPersistentStoreRemoteChangeNotificationPostOptionKey option set to true:
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("FAILED to load persistent store:\(storeDescription)\nERROR:\n\(error)\n\(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
for description in container.persistentStoreDescriptions {
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
}
Clearly the data is being sync'd OK. It's just the notification that is not working as expected. So the end user doesn't see the new/sync'd data automatically.
How can I get this to work?
I have the same problem, and solved by configuring custom persistent store descriptions before calling loadPersistentStores(completionHandler:)
container = NSPersistentCloudKitContainer(name: "RubikClub")
// turn on persistent history tracking
let description = container.persistentStoreDescriptions.first
description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
NotificationCenter.default.addObserver(self, selector: #selector(type(of: self).storeRemoteChange(_:)), name: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator)
container.loadPersistentStores { (_, error) in
if let error = error {
fatalError("init core data error: \(error.localizedDescription)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
I have the same problem. I just found out that it works fine in the TestFlight builds, but when directly built with Xcode, it does not. Have you tried that?
Also remember to listen for remote changes as outlined here:
https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes
This seems to require the NotificationCenter.default.addObserver object: field to be container.persistentStoreCoordinator to work, which is in the documentation at https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes.
Apple's example code at https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud uses object: container but doesn't work.
Listener:
NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: nil)
Should be added inside
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Here:
NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: nil)
}
Don't forget to unsubscribe on view will disappear:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: .NSPersistentStoreRemoteChange, object: nil)
}

Deactivate AudioSession in AudioKit

I'm using AudioKit, and trying to set audio session inactive, when I don't need it. So, I wrote some simple code to understand mechanism of this process, and faced one unexpectable trouble. With attempts of deactivating session, I'm getting error:
[avas] AVAudioSession.mm:1079:-[AVAudioSession setActive:withOptions:error:]: Deactivating an audio session that has running I/O. All I/O should be stopped or paused prior to deactivating the audio session.
ViewController.swift:deactivateAudioSession():73:Error Domain=NSOSStatusErrorDomain Code=560030580 "(null)"
This is my sample code:
import UIKit
import AudioKit
class ViewController: UIViewController {
var reverb: AKReverb?
var delay: AKDelay?
var chorus: AKChorus?
var mic: AKMicrophone!
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(applicationWillResignActive),
name: UIApplication.willResignActiveNotification,
object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive),
name: UIApplication.didBecomeActiveNotification,
object: nil)
super.viewDidLoad()
AKSettings.useBluetooth = true
guard let mic = AKMicrophone() else { return }
self.mic = mic
chorus = AKChorus(mic)
chorus?.depth = 1
chorus?.frequency = 44000
let delay = AKDelay(chorus)
delay.feedback = 0.2
reverb = AKReverb(delay)
let mix = AKMixer(reverb)
AudioKit.output = mix
}
#IBAction func launchEngine() {
do {
try AudioKit.start()
} catch {
AKLog(error)
}
}
#IBAction func deactivateAudioSession() {
// mic.stop()
// reverb?.stop()
// delay?.stop()
// chorus?.stop()
do {
try AKSettings.session.setActive(false)
} catch {
AKLog(error)
}
}
#objc func applicationDidBecomeActive() {
launchEngine()
}
#objc func applicationWillResignActive() {
deactivateAudioSession()
}
}
As you can see, basically, I wanted to handle app state changing, but this error happens even if I call deactivateAudioSession() method using UI. I've tried to stop() all node objects (commented code) before deactivation, but error stays. What I'm doing wrong?

Watch for SD Card Insertion

I would like my app to be notified when the user inserts an SD card. I tried adding an observer, but no notifications are received.
class SDCardWatcher: NSObject {
public override init() {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(self.onDiskMounted(_:)), name: .NSWorkspaceDidMount, object: nil)
}
#objc public func onDiskMounted(_ notification : Notification) {
// This code is never executed
print(notification.description)
}
}
I am new to MacOS so would appreciate any suggestions.

Notifications and pause mode

I'm making some game with Swift and SpriteKit.
When my app is going to background it calls a function pause but it automatically unpause when the game resumes.
func pauseTheGame()
{
self.scene?.isPaused = true
}
AppDelegate
func applicationWillResignActive(_ application: UIApplication)
{
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "goToBackground"), object: self)
GameScene
NotificationCenter.default.addObserver(self, selector: #selector(GameScene.pauseTheGame), name: NSNotification.Name("goToBackground"), object: nil)
How can I fix it?
I think its not ideal to pause the whole scene, its better to have a worldNode and pause that node. This will also make your life easier for overlaying Menu nodes etc.
Apple also does this in their sample game DemoBots.
Create a world node in your scene and a isGamePause property
var isGamePaused = false
let worldNode = SKNode()
and add it in didMoveToView
addChild(worldNode)
Than add all your sprites to that node
worldNode.addChild(someSprite1)
worldNode.addChild(someSprite2)
Than in your pause function you say
func pauseTheGame() {
isGamePaused = true
worldNode.paused = true
physicsWorld.speed = 0
/// show pause menu
}
Your resume function should say
func resumeTheGame() {
isGamePaused = false
worldNode.paused = false
physicsWorld.speed = 1
// remove pause menu
}
To make extra sure that your game does not resume when paused I add a check in the update method to keep the game paused.
override func update(_ currentTime: TimeInterval) {
guard !isGamePaused else {
worldNode.paused = true
physicsWorld.speed = 0
return
}
...
}
As a tip you should always organise string keys into properties to avoid typos e.g Notification centre names, UserDefaults keys, SKAction keys etc.
With Swift 3 for Notification Center names you can now create an extension and handle them in a very neat way.
extension NSNotification.Name {
static let goToBackground = Notification.Name(rawValue: "goToBackground")
}
Now you can say
NotificationCenter.default.post(name: .goToBackground, object: self)
NotificationCenter.default.addObserver(self, selector: #selector(pauseTheGame), name: .goToBackground, object: nil)
Hope this helps

NSNotificationCenter - UIApplicationWillEnterForegroundNotification takes too long

My code:
overide func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "activeAgain", name: UIApplicationWillEnterForegroundNotification, object:nil)
}
func activeAgain() {
println("ActiveAgain") //Comes immediately
callSeparateFunction() //Takes 5s
}
Why does the println comes immediately and the separate function call takes up to 5s? I have to call a new function when the app comes back to foreground. Thanks!