I had this function to move certain textfields upwards, when the keyboards would block their view - I'm sure you all know about this:
override func viewDidLoad() {
super.viewDidLoad()
let center: NotificationCenter = NotificationCenter.default
center.addObserver(self, selector: #selector(keyboardDidShow(notification:)), name: NSNotification.Name?.UIKeyboardDidShow, object: nil)
center.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name?.UIKeyboardWillHide, object: nil)
}
But when I recently updated to swift 4.2, these stopped working, and these suggestions came up:
Replace 'UIKeyboardDidShow' with 'UIResponder.keyboardDidShowNotification' &
Replace 'UIKeyboardWillHide' with 'UIResponder.keyboardWillHideNotification
But when I pressed "fix", I get the error (x2):
Type 'NSNotification.Name' has no member 'UIResponder'
It kind of seems like a bug to me? That xCode can't accept it's own changes?? Anybody came across this and knows what to do?
Thanks!
Try this
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification object: nil)
More info use this link :- enter link description here
I hope this will help you :D
Thanks
Related
I am using NSNotificationCenter to send local notifications in my code and working in both Objective-C and Swift. I'm posting notifications from Objective-C And receiving in Swift. But the methods that I added in notification getting called multiple times and added observer only in viewDidLoad method.
Swift:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil);
}
Objective-C:
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.isSyncPending = true;
[[NSNotificationCenter defaultCenter]
postNotificationName:NOTIF_CONTACT_ENTITY_CHANGE object:nil];
}
-(void)insertData(){
[[NSNotificationCenter defaultCenter]
postNotificationName:NOTIF_SERVER_CARD_SYNCED object:nil];
}
I added remove observer in my deinit but it is not even calling. How to stop calling multiple times.
//call this method in viewDidLoad
fileprivate func registerNotifs() {
//remove observer before adding to make sure that it is added only once
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil);
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil);
}
you can do like this
fileprivate func registerLocalNotifications() {
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil)
NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil)
}
add above method in viewDidLoad and in
deinit {
NotificationCenter.default.removeObserver(self)
}
REF : Where to remove observer for NSNotification in Swift?
Update:
Check you class instance if it already persist i.e
in view when you are instantiating this view controller
you can do like this
if let vc = yourNotificationViewCointrollerObj {
// USE EXISTING ONE
} else {
// CREATE NEW INSTANCE
}
NSNotificationCenter is a "publish-subscribe" mechanism where each posted notification is delivered to all subscribers (called observers). If you receive a notification multiple times it means that either you have multiple subscribers, or you are sending a notification multiple times.
I assume that you have only one subscriber for each notification type - your MainScreen UIViewController in Swift. It means that you probably send each notification multiple times.
For example applicationDidBecomeActive is called multiple times (each time the app becomes active). If you want to stop responding to this notification after the first time, you could unsubscribe from it as soon as you receive it first time:
#objc
func initateSync {
// do something first time
// ...
// unsubscribe to not receive it anymore
NotificationCenter.default.removeObserver(self,
name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE),
object: nil)
}
This is what you do in real world after receiving a newspaper trial that you didn't like :)
NotificationCenter.default.addObserver(self, selector: Selector(("uploaded")), name: NSNotification.Name(rawValue: "uploaded"), object: nil)
I was writing name: "uploaded:" and xcode corrected it to the above code. The problem is when running the app i get unrecognized selector.
Any one know how to fix this to work with swift 3
Use the (identifier checking) #selector syntax:
Without parameter:
#selector(uploaded)
With parameter:
#selector(uploaded(_:))
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.update), name: NSNotification.Name(rawValue: "uploaded"), object: nil)
func update() {
// do what you want
}
please note that "ViewController" is the class name where your function is
Getting Segmentation fault in Xcode 8
I have recently migrated my project to Swift 3. Xcode Version 8.0 (8A218a)
I get this error whenever I use UIKeyboardWillShow notification :
Command failed due to signal: Segmentation fault: 11`
This is how I am using the notification in my code:
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillShow)
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillHide)
NotificationCenter.default.addObserver(self, selector: #selector(myViewController.keyboardWillShow(_:)), name:NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(myViewController.keyboardWillHide(_:)), name:NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(_ sender: Notification) {
//keyboardWillShow Method
}
func keyboardWillHide(_ sender: Notification) {
// keyboardWillHide Method
}
Project runs successfully when I comment out the code in viewWillAppear method.
The main topic: Segmentation fault: 11, it's a bug of Xcode8/Swift3 and you should send a bug report.
And about your code:
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillShow)
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillHide)
There are no methods removing observers specifying only their names. You need to specify observer object for removeObserver(_:).
I'm not sure this is what you intend, but you can use removeObserver(_:name:object:) method like this:
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
I'm sure this would not crash your Xcode.
I had the same issue in the same conditions and environment (Swift 3, Xcode 8) and to resolve this problem you should put:
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
instead of:
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillShow)
NotificationCenter.default.removeObserver(NSNotification.Name.UIKeyboardWillHide)
This question already has answers here:
How do I resolve "ambiguous use of" compile error with Swift #selector syntax?
(3 answers)
Closed 6 years ago.
How do I convert these statements to use the #selector statement.
The statements work fine but gives warnings in Xcode, which I dislike.
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
In Swift 3, it looks like this:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
I use Core Spotlight, and I use UIPageController as RootViewController and several UIViewControllers. Every controller has UIView I drawing a circle of information in there. When I slide between controllers and open new controller I sent NSNotification from current UIViewController to current UIView which is located on current UIViewController. I sent NSNotification that so turn on NSTimer in UIView for updating of information. It works is fine when I just open the app. My problem is when I find infromation from the app in spotlight search and open needed controller from spotlight search NSNotification doesn't sent. I tried several different methods and I cannot to find how I can to make it. Please tell me how can I make it?
UPDATE I also tried singleton pattern for NSNotificationCenter but it also didn't help me.
UPDATE I tried write Selector as notificationCenter.addObserver(self, selector: Selector(turnOnMemoryTimer()), name: "turnOnMemoryArc", object: nil)
and it works when I launch app from spotlight search but it doesn't work when I just launch the app. For any help on this matter thanks!
I also tried to send notification from AppDelegate but it also didn't work
switch startIndex {
case 1:
notificatioCenter.postNotificationName("turnOnCPUTimer", object: nil)
default: break
}
UIViewController
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
if GlobalTimer.sharedInstance.controllerTimer != nil {
GlobalTimer.sharedInstance.controllerTimer.invalidate()
GlobalTimer.sharedInstance.viewTimer.invalidate()
}
GlobalTimer.sharedInstance.controllerTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "showMemory", userInfo: nil, repeats: true)
// notifications
notificationCenter.postNotificationName("turnOnMemoryArc", object: nil) // this message doesn't sent
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
notificationCenter.postNotificationName("checkMemoryOrientation", object: nil)
notificationCenter.addObserver(self, selector: "changeMemoryOrientation", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
}
UIView
// MARK: - var and let
var arc = Arc()
let notificationCenter = NSNotificationCenter.defaultCenter()
var boolForMemoryArc = false
override func drawRect(rect: CGRect) {
if boolForMemoryArc == false {
drawMemoryArc()
boolForMemoryArc = true
}
notificationCenter.addObserver(self, selector: "turnOnMemoryTimer", name: "turnOnMemoryArc", object: nil)
notificationCenter.addObserver(self, selector: "changedMemoryOrientation", name: "checkMemoryOrientation", object: nil)
}
func turnOnMemoryTimer() {
if GlobalTimer.sharedInstance.viewTimer != nil {
GlobalTimer.sharedInstance.viewTimer.invalidate()
}
GlobalTimer.sharedInstance.viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawMemoryArc", userInfo: nil, repeats: true)
}
I had a similiar issue and solved it like this:
notificationCenter.addObserver(self, selector: "turnOnMemoryTimer:", name: "turnOnMemoryArc", object: nil)
Receive AnyObject:
func turnOnMemoryTimer(notification: AnyObject) {
}
This needed change happened "spontaneous" the normal code was working for months.
I think you need to add the NSNotification as parameter to the function you're calling. So, two tweeks:
notificationCenter.addObserver(self, selector: "turnOnMemoryTimer:", name: "turnOnMemoryArc", object: nil)
and
func turnOnMemoryTimer(notification: NSNotification) {
// function body
}