I'm working with Intercom's iOS SDK and reading through the Header available I found:
//=========================================================================================================
/*! #name Intercom Notifications */
//=========================================================================================================
/*!
These are notifications thrown by Intercom for iOS when the Intercom window is displayed and hidden or when
a new conversation has been started. These notifications are fired only when there is a change in the state
of Intercom's UI: when a user receives a message for instance, willShow and didShow notifications will be
fired accordingly when the Intercom Notification (chat head) is presented.
Once the user taps on the chat head, the message is presented in your app. It will be presented covering
the entire screen, but no notifications will be thrown here as Intercom has already been visible.
In the case of a new conversation this notification may be used to prompt users to enable push notifications.
*/
let IntercomWindowWillShowNotification: String
let IntercomWindowDidShowNotification: String
let IntercomWindowWillHideNotification: String
let IntercomWindowDidHideNotification: String
let IntercomDidStartNewConversationNotification: String
How can I got about catching these notifications in a controller and then do something based on the specific notification that is thrown?
You will need to add your ViewControllerClass as an observer to each notification it should observe in viewDidLoad...
class ITC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("icWindowWillShowNotification:"), name: IntercomWindowWillShowNotification, object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func icWindowWillShowNotification (notification: NSNotification) {
//Do something
}
}
Related
Here I created a customView: UIView and implemented UITextField didBegin and didEnd notificationObservers
When set object as nil. I'm get triggered notificationObserved(_:)
But When I pass a (object: self) I didn't receive notificationObserved.
class CustomView: UIView {
func setupView() {
[UITextField.textDidBeginEditingNotification,
UITextField.textDidEndEditingNotification].forEach({
NotificationCenter.default.addObserver(self, selector: #selector(notificationObserved(_:)), name: $0, object: self)
})
}
#objc func notificationObserved(_ notified: Notification) {
switch notified.name {
case UITextField.textDidBeginEditingNotification:
// Do here
case UITextField.textDidEndEditingNotification:
// Do here
default:
break
}
}
}
That's actually the expected behavior. The parameter object in the method addObserver(_,selector:,name:,object:) is, as stated in the developer documentation (here), "The object that sends notifications to the observer".
Since the object sending the notification is UITextField and not and instance of your class CustomView, you will never get the notification when you pass self in the object parameter.
Passing nil indicates that no matter the sender, you always want to receive the notification.
I try to get notifications as soon as the currently visible pages in my pdfView change.
Actually this should work according to the documentation via .PDFViewVisiblePagesChanged.
However, I only get a notification the very first time when the pdfView didLoad.
As soon as I then scroll (and thus the visible pages change) I do not receive a single notification. The funny thing is that the notification .PDFViewPageChanged works normally (but in this case it is not enough). The same behaviour is also with .PDFViewScaleChanged: here I never get a notification when zooming inside the pdfView.
Code Snippet from my ViewController:
ovverride func viewDidLoad() {
//...
NotificationCenter.default.addObserver(self, selector: #selector(onDidVisiblePagesChanged(_:)), name: .PDFViewPageChanged, object: nil)
//...
}
#objc func onDidVisiblePagesChanged(notification:Notification) {
print("visible Pages changed!")
}
The problem is located in your function "onDidVisiblePagesChanged, you're waiting for a parameter type notification, you need to cast the parameter inside your function
#objc func onDidVisiblePagesChanged(_ sender:Any) {
if let notification = sender as? Notification {
print("visible Pages changed!")
print(notification)
}
}
Hi am developing a app using swift2 in my app i want to track location for every 5 minutes when user successfully logged in now i can successfully track location of the user now i want to track when the app is in backgrounded for that i have to use app delegate but all functions and methods are i wrote in view controllers only so how can i call view controllers method and function to app delegate.
code in viewController:
class ThirdViewController: UIViewController{
In view did load:
{
////// i created timer scheduled with time internal /////
}
////// Here am fetched current locations and performed some function for timer to execute //////
}
In my appDelegate:
func applicationDidEnterBackground(application: UIApplication) {
if UIApplication.sharedApplication().applicationState != .Active{
//here i have to call that timer function execute how to do that????
}
You can fire notification when app goes to background
func applicationDidEnterBackground(application: UIApplication) {
if UIApplication.sharedApplication().applicationState != .Active{
NSNotificationCenter.defaultCenter().postNotificationName("Notificationname", object: nil)
}
}
in your controller view did load dd observer for notification
// add observer for notification.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.notificationReceived), name: "Notificationname", object: nil)
Method handler for received Notification
func notificationReceived() {
// do what you want to do here.
}
You would want to create a class with your function inside it and then call it from your app delegate, you can do this like this:
Create a swift file with the name of your class e.g. MyClass.swift
Then you create the class in your file and add the function in it:
class MyClassName {
Add your function in here
}
Then you call it from appDelegate.swift like this:
let myClassVar: MyClassName?
Then call the function like this -> myClassVar.functionName
Like this,
func applicationDidEnterBackground(application: UIApplication) {
if UIApplication.sharedApplication().applicationState != .Active{
let thirdViewController = ThirdViewController()
thirdViewController.functionYouWantToCall()
}
Thanks :)
I am learning & developing ios application with swift.I have 2 tabs in my app,so I have 2 view controller.I need to connect socket server.But in which file ?
First tab is showing conversations list and second tab is chat interface.User is sending message from second tab.If someone sends a message to this user,I need to show this message in first tab.
I need to connect socket server but in which file ? I mean example: When message arrives to this user i need to save it to database and show user in second tab.Is view controller file good for this case ?
I would recommend checking out Alamofire. It is a fantastic networking library built entirely for Swift and has really picked up in popularity of the past few months. This makes it incredibly easy to call a web service to fetch data.
WebSockets
If you actually need to connect to your server using web sockets, then I'd check out SocketRocket built by the fine folks at Square. Here's a link to their project on Github.
Since you're new to iOS development, I'd suggest a simple architecture where you abstract the network calls out of your view controllers.
ChatManager
Internally manages all networking such as SocketRocket
Should be a singleton or property on UIApplicationDelegate
Has public API for sending message
Sends out notifications when it receives notifications back
class ChatManager {
// Add property for socket
class var sharedInstance: ChatManager {
struct Singleton { static let instance = ChatManager() }
return Singleton.instance
}
init() {
// Create the socket
}
func sendMessage(message: String) {
// Push the message onto the socket
}
// Delegate methods
func messageReceived(message: String) {
// Emit the message using NSNotificationCenter
}
}
View Controller 1
Subscribes to notifications from ChatManager
class ViewController1 : UIViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Register for NSNotification coming from ChatManager
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
View Controller 2
Subscribes to notifications from ChatManager
Sends new messages to the ChatManager to push through the socket
class ViewController2 : UIViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Register for NSNotification coming from ChatManager
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func userAddedNewChatMessage(message: String) {
ChatManager.sharedInstance.sendMessage(message)
}
}
I am building an iOS app using the new language Swift. Now it is an HTML5 app, that displays HTML content using the UIWebView. The app has local notifications, and what i want to do is trigger a specific javascript method in the UIWebView when the app enters foreground by clicking (touching) the local notification.
I have had a look at this question, but it does not seem to solve my problem. I have also come across this question which tells me about using UIApplicationState, which is good as that would help me know the the app enters foreground from a notification. But when the app resumes and how do i invoke a method in the viewController of the view that gets displayed when the app resumes?
What i would like to do is get an instance of my ViewController and set a property in it to true. Something as follows
class FirstViewController: UIViewController,UIWebViewDelegate {
var execute:Bool = false;
#IBOutlet var tasksView: UIWebView!
}
And in my AppDelegate i have the method
func applicationWillEnterForeground(application: UIApplication!) {
let viewController = self.window!.rootViewController;
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("FirstView") as FirstViewController
setViewController.execute = true;
}
so what i would like to do is when the app enters foreground again, i want to look at the execute variable and run the method as follows,
if execute{
tasksView.stringByEvaluatingJavaScriptFromString("document.getElementById('sample').click()");
}
Where should i put the code for the logic to trigger the javascript from the webview? would it be on viewDidLoad method, or one of the webView delegate methods? i have tried to put that code in the viewDidLoad method but the value of the boolean execute is set to its initial value and not the value set in the delegate when the app enters foreground.
If I want a view controller to be notified when the app is brought back to the foreground, I might just register for the UIApplication.willEnterForegroundNotification notification (bypassing the app delegate method entirely):
class ViewController: UIViewController {
private var observer: NSObjectProtocol?
override func viewDidLoad() {
super.viewDidLoad()
observer = NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [unowned self] notification in
// do whatever you want when the app is brought back to the foreground
}
}
deinit {
if let observer = observer {
NotificationCenter.default.removeObserver(observer)
}
}
}
Note, in the completion closure, I include [unowned self] to avoid strong reference cycle that prevents the view controller from being deallocated if you happen to reference self inside the block (which you presumably will need to do if you're going to be updating a class variable or do practically anything interesting).
Also note that I remove the observer even though a casual reading of the removeObserver documentation might lead one to conclude is unnecessary:
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 dealloc method.
But, when using this block-based rendition, you really do need to remove the notification center observer. As the documentation for addObserver(forName:object:queue:using:) says:
To unregister observations, you pass the object returned by this method to removeObserver(_:). You must invoke removeObserver(_:) or removeObserver(_:name:object:) before any object specified by addObserver(forName:object:queue:using:) is deallocated.
I like to use the Publisher initializer of NotificationCenter. Using that you can subscribe to any NSNotification using Combine.
import UIKit
import Combine
class MyFunkyViewController: UIViewController {
/// The cancel bag containing all the subscriptions.
private var cancelBag: Set<AnyCancellable> = []
override func viewDidLoad() {
super.viewDidLoad()
addSubscribers()
}
/// Adds all the subscribers.
private func addSubscribers() {
NotificationCenter
.Publisher(center: .default,
name: UIApplication.willEnterForegroundNotification)
.sink { [weak self] _ in
self?.doSomething()
}
.store(in: &cancelBag)
}
/// Called when entering foreground.
private func doSomething() {
print("Hello foreground!")
}
}
Add Below Code in ViewController
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector:#selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
#objc func appMovedToForeground() {
print("App moved to foreground!")
}
In Swift 3, it replaces and generates the following.
override func viewDidLoad() {
super.viewDidLoad()
foregroundNotification = NotificationCenter.default.addObserver(forName:
NSNotification.Name.UIApplicationWillEnterForeground, object: nil, queue: OperationQueue.main) {
[unowned self] notification in
// do whatever you want when the app is brought back to the foreground
}