I use Kugel Library for Notification (https://github.com/TakeScoop/Kugel/tree/swift-3.0). I want to know how to remove Observer and where in my code . i use Unsubscribe for library and nothing happens
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
Kugel.unsubscribe("SleepMode")
Kugel.unsubscribe("SleepModeSynchroMode")
Kugel.unsubscribe(self, name: NSNotification.Name(rawValue: "SleepMode"), object: nil)
Kugel.unsubscribe(self, name: NSNotification.Name(rawValue: "SleepModeSynchroMode"), object: nil)
NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: "SleepMode"), object: nil);
NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: "SleepModeSynchroMode"), object: nil);
}
i want remove subscribe notification ( add observer ) when i go back to other view.
I use denit { } but the notification that doesn't killed .
Can you helpme
Tahnks
All that is wrong. Here is the right way to remove observers in Swift (also applies to Obj-C):
According to Apple's documentation, you have to keep a reference to your observer! NSNotificationCenter addObserver Self is not an observer so NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: "SleepMode"), object: nil); doesn't do anything.
What you have to do is:
Extend the Notification.Name for your notification: (where you post the notification)
extension Notification.Name {
static let notification = Notification.Name(rawValue: "A notification")
}
Create a weak reference to your observer with:
weak var observer: NSObjectProtocol?
Create an "addObserver" function like so: (where you want to listen to the notification)
func addObserver() {
guard observer == nil else { return }
observer = NotificationCenter.default.addObserver(forName: .notification,
object: nil,
queue: .main) { notification in
print("Notification triggered")
}
Create a "removeObserver" function:
func removeObserver() {
guard let observer = observer else { return }
NotificationCenter.default.removeObserver(observer)
}
Call your "addObserver" function from wherever you need it in your code (most probably from your viewDidLoad method)
Call the "removeObserver" function when you are done listening to that notification.
An important point here is that if you have an extra strong reference to your class implementing the notification and you "think" the observer is removed but it is not, then the guard implementation above prevents your code from creating several observers. This is particularly the case for some implementations of addObserver in the viewDidLoad function missing a removeObserver.
A proof? add a breakpoint in the addObserver function at the line where you assign the observer and edit the breakpoint (right click) then choose add action and pick Sound and select the option Automatically continue after evaluating actions.
Start your app and go back and forth in the view that implements the observer. If the number of time you hear the sound is constant, you're done! Otherwise you should here the sound increase by one each time you enter the view. There you go!
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its deallocation method. If your app targets earlier releases, you need to keep a reference to the observer object and submit it instead of 'self', also the library says its been Deprecated why are you using it?
Try and remove the observer in viewWillAppear
Related
I'm implementing a simple router in Go. I used to have a lot of redundant code for each endpoint returning an error when the method called wasn't implemented for that endpoint. I refactored and made a "base" type which provides default functions for each request type that simply return the unimplemented error. Now all I have to do is override the specific method functions for a given endpoint I wish to implement. This was all fun and games until I wanted to figure out, given an endpoint variable, which of the methods have been overridden?
Omitting extraneous details, here's as simple of an example as I can think of right now:
package main
import (
"fmt"
)
// Route defines the HTTP method handlers.
type Route interface {
Get() string
Post() string
}
// BaseRoute is the "fallback" handlers,
// if those handlers aren't defined later.
type BaseRoute struct{}
func (BaseRoute) Get() string {
return "base get"
}
func (BaseRoute) Post() string {
return "base post"
}
// Endpoint holds a route for handling the HTTP request,
// and some other metadata related to that request.
type Endpoint struct {
BaseRoute
URI string
}
// myEndpoint is an example endpoint implementation
// which only implements a GET request.
type myEndpoint Endpoint
func (myEndpoint) Get() string {
return "myEndpoint get"
}
func main() {
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
fmt.Println(myEndpointInstance.URI)
fmt.Println(myEndpointInstance.Get())
fmt.Println(myEndpointInstance.Post())
}
This snippet will print out the following:
/myEndpoint
myEndpoint get
base post
So my overriding of the functions works as intended. Now I'm wondering that in my main function, after I declare the myEndpointInstance, can I tell somehow that the Post function has not been overridden and is still implemented by the underlying BaseRoute without actually calling the function? Ideally, I want something like this:
func main() {
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
if myEndpointInstace.Post != BaseRoute.Post {
// do something
}
}
I've played around with the reflect package a bit, but haven't found anything helpful.
As noted by others, which method to call is a compile-time decision. So you can check this at compile time, most IDE's will navigate you to the method that is bound to the actual call.
If you want to check this at runtime, you may compare the function pointers. You can't compare function values, they are not comparable (only to the nil value). Spec: Comparison operators:
Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.
This is how you can do that:
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
v1 := reflect.ValueOf(myEndpointInstance.Post).Pointer()
v2 := reflect.ValueOf(myEndpointInstance.BaseRoute.Post).Pointer()
fmt.Println(v1, v2, v1 == v2)
v1 = reflect.ValueOf(myEndpointInstance.Get).Pointer()
v2 = reflect.ValueOf(myEndpointInstance.BaseRoute.Get).Pointer()
fmt.Println(v1, v2, v1 == v2)
This will output (try it on the Go Playground):
882848 882848 true
882880 882912 false
Output tells Post() is not "overridden" (myEndpointInstance.Post is the same as myEndpointInstance.BaseRoute.Post), while Get() is (myEndpointInstance.Get is not the same as myEndpointInstance.BaseRoute.Get).
See related questions:
How to compare 2 functions in Go?
Collection of Unique Functions in Go
I am using Swift 4 and I am wondering how having a reference to a ViewController in AppDelegate works. I have two questions which I have put in bold. I understand that AppDelegate is a delegate that has functions that get called when the app becomes foreground or background, or even when the user does the "open with" event on a file extension that my app is registered to handle and selects to open that file with my app- AppDelegate lets the app know that took place. 1) But what I don't understand is how AppDelegate should communicate with my Views to tell them that these events happened. I am wondering what the good design pattern is for doing so. My solution is to have a reference to a viewController so here is an example:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var hotSpotRISViewController = HotSpotRISViewController()
...
func application(_ app: UIApplication, open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
hotSpotRISViewController.setURL(theURL: url)
return true
}
}
What I don't understand is how this actually works. I thought that AppDelegate looks at Main.storyboard and starts that and that Main.storyboard has it's own reference to HotSpotRISViewController(). 2) How is it that by making a reference to HotSpotRISViewController() in the AppDelegate, that it uses this reference instead?
I have created a time activate on the View Controller.
It needs to call a selector, and for that selector, I am calling a function.
When the function is in the View Controller file, it works. If i put this function in another Swift file that I created in the app, it does not find the Selector and I get an error during runtime.
Is it possible to put functions in Swift in different files or not?
#IBAction func startNotificationTimer(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: "update_start", userInfo: nil, repeats: true)
timerStatus.text = "Started"
}
"update_start" is in a different file.
Thanks for the help
It doesn't matter what file your update_start method is in, but it does matter that it be a method in your View Controller class. If you define it in a file other than the one where that class is declared, you'll need to define the method in an extension on that class.
Also, NSTimer selectors should end with a colon (update_start:), because they take a single parameter (the timer) when called.
I am creating my first app with storyboards. So far, I have two ViewControllers - on the first VC, the user taps a button, and it takes them to the second VC, using a 'Present modally" segue.
Is there some method that is called when the new view appears? I want to be able to write the code to start the game in here.
You should look at viewDidLoad(), viewWillAppear(_:) and viewDidAppear(_:). Most likely what you need is the first one.
I think you're searching for the prepareForSegue method:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "Load View") {
// pass data to next view
}
}
It's called right before the segue is performed so you can for example identify the target ViewController and pass it some params.
I start project in Swift Language. Apps almost done. Single ViewController logics are all done. But I need to communicate with each other ViewController.
I want to pass some value from one ViewController to another ViewController. I'm using StoryBoard. I want to pass value using prepareSeague function as like Objective-C has. Is there any way to do this without using delegate-way.
In the first view controller handle prepareForSegue method and provide additional values to the second view controller, like:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "someidentifier" {
let vc = segue.destinationViewController as MySecondViewController
// vc.someProperty = someValue
}
}