popover controller not being dismissed - ios

I have this UIViewController which is presented as .popover.
func editSlotPopOver(eventCell:EventCell, gr:UITapGestureRecognizer){
let location = gr.location(in: eventCell)
let editAlertController = UIViewController()
let viewAlert = EditSlotPopOver(frame: CGRect(x: 0, y: 0, width:editAlertController.view.bounds.width , height: editAlertController.view.bounds.height))
viewAlert.delegate = self
viewAlert.setEvent(event: eventCell.event!, cell: eventCell)
editAlertController.view = viewAlert
editAlertController.modalPresentationStyle = .popover
let popoverMenuViewController:UIPopoverPresentationController = editAlertController.popoverPresentationController!
popoverMenuViewController.permittedArrowDirections = .any
editAlertController.popoverPresentationController?.delegate = self
popoverMenuViewController.sourceView = eventCell
popoverMenuViewController.sourceRect = CGRect(
x: location.x,
y: location.y,
width: 1,
height: 1)
present(editAlertController, animated: true, completion: nil)
}
The popover is presented as expected:
However, when I try to delete the cell with this method:
func deleteSlot(eventCell: EventCell, id: Int){
let application = UIApplication.shared.delegate as! AppDelegate
let id:Int32 = Int32(eventCell.eventId!)
print(id)
let context = application.managedObjectContext
let fetchRequest:NSFetchRequest<Slot> = NSFetchRequest(entityName: "Slot")
fetchRequest.predicate = NSPredicate(format: "event_id = %d", id)
do {
let result = try context.fetch(fetchRequest)
let slot = result[0]
application.managedObjectContext.delete(slot)
do{
try context.save()
}catch let err {
print(err)
}
}catch let error {
print(error)
}
//DISMISS DOESN'T WORK HERE
self.editAlertController?.dismiss(animated: true, completion: nil)
eventCell.removeFromSuperview()
self.calendarView.forceReload(reloadEvent: true)
}
The cell is removed from the superview and the objected removed from core data but I am not able to dismiss the popover:
The 2 functions are declared in the same controller, however EditSlorPopOver is a subclass of UIView with a protocol named EditSlotDelegate. The delegate is being called but the popover is not being dismissed.
protocol EditSlotDelegate {
func deleteSlot(eventCell: EventCell, id: Int)
}
class EditSlotPopOver: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setUpEditButton()
editButton.addTarget(self, action: #selector(deleteSlot), for: .touchUpInside)
}
//.....more code here
func deleteSlot(){
delegate?.deleteSlot(eventCell: eventCell!, id: Int(slotid!))
}
//.....more code here
}

Moved from a comment:
Try calling dismiss on self rather than the self.editAlertController. It should be the controller thats presenting the popover that should dismiss it, not the popover dismissing itself.

Related

Adding UIView with data to the window

I need to add a UIView with size of tabbar but exactly above tabbar. This view allow user to come back to a started workout. My idea is holding data inside UIView and instantiate a View Controller with unfinished data when user clicks button. The problem is that when I want to instantiate VC my data in UIView become nil.
class BeforeRoutineClass {
// HERE I CREATE the UIView
func showWorkoutView(temporaryRoutine: Routine) {
guard let tabBar = navigationController.tabBarController else { return print("Tabbar is nil") }
let window = UIApplication.shared.keyWindow!
let height = tabBar.tabBar.frame.height
view2 = BackToWorkoutButton(frame: CGRect(x: 0, y: (tabBar.tabBar.frame.origin.y) - height, width: window.frame.width, height: height), routine: temporaryRoutine)
window.addSubview(view2!)
}
}
class BackToWorkoutButton: UIView {
var routine: Routine?
init(frame: CGRect, routine: Routine?, bobo: String?) {
self.routine = routine
super.init(frame: frame)
customInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private func customInit() {
let xibView = Bundle.main.loadNibNamed("BackToWorkoutButton", owner: self, options: nil)?.first as! UIView
xibView.frame = self.bounds
addSubview(xibView)
}
#IBAction func backButtonTapped(_ sender: UIButton) {
// THERE IS NIL ALWAYS
guard let routine = routine else { return print("Routine is nil") }
let routineVC = RoutineFactory.startWorkoutScene(routine: routine)
let navBarOnModal = UINavigationController(rootViewController: routineVC)
navBarOnModal.modalPresentationStyle = .fullScreen
guard let nav = UIApplication.shared.windows.last?.rootViewController else { return print("there is no nav")}
nav.present(navBarOnModal, animated: true, completion: nil)
self.removeFromSuperview()
}
}

