Are the new notifications not currently working in Swift 3?
I am doing:
NotificationCenter.default().post(name: DidTouchParticleView, object: self.particle as? AnyObject)
In a custom view's touchesBegan() and I need to send the particle object to the view controller if there is one. So I do this:
NotificationCenter.default().addObserver(forName: DidTouchParticleView,
object: self,
queue: OperationQueue.main(),
using: presentParticleDisplayView(notification:))
In a view controller's viewDidLoad(). I am certain that that particular view controller is the one presented when I tap my custom view, however, the function presentParticleDisplayView(notification:) is never called.
Also, DidTouchParticleView is defined globally like this:
let DidTouchParticleView = NSNotification.Name("didTouchParticleView")
Is this due to the beta, or am I doing something wrong?
It sounds like you may be intending to call addObserver(_:selector:name:object:), where the second parameter message (the selector:) is sent to the first parameter (the target).
Instead, you are calling the wrong method, addObserver(forName:object:queue:using:), which works quite differently.
Also, as to the second part of your question:
let DidTouchParticleView = NSNotification.Name("didTouchParticleView")
That is correct (almost); it should be
let DidTouchParticleView = Notification.Name("didTouchParticleView")
All notification names are now Notification.Name instances. The proper way to do this is to say:
extension Notification.Name {
static let didTouchParticleView = Notification.Name("didTouchParticleView")
}
You can then refer to the notification's name as .didTouchParticleView throughout your code.
You're watching for yourself to post the notification (object: self). You probably mean something like object: particle or possibly object: nil in the addObserver call (but then be careful to make sure it's the right particle in the handler). Re-read the docs for this method and note carefully what the object parameter is for.
Note that this version of addObserver returns an observer object. You must store that so you can later call removeObserver with it.
Related
Currently in the process of implementing NS Notification in to my first IOS application. I am wanting to use it so when a user succesfully makes a purchase, the product name is broad cast out, and the listener runs the method to unlock the products. Looking at tutorials i am confused about how it works and would really appreciate if these could be cleared up. I will post the code below and what i think it does, if their are any mistakes please point these out.
Line 1 - Let is a variable that can not be changed, NotificationName is the name of the variable. Notfication.Name is declaring the name as "Notification Identifier"
let notificationName = Notification.Name("NotificationIdentifier")
Line 2 - I think here the "NotificationName" is the id of this for the listener as defined above by the let.
If i want to pass in an object is this done at the end? via the object tag. IE object: productsRequest
NotificationCenter.default.post(name: notificationName, object: nil)
Line - 3 This is the listener, the notification name has to match the post to receive the correct notification i assume. The add observer self selector is confusing me, and if i pass in an object from the post line 2 above, ie Object Products Request. Does this have to be declared in the listener?
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)
Any explanations to further my understanding are appreciated. Sorry if these seems like a basic question, how ever reading tutorials i am struggling to understand certain elements of this.
Thanks
Correct.
Correct. The object you pass into postNotification method is a sender, which can be used to filter notifications with the same name (p.3)
When you subscribe for a specific notification and pass an object to addObserver method, you will receive only notifications which were sent with this exact object. If you don't specify it in addObserver you will receive all notifications with this name.
Don't forget to removeObserver as soon as you don't need to listen to them anymore. If your listener is a view controller, it is usually a good practice to addObserver in viewWillAppear and removeObserver in viewDidDisappear methods.
Could someone kindly clarify the purpose of notificationSender in the addObserver function of NSNotification?
Here's the explanation from the Apple docs:
notificationSender
The object whose notifications the observer wants to receive; that is, only notifications sent by this sender are delivered to the observer.
If you pass nil, the notification center doesn’t use a notification’s sender to decide whether to deliver it to the observer.
We use notifications to respond when a video has ended. The code:
NSNotificationCenter.defaultCenter().removeObserver(self, name: AVPlayerItemDidPlayToEndTimeNotification, object: playerItem)
where playerItem contains the video in question. However, passing nil for object seems to have no discernible effect.
It's better for us to use nil instead of playerItem because we wouldn't need to create another class variable.
What's the risk in using nil, and what's the advantage in using playerItem?
The only reason to be specific with the notificationSender is if you have chosen a notification name that other objects (that you don't want to listen to) are going to send to you. Specifying a notificationSender is akin to a delegate relationship, where leaving it nil means that absolutely any object could send you a notification with the same String and you would process it.
In practice, this is rarely an issue as long as you pick notification strings that are unique. You'll see people using things like com.my.app.name.notification or kMyAppNotification for precisely this reason.
And as to the specific line of code you linked, I don't actually know the implementation details, but I'm assuming if you added a listener with the notificationSender property pointing to an object, you also need to remove the same listener with the notificationSender property set, or else risk a memory leak by not removing observers. But I'd have to read the docs again to figure that out.
Try this with a plain new Single View application template, so in the storyboard there is only 1 view controller
In the ViewController
class ViewController: UIViewController {
override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
print(self)
return self
}
}
We can see that it is printed 3 times, why is that?
In the spec
Overridden by subclasses to substitute another object in place of the object that was decoded and subsequently received this message.
You can use this method to eliminate redundant objects created by the coder. For example, if after decoding an object you discover that an equivalent object already exists, you can return the existing object. If a replacement is returned, your overriding method is responsible for releasing the receiver.
This method is invoked by NSCoder. NSObject’s implementation simply returns self.
Why is it called many times?
I have tested with your suggest and I see that it call 2 times. And with this I describe my knowledge below:
ViewController will call initWithCoder and after that will call awakeAfterUsingCoder
Continue ViewController will call loadNibNamed, loadNibNamed still call awakeAfterUsingCoder again.
This infomation I have referenced from other source. You can view and if have some info. Please share with me. I am very appreciate :)
From StackOverflow
Cocoanuts
fantageek.com
I was using this code to pass data between controllers.
InterfaceController.reloadRootControllersWithNames(["1","2","3"], contexts: ["adf","asd","asd"])
I called this code in willActivate() method, that you can see here.
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
InterfaceController.reloadRootControllersWithNames(["1","2","3"], contexts: ["adf","asd","asd"])
}
I have no idea about whats wrong with this code, in apple watch, the app is just refreshing again and again. Is there any other method to pass data between interface controllers while we use page based navigation.??
Please Find the below way of passing data in paged-based navigation in watch application (Watch os 2 and later).
Note :
An array of strings, each of which contains the name of an interface controller you want to display in the page-based interface. In your storyboard, the name of an interface controller is stored in the object’s Identifier property, which is located in the attributes inspector. The order of the strings in the array is used to set the order of the corresponding interface controllers. This parameter must not be nil or an empty array.
Objectiv C
[self presentControllerWithNames:#[#"FirstViewController",#"SecondViewController",#"ThirdViewController"] contexts:#[#"adf",#"asd",#"asd"]];
Swift
let controller = ["FirstViewController","SecondViewController","ThirdViewController"]
let pageContexts:[AnyObject]? = ["adf","asd","asd"]
presentControllerWithNames(controller, contexts: pageContexts)
If you call reloadRootControllersWithNames(NSArray, contexts: NSArray) onto the view controller, it will do as the function is titled: reload. Therefore, you have a view controller that refreshes all 3 of the items in the first Array you give, and then, since your current view controller calls willActivate() upon loading, it infinitely refreshes.
I don't have enough reputation to make this a comment, but my suggestion here is to find a method that you can call on an instance of the watch interface you want to in order to pass data.
What I mean is, if you have each interface as its own class, then you can make a method in the interface you want to get to that sets a property to whatever data you want to transfer before you present the interface.
I also use Objective-C more than Swift, but here's what my guess is as to what the Obj-C code would come to:
SecondWatchInterface *secondWatchInterface = [SecondWatchInterface new];
[SecondWatchInterface setSomeDataWithAStringValue:#"Foo"];
[self presentWatchInterface:SecondWatchInterface]
In Swift, I'm thinking this would equate to:
SecondWatchInterface *secondWatchInterface = SecondWatchInterface.new()
secondWatchInterface.setSomeDataWithAStringFile:"Foo"
presentWatchInterface(secondWatchInterface)
I'm unfamiliar with WatchKit myself; I typically use SpriteKit. I hope I helped identify what the problem was, at least!
To pass data between interface controllers you need to go for this method:
presentControllerWithName(“Second Watch Controller”, context: [“segue”:“pagebased”,“data”: "Data Passed Successfully”]);
Also, you can refer to this example: http://www.informit.com/articles/article.aspx?p=2272657&seqNum=3
I have a static method in a separate class to handle UIKeyboard.WillHideNotification & UIKeyboard.WillShowNotification so that it can be used across the app.
I am adding the observer in a ViewController in the following way :-
NSNotificationCenter.DefaultCenter.AddObserver (UIKeyboard.WillHideNotification, KeyboardAppearanceUtilities.OnKeyboardNotification);
How can I get the observer object in the notification Action method which is declared in KeyboardAppearanceUtilities class as follows :-
public static void OnKeyboardNotification (NSNotification notification)
{
}
notification.Object is always null for obvious reason that I am not setting the object parameter in the AddObserver method.
Can someone guide me how to rearrange the code so that this notification handler can be used across the app and also gives me access to the observer?
Your code would be a lot nicer if you used the strongly typed notifications:
http://iosapi.xamarin.com/?link=M%3aMonoTouch.UIKit.UIKeyboard%2bNotifications.ObserveWillHide