Error: Unrecognised Selector when using class reference - ios

I have a class in a swift file called cloud I use a reference to that class in my project to call two of its methods. But I get the following error and the app crashes;
NSForwarding: warning: object 0x7fc938717160 of class 'App.Cloud' does
not implement methodSignatureForSelector: -- trouble ahead
Unrecognized selector -[App.Cloud persistentStoreWillChange]
(lldb)
Does anybody know who i could resolve this and why this is occurring ?
PS: The error only appears when installing the app and launching for the first time. If I quit and relaunch it does not appear, however it does not execute the methods.
Heres my class,
class Cloud {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
func persistentStoreWillChange (notification:NSNotification) {
self.moc!.performBlock { () -> Void in
if self.moc!.hasChanges {
var error:NSError? = nil
self.moc!.save(&error)
if error != nil {
println("Save error: \(error)")
} else{
// drop any manged object refrences
self.moc!.reset()
}
}
}
}
func persistentStoreDidChange () {
println("Store Did Change")
}
//Refresh Data
func recieveChanges (notification:NSNotification){
self.moc!.performBlock { () -> Void in
self.moc!.mergeChangesFromContextDidSaveNotification(notification)
}
}
//View Will Appear
func addObsevers() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "persistentStoreDidChange:", name: NSPersistentStoreCoordinatorStoresDidChangeNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("persistentStoreWillChange:"), name:NSPersistentStoreCoordinatorStoresWillChangeNotification, object: moc!.persistentStoreCoordinator)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("recieveICloudChanges:"), name:NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: moc!.persistentStoreCoordinator)
}
//View Will Dissapear
func removeObservers() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: NSPersistentStoreCoordinatorStoresDidChangeNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: NSPersistentStoreCoordinatorStoresWillChangeNotification, object: moc!.persistentStoreCoordinator)
NSNotificationCenter.defaultCenter().removeObserver(self, name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: moc!.persistentStoreCoordinator)
}
}
Class reference in View Controller:
let iCloudSync = Cloud()
override func viewWillAppear(animated: Bool) {
iCloudSync.addObsevers()
loadData()
}
override func viewWillDisappear(animated: Bool) {
iCloudSync.removeObservers()
}

You need to derive class Cloud from NSObject when you declare it, like this:
class Cloud : NSObject {
Otherwise your selectors are invisible to Objective-C.

You changed code but you forgot to change method declaration from
func persistentStoreDidChange () {
println("Store Did Change")
}
to
func persistentStoreDidChange (notification: NSNotification) {
println("Store Did Change")
}

Well you do this, which says to call persistentStoreDidChange on self when the notification triggers:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "persistentStoreDidChange",
name: NSPersistentStoreCoordinatorStoresDidChangeNotification,
object: nil)
But then it looks like you don't implement persistentStoreDidChange within class Cloud.
So either remove that observer, or implement the method.

Your methods have parameters so you must express this with ':' in their names. Changed code should look like this:
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("persistentStoreWillChange:"), name: NSPersistentStoreCoordinatorStoresWillChangeNotification, object: moc!.persistentStoreCoordinator)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("recieveICloudChanges:"), name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: moc!.persistentStoreCoordinator)

Related

Update variables when day changes Swift [duplicate]

I want my app to act when there is a change to another day.
So, in my appDelegate, I put
func applicationSignificantTimeChange(_ application: UIApplication){
//this one fires
}
and in the ViewController that should update its content I do:
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(self.dayChanged(notification:)), name: Notification.Name("significantTimeChangeNotification"), object: nil)
}
and
#objc func dayChanged(notification: NSNotification){
//this one doesn't fire
}
somehow, while the func in AppDelegate is called, the observer seems to be blind for that event.
Is this syntax, or just plain misunderstanding of the mechanism?
You need to add an observer for "UIApplicationSignificantTimeChangeNotification":
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplicationSignificantTimeChangeNotification, object: nil)
For Swift 4.2 or later
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplication.significantTimeChangeNotification, object: nil)
Note: If your intent is to be notified when the day changes you can use .NSCalendarDayChanged ("NSCalendarDayChangedNotification") instead of UIApplication.significantTimeChangeNotification.
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: .NSCalendarDayChanged, object: nil)
And add the selector method to the view controller where you would like to monitor the day changes:
#objc func dayChanged(_ notification: Notification) {
}

Must Selector method be in the same instances as where the observer is?

Normally, the code addObserver both the Selector method tag with #Objc are coded in the same instance (instantiated class).
It is possible to pass a Selector from different instance to the addObserver?
The reason for doing this is because Selector behavior as a callback most of the time. Some of the callback methods are commonly used and could well be coded into a CommonCallBack Class, an example of usage would be like this:
class SomeViewController{
override func viewDidLoad() {
...
let common = CommonCallback()
NotificationCenter.default.addObserver(
self,
selector: #selector(common.methodA),
name: "notificationName",
object: nil
)
}
}
class CommonCallback{
#Objc func methodA() {
// doing A
}
}
The issue is I keep getting unrecognized selector sent to instance
You can also achieve this by doing this way
class SomeViewController {
override func viewDidLoad() {
let common = CommonCallback()
common.enableObserver = true
}
}
class CommonCallback{
var enableObserver : Bool!
override func viewDidLoad() {
if enableObserver {
NotificationCenter.default.addObserver(
self,
selector: #selector(common.methodA),
name: "notificationName",
object: nil
)
}
}
#objc func methodA() {
// Your code here
}
}
I found out, where went wrong if the code. The observer argument must be in the same class as the Selector method, so instead of:
NotificationCenter.default.addObserver(
self,
selector: #selector(common.methodA),
name: "notificationName",
object: nil
)
it should be:
NotificationCenter.default.addObserver(
common,
selector: #selector(common.methodA),
name: "notificationName",
object: nil
)
This will call CommonCallback.methodA instead of SomeViewController.methodA

Notification Center Observer Selector Method does not get called

I am adding an observer on A view controller and view controller B is presenting on A.
While dismissing Controller B , I have posted the notification but It does not called the selector method added in A.
Also notification get registered first and the post method is get called. I have already checked that.
Here is the sample code:
NotificationCenter.default.addObserver(self, selector: #selector(closButtonPressed(notification:)) ,name: Notification.Name("CloseButtonPressed"), object: nil)
#objc func closButtonPressed(notification: Notification){
}
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"), object: self)
Any help would be appreciated.
Make sure posting notification in completion handler
self?.dismiss(animated: true, completion: {
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"),
object: self)
}
Make sure you implement Notification correctly. I recommend you to create an extension for Notification Name & make it static.
extension Notification.Name {
static let didTapCloseButton = Notification.Name("CloseButtonPressed")
}
NotificationCenter.default.addObserver(self, selector: #selector(didTapCloseButton(_:)), name: .didTapCloseButton, object: nil)
#objc func didTapCloseButton(_ sender: Notification?) {
}
NotificationCenter.default.post(name: .didTapCloseButton, object: nil)
I am not sure what's wrong with your project. To solve your problem, I create a test project and write some code like this:
//ControllerA.swift
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(getNotification(notification:)), name: NSNotification.Name("CloseButtonPressed"), object: nil)
}
getNotification(notification: Notification) {
print(notification)
}
#objc func buttonAClick() {
navigationController?.present(ViewControllerB(), animated: true, completion: {
})
}
//ViewControllerB.swift
#objc func buttonClick() {
NotificationCenter.default.post(name: Notification.Name("CloseButtonPressed"), object: self)
self.dismiss(animated: true) {
}
}
As you said, I add notification in ControllerA, and present ControllerB, When ControllerB close, post notification and dismiss, console can print the notification object, so may I miss something?

iOS - NotificationCenter addObserver "UIMenuControllerWillHideMenu"

I have added notification observer for UIMenuControllerWillHideMenu but it does not call selector added/associated with notification center.
UIMenuControllerWillHideMenu is notification center identifier for UIMenuController and should be called when UIMenuController will hide. But somehow it's not working.
Here is code I've tried (Swift 3.x):
private func addMenuObserverNotification(){
NotificationCenter.default.addObserver(self, selector: #selector(self.menuControllerWillHideMenu), name: NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu"), object: nil)
}
// This function should be called on 'UIMenuControllerWillHideMenu'
func menuControllerWillHideMenu() -> Void {
removeMenuObserverNotification()
}
private func removeMenuObserverNotification(){
NotificationCenter.default.removeObserver(self)
}
Unable to identify, what's wrong.
Found a solution by replacing NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu") with just .UIMenuControllerWillHideMenu
private func addMenuObserverNotification(){
NotificationCenter.default.addObserver(self, selector: #selector(self.menuControllerWillHideMenu), name: .UIMenuControllerWillHideMenu), object: nil)
}
I did a mistake by adding it's initializer NSNotification.Name(rawValue: "UIMenuControllerWillHideMenu"), which may not require as NSNotificationName is typedef NSString, which directly allows an access to predefined values using .<value name>
For more details:
addObserver:selector:name:object:
NSNotificationName

Swift Nsnotificationcenter post notification error

I have a problem with post notification function.
In the FirstViewController in viewDidLoad I have this sentence:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "ponresultado", name: "resultadobusqueda", object: nil)
After that I have the function:
func ponresultado(notification:NSNotification)
{
var oDato : oDatoSel = notification.object as oDatoSel
}
In second view controller of type TableViewController in didDeselectRowAtIndexPath method I have this code:
var oDato : oDatoSel = oDatoSel()
oDato.id = "1"
oDato.nombre = "test"
NSNotificationCenter.defaultCenter().postNotificationName("resultadobusqueda", object: oDato)
I receive this error:
[App.FirstViewController ponresultado]: unrecognized selector sent to instance 0x797d2310
If in my ponresultado function in FirstViewController, I quit notification:NSNotification parameter like this:
func ponresultado()
{
var oDato : oDatoSel = notification.object as oDatoSel
}
I don't have the error. Why?
You need to add a : after the selector's name:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "ponresultado:", name: "resultadobusqueda", object: nil)
As your method is declared such as it accepts a NSNotification object:
func ponresultado(notification:NSNotification)
{
var oDato : oDatoSel = notification.object as oDatoSel
}
If your method takes a NSNotification as a parameter, you should add the ":" to your selector when registering. So your line :
NSNotificationCenter.defaultCenter().addObserver(self, selector: "ponresultado", name: "resultadobusqueda", object: nil)
Becomes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "ponresultado:", name: "resultadobusqueda", object: nil)

Resources