How to change label text of a label in a popover view controller when pressing a button in the main view?

I'm relatively new to Swift. I have a main view controller, ViewControllerMain, and a popover view controller, PopUpVC, which only has a label. I have a function, infoClicked that displays the popover with another function (showPopover) when the info button is clicked. When I click the button, I want to change the label text of the popover. However, with the current code, the label always displays "Default".
Here is my code:
class ViewControllerMain: UIViewController, UIPopoverPresentationControllerDelegate, GetTimesUsed {
let tipController: PopUpVC = PopUpVC().self
#IBAction func infoClicked(_ sender: UIButton) {
tipController.tipText = "Success"
showPopover()
}
func showPopover() {
let myViewController = storyboard?.instantiateViewController(withIdentifier: "popupController")
myViewController?.preferredContentSize = CGSize(width: 350, height: 200)
myViewController?.modalPresentationStyle = .popover
let popOver = myViewController?.popoverPresentationController
popOver?.delegate = self
UIView.animate(withDuration: 1, animations: {
self.GifView.alpha = 0.7
})
DispatchQueue.main.asyncAfter(deadline: .now() + 0.45) {
UIView.animate(withDuration: 0.5, animations: {
self.present(myViewController!, animated: true, completion: nil)
})
}
popOver?.permittedArrowDirections = .down
popOver?.sourceView = self.view
var passthroughViews: [AnyObject]?
passthroughViews = [infoButton]
myViewController?.popoverPresentationController?.passthroughViews = (NSMutableArray(array: passthroughViews!) as! [UIView])
popOver?.sourceRect = infoButton.frame
}
}
class PopUpVC: UIViewController {
#IBOutlet weak var tip: UILabel!
var tipText: String = "Default"
override func viewDidLoad() {
super.viewDidLoad()
tip.text = tipText
// Do any additional setup after loading the view.
}
}
Thank you for your help.
As mentioned in comments, you seem to be instantiating the popup controller 2 times, so try it like this in your showPopOver code:
let myViewController = storyboard?.instantiateViewController(withIdentifier: "popupController") as! PopUpVC
myViewController.preferredContentSize = CGSize(width: 350, height: 200)
myViewController.modalPresentationStyle = .popover
myViewController.tipText = '' //set to what ever

Memory Leak in ViewController

So im having somewhat of an issue with my ios app. Im facing a memory leak when I enter my view controller that controls the display of my comments. I am using IGListKit so anyone that is familar with that would be a great help to this question but help is needed none the less. This is my newCommentsViewController that handles pulling the comments from firebase and sends them to the datasource.
import UIKit
import IGListKit
import Firebase
class NewCommentsViewController: UIViewController, UITextFieldDelegate,CommentsSectionDelegate,CommentInputAccessoryViewDelegate {
//array of comments which will be loaded by a service function
var comments = [CommentGrabbed]()
var messagesRef: DatabaseReference?
var bottomConstraint: NSLayoutConstraint?
public let addHeader = "addHeader" as ListDiffable
public var eventKey = ""
//This creates a lazily-initialized variable for the IGListAdapter. The initializer requires three parameters:
//1 updater is an object conforming to IGListUpdatingDelegate, which handles row and section updates. IGListAdapterUpdater is a default implementation that is suitable for your usage.
//2 viewController is a UIViewController that houses the adapter. This view controller is later used for navigating to other view controllers.
//3 workingRangeSize is the size of the working range, which allows you to prepare content for sections just outside of the visible frame.
lazy var adapter: ListAdapter = {
return ListAdapter(updater: ListAdapterUpdater(), viewController: self)
}()
// 1 IGListKit uses IGListCollectionView, which is a subclass of UICollectionView, which patches some functionality and prevents others.
let collectionView: UICollectionView = {
// 2 This starts with a zero-sized rect since the view isn’t created yet. It uses the UICollectionViewFlowLayout just as the ClassicFeedViewController did.
let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
// 3 The background color is set to white
view.backgroundColor = UIColor.white
return view
}()
//will fetch the comments from the database and append them to an array
fileprivate func fetchComments(){
comments.removeAll()
messagesRef = Database.database().reference().child("Comments").child(eventKey)
// print(eventKey)
// print(comments.count)
let query = messagesRef?.queryOrderedByKey()
query?.observe(.value, with: { (snapshot) in
guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else {
return
}
// print(snapshot)
allObjects.forEach({ (snapshot) in
guard let commentDictionary = snapshot.value as? [String: Any] else{
return
}
guard let uid = commentDictionary["uid"] as? String else{
return
}
UserService.show(forUID: uid, completion: { (user) in
if let user = user {
let commentFetched = CommentGrabbed(user: user, dictionary: commentDictionary)
commentFetched.commentID = snapshot.key
let filteredArr = self.comments.filter { (comment) -> Bool in
return comment.commentID == commentFetched.commentID
}
if filteredArr.count == 0 {
self.comments.append(commentFetched)
}
self.adapter.performUpdates(animated: true)
}else{
print("user is null")
}
self.comments.sort(by: { (comment1, comment2) -> Bool in
return comment1.creationDate.compare(comment2.creationDate) == .orderedAscending
})
self.comments.forEach({ (comments) in
})
})
})
}, withCancel: { (error) in
print("Failed to observe comments")
})
//first lets fetch comments for current event
}
//allows you to gain access to the input accessory view that each view controller has for inputting text
lazy var containerView: CommentInputAccessoryView = {
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 50)
let commentInputAccessoryView = CommentInputAccessoryView(frame:frame)
commentInputAccessoryView.delegate = self
return commentInputAccessoryView
}()
#objc func handleSubmit(for comment: String?){
guard let comment = comment, comment.count > 0 else{
return
}
let userText = Comments(content: comment, uid: User.current.uid, profilePic: User.current.profilePic!,eventKey: eventKey)
sendMessage(userText)
// will clear the comment text field
self.containerView.clearCommentTextField()
}
#objc func handleKeyboardNotification(notification: NSNotification){
if let userinfo = notification.userInfo {
if let keyboardFrame = (userinfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue{
self.bottomConstraint?.constant = -(keyboardFrame.height)
let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow
self.bottomConstraint?.constant = isKeyboardShowing ? -(keyboardFrame.height) : 0
if isKeyboardShowing{
let contentInset = UIEdgeInsetsMake(0, 0, (keyboardFrame.height), 0)
collectionView.contentInset = UIEdgeInsetsMake(0, 0, (keyboardFrame.height), 0)
collectionView.scrollIndicatorInsets = contentInset
}else {
let contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
collectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
collectionView.scrollIndicatorInsets = contentInset
}
UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completion) in
if self.comments.count > 0 && isKeyboardShowing {
let item = self.collectionView.numberOfItems(inSection: self.collectionView.numberOfSections - 1)-1
let lastItemIndex = IndexPath(item: item, section: self.collectionView.numberOfSections - 1)
self.collectionView.scrollToItem(at: lastItemIndex, at: UICollectionViewScrollPosition.top, animated: true)
}
})
}
}
}
override var inputAccessoryView: UIView? {
get {
return containerView
}
}
override var canBecomeFirstResponder: Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView.frame = CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height-40)
view.addSubview(collectionView)
collectionView.alwaysBounceVertical = true
adapter.collectionView = collectionView
adapter.dataSource = self
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
collectionView.register(CommentCell.self, forCellWithReuseIdentifier: "CommentCell")
// collectionView.register(CommentHeader.self, forCellWithReuseIdentifier: "HeaderCell")
collectionView.keyboardDismissMode = .onDrag
navigationItem.title = "Comments"
self.navigationItem.hidesBackButton = true
let backButton = UIBarButtonItem(image: UIImage(named: "icons8-Back-64"), style: .plain, target: self, action: #selector(GoBack))
self.navigationItem.leftBarButtonItem = backButton
}
#objc func GoBack(){
print("BACK TAPPED")
self.dismiss(animated: true, completion: nil)
}
//look here
func CommentSectionUpdared(sectionController: CommentsSectionController){
print("like")
self.fetchComments()
self.adapter.performUpdates(animated: true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
fetchComments()
tabBarController?.tabBar.isHidden = true
//submitButton.isUserInteractionEnabled = true
}
//viewDidLayoutSubviews() is overridden, setting the collectionView frame to match the view bounds.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// collectionView.frame = view.bounds
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension NewCommentsViewController: ListAdapterDataSource {
// 1 objects(for:) returns an array of data objects that should show up in the collection view. loader.entries is provided here as it contains the journal entries.
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
let items:[ListDiffable] = comments
//print("comments = \(comments)")
return items
}
// 2 For each data object, listAdapter(_:sectionControllerFor:) must return a new instance of a section controller. For now you’re returning a plain IGListSectionController to appease the compiler — in a moment, you’ll modify this to return a custom journal section controller.
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
//the comment section controller will be placed here but we don't have it yet so this will be a placeholder
// if let object = object as? ListDiffable, object === addHeader {
// return CommentsHeaderSectionController()
// }
let sectionController = CommentsSectionController()
sectionController.delegate = self
return sectionController
}
// 3 emptyView(for:) returns a view that should be displayed when the list is empty. NASA is in a bit of a time crunch, so they didn’t budget for this feature.
func emptyView(for listAdapter: ListAdapter) -> UIView? {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}
}
extension NewCommentsViewController {
func sendMessage(_ message: Comments) {
ChatService.sendMessage(message, eventKey: eventKey)
}
}
I did some debugging using both instruments and the debugger graph tool and it seems to be pointing me to my commentsSectionController
import UIKit
import IGListKit
import Foundation
import Firebase
protocol CommentsSectionDelegate: class {
func CommentSectionUpdared(sectionController: CommentsSectionController)
}
class CommentsSectionController: ListSectionController,CommentCellDelegate {
weak var delegate: CommentsSectionDelegate? = nil
var comment: CommentGrabbed?
let userProfileController = ProfileeViewController(collectionViewLayout: UICollectionViewFlowLayout())
var eventKey: String?
var dummyCell: CommentCell?
override init() {
super.init()
// supplementaryViewSource = self
//sets the spacing between items in a specfic section controller
inset = UIEdgeInsets(top: 5, left: 0, bottom: 0, right: 0)
}
// MARK: IGListSectionController Overrides
override func numberOfItems() -> Int {
return 1
}
specifically this function here
override func sizeForItem(at index: Int) -> CGSize {
let frame = CGRect(x: 0, y: 0, width: collectionContext!.containerSize.width, height: 50)
dummyCell = CommentCell(frame: frame)
dummyCell?.comment = comment
dummyCell?.layoutIfNeeded()
let targetSize = CGSize(width: collectionContext!.containerSize.width, height: 55)
let estimatedSize = dummyCell?.systemLayoutSizeFitting(targetSize)
let height = max(40+8+8, (estimatedSize?.height)!)
return CGSize(width: collectionContext!.containerSize.width, height: height)
}
override var minimumLineSpacing: CGFloat {
get {
return 0.0
}
set {
self.minimumLineSpacing = 0.0
}
}
override func cellForItem(at index: Int) -> UICollectionViewCell {
guard let cell = collectionContext?.dequeueReusableCell(of: CommentCell.self, for: self, at: index) as? CommentCell else {
fatalError()
}
// print(comment)
cell.comment = comment
cell.delegate = self
return cell
}
override func didUpdate(to object: Any) {
comment = object as? CommentGrabbed
}
override func didSelectItem(at index: Int){
}
func optionsButtonTapped(cell: CommentCell){
print("like")
let comment = self.comment
_ = comment?.uid
// 3
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
// 4
if comment?.uid != User.current.uid {
let flagAction = UIAlertAction(title: "Report as Inappropriate", style: .default) { _ in
ChatService.flag(comment!)
let okAlert = UIAlertController(title: nil, message: "The post has been flagged.", preferredStyle: .alert)
okAlert.addAction(UIAlertAction(title: "Ok", style: .default))
self.viewController?.present(okAlert, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let replyAction = UIAlertAction(title: "Reply to Comment", style: .default, handler: { (_) in
//do something here later to facilitate reply comment functionality
print("Attempting to reply to user \(comment?.user.username) comment")
})
alertController.addAction(replyAction)
alertController.addAction(cancelAction)
alertController.addAction(flagAction)
}else{
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let deleteAction = UIAlertAction(title: "Delete Comment", style: .default, handler: { _ in
ChatService.deleteComment(comment!, (comment?.eventKey)!)
let okAlert = UIAlertController(title: nil, message: "Comment Has Been Deleted", preferredStyle: .alert)
okAlert.addAction(UIAlertAction(title: "Ok", style: .default))
self.viewController?.present(okAlert, animated: true, completion: nil)
self.onItemDeleted()
})
alertController.addAction(cancelAction)
alertController.addAction(deleteAction)
}
self.viewController?.present(alertController, animated: true, completion: nil)
}
func onItemDeleted() {
delegate?.CommentSectionUpdared(sectionController: self)
}
func handleProfileTransition(tapGesture: UITapGestureRecognizer){
userProfileController.user = comment?.user
if Auth.auth().currentUser?.uid != comment?.uid{
self.viewController?.present(userProfileController, animated: true, completion: nil)
}else{
//do nothing
}
}
deinit {
print("CommentSectionController class removed from memory")
}
}
Here is a screenshot is what I saw in the debugger graph tool even when i leave the screen and check the debugger tool those blocks are still there.
So my question is does anyone see anything I don't see with the function. I really want to fix this memory leak. In addition to that this memory leak doesn't seem to be evident when I use my phone but when I use my simulator it is a huge memory leak....Any insight is greatly appreciated
Couple of things:
DatabaseReference's query observer that is owned by your ViewController is capturing self (your view controller). This makes a circle of ownerships which never let each other to deinit. This is called retain cycle.
Add [unowned self] or [weak self] to your completion block like so:
query?.observe(.value, with: { [weak self] (snapshot) in
// your code...
}
I used weak here because query is optional.
Remove notification observers when you no longer need them by calling NotificationCenter.default.removeObserver(self).
Shameless plug of my library: Consider Typist for managing keyboard in UIKit, it avoids any interaction with NotificationCenter and is super easy to setup and use.
Remove your notification Observer in viewWillDisappear method
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
You should use weak or unowned reference in closure, Like below
query?.observe(.value, with: { [unowned self] (snapshot) in
}
I believe you should rewrite this closure with [unowned self] (or weak):
UserService.show(forUID: uid, completion: { [unowned self] user in }
And as #Dhiru mentioned, you should remove all notification observers.

Logout delegate not working

I have an app that contains a central view controller with 3 child view controllers in a scrollview that represent sections of the app. General flow of my app goes as follows
LoginVC -> AppVC [Settings, Inbox, Email]
I currently have my logout button in my Settings view controller however the actual logout function needs to be in AppVC. I have tried implementing a delegate but cannot seem to get it working correctly
class Settings: UIViewController {
var delegate: LogoutDelegate?
#IBAction func logout(_ sender: Any) {
delegate?.logoutOfApp()
}
}
protocol LogoutDelegate: class {
func logoutOfApp()
}
----------------------------------
class AppVC: UIViewController, LogoutDelegate {
func logoutOfApp() {
print("This should be called")
//Execute logout code
}
}
Can anyone help me figure out why my delegate function isnt being called in my AppVC?
Update
This is how I set up my child view controllers in a scrollview
func setupViews() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let settingsVC = storyboard.instantiateViewController(withIdentifier: "SettingsVC")
let inboxVC = storyboard.instantiateViewController(withIdentifier: "InboxVC")
let emailVC = storyboard.instantiateViewController(withIdentifier: "EmailVC")
let viewControllers = [settingsVC, inboxVC, emailVC]
let width = scrollView.bounds.width
let height = scrollView.bounds.height
scrollView.contentSize = CGSize(width: width * 3, height: height)
var idx = 0
for vc in viewControllers {
addChildViewController(vc)
let originX = CGFloat(idx) * width
vc.view.frame = CGRect(x: originX, y: 0, width: width, height: height)
scrollView.addSubview(vc.view)
vc.didMove(toParentViewController: self)
idx += 1
}
scrollView.setContentOffset(CGPoint(x: width, y: 0), animated: false)
}
I am not sure where to set my delegate. I have tried to set it inside my for loop self.delegate = vc but always get the same error of not being able to set the delegate
The problem is that you never set the delegate, otherwise the delegate will always be nil and delegate?.logoutOfApp() won't be executed.
In AppVC, you need to do something like:
override func viewDidLoad() {
super.viewDidLoad()
settings.delegate = self
}

PopoverPresentationController delegate methods not called

I have a class to construct a UIPopoverPresentationController in an empty swift file:
import Foundation
import UIKit
class Popovers : NSObject, UIPopoverPresentationControllerDelegate {
func presentLoginScreen() {
// Presenting login Popover
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginScreen = storyboard.instantiateViewControllerWithIdentifier("LogInScreen")
let window = UIApplication.sharedApplication().windows.last!
let height = window.screen.bounds.size.height
let width = window.screen.bounds.size.width
loginScreen.modalPresentationStyle = UIModalPresentationStyle.Popover
loginScreen.preferredContentSize = CGSizeMake(width * 0.85 , height * 0.35)
let loginScreenPopover = loginScreen.popoverPresentationController
loginScreenPopover?.permittedArrowDirections = UIPopoverArrowDirection.init(rawValue: 0)
loginScreenPopover?.delegate = self
loginScreenPopover?.sourceView = window.rootViewController?.view
loginScreenPopover?.sourceRect = CGRectMake(CGRectGetMidX(window.screen.bounds), CGRectGetMidY(window.screen.bounds), 0, 0)
window.rootViewController?.presentViewController(loginScreen, animated: true, completion: nil)
let blur = UIVisualEffectView(effect: UIBlurEffect(style: .Light)) as UIVisualEffectView
let bounds = window.screen.bounds
blur.frame = bounds
blur.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
window.rootViewController!.view.addSubview(blur)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.None
}
func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
// Remove blur layer
print("method called")
let window = UIApplication.sharedApplication().windows.last
window?.subviews.last?.removeFromSuperview()
}
}
But whenever I dismiss the PopoverPresentationController the delegate method popoverPresentationControllerDidDismissPopover is never fired.
I have set the delegate of the loginScreenPopover to self and let the Popovers class inherit from the UIPopoverPresentationControllerDelegate but neither seems to be working.
It is on an iPhone, if that is relevant to the question.
I have found the answer. In the ViewDidLoad() from the LogInScreen I set the delegate to:
self.popoverPresentationController.delegate = getPopovers()
Where the getPopovers() function is a function to retrieve the Popover object created somewhere else in the code. Now in my Popovers class I can conform to the UIPopoverPresentationControllerDelegate and use those methods.

Resources