I share some contents using the following code
var textToShare = "Test"
let activityVC = UIActivityViewController(activityItems: [textToShare], applicationActivities: nil)
activityVC.excludedActivityTypes = [UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact]
presentViewController(activityVC, animated: true, completion: nil)
But when I press the cancel button or when the content is shared successfully, the App shows a blank screen.
How to fix this issue ?
UPDATE:
The blank screen just appears when I select mail or sms apps for the sharing target, For Telegram, Twitter and Facebook it is working perfect.
I commented all the code inside lifecycle methods, Still same issue.
override func viewDidAppear(animated: Bool)
{
//setControlsAreHidden(true)
}
override func viewWillAppear(animated: Bool)
{
//if dataAddedToView
//{
// activityIndicator?.removeFromSuperview()
//}
}
override func viewWillDisappear(animated: Bool)
{
//setControlsAreHidden(false)
}
I was having this same problem, and was able to solve it by adjust the sizing constraints of my primary UIView.
Code before:
override func loadView() {
self.view = UIView()
self.view.translatesAutoresizingMaskIntoConstraints = false
}
Code after:
override func loadView() {
self.view = UIView()
}
So just remove self.view.translatesAutoresizingMaskIntoConstraints = false
This might not apply to everyone, but based on other peoples' answers, I gather there are various issues with how views are displayed which can cause the same problem. If my fix doesn't work for you, I suggest commenting out all unnecessary code until the problem goes away, and then methodically bring small bits back online, testing along the way to identify your issue.
As you are presenting MFMailComposeViewController and MFMessageComposeViewController above your current UIViewController so when you dismiss the MFMailComposeViewController or MFMessageComposeViewController after sending the message then your UIViewController viewWillAppear method will be called as the view is appearing again, so in my opinion check in viewWillAppear or viewWillDisappear method whether you are making your view nil.
I don't see any calls to the super implementation in your viewDidAppear, viewWillAppear or viewWillDisappear methods.
What happens if you do?:
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
//setControlsAreHidden(true)
}
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
//if dataAddedToView
//{
// activityIndicator?.removeFromSuperview()
//}
}
override func viewWillDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
//setControlsAreHidden(false)
}
Maybe you're not presenting the activity view controller in the proper view, try something like this:
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")){
activityViewController.popoverPresentationController.sourceView = self.view;
}
It's a objective C code, but just as example of how to set the view.
If you need how to check the iOS version:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
You need to first check that your view controller is not being destroyed while you're presenting content. Some debug statements in the presenting view controller's lifecycle management routines (e.g., ViewWillDisappear) could help.
If the problem stems from the ViewController disappearing, you'll need to recreate it appropriately.
Also look at any place where you provide content: is it being triggered to draw at the right times?
Additionally, ensure you're using APIs as required (e.g., calling the superclass in all methods where it's required, such as the view controller lifecycle routines). See:
SO ViewController methods question
SO ViewController lifecycle question
Apple UIViewController reference (latest)
These are the areas I would focus my attention on and/or provide the relevant code for.
Related
I have weird situation and have no clue how to debug it. I load three viewControllers in navigation controller. When Im navigating back from there second and first ViewController doesn't display anything just white screen I added print methods everywhere in lifecycle methods and it seems that it loads views but anyway they not visible. What could be the problem?
Yep It's weird, There maybe some code which do something with your view on such events like:
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// remove some subviews or change constraints.
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// remove some subviews or change constraints.
}
Please send us a code of the view controller which has the problems and code how exactly you show the controller.
I have a basic app with a UITabBarController as the root view controller. When a user of the app is not signed in I'm showing a modal controller via window!.rootViewController!.present(viewController, animated: true) in my AppDelegate. This works fine on all iPhone models, however the following happens on any iPad:
The background color of the SignInController is visible during the transition. Now comes the weird thing: When I change the view in Interface Builder to an iPad the bug is gone like so:
Changing the background color back to the transparent default removes at least the white background, however the view is still animating from the left bottom which is something I don't want. And by the way, changing the view in Interface Builder breaks the animation on all iPhones. Changing it back fixes it but breaks again all iPads.
This is the code (using ReSwift for state management):
func newState(state: State) {
switch (previousState.session, state.session) {
case (.loading, .notSignedIn), (.signedIn, .loading):
(window!.rootViewController! as! UITabBarController).selectedIndex = 0
let viewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController")
window!.rootViewController!.present(viewController, animated: true, completion: nil)
default:
// more stuff
break
}
}
EDIT: Added the actual code.
I fixed it! 😊
The problem was a combination of having an observer on keyboardWillShowNotification and a becomeFirstResponder in the viewWillAppear method of the presented controller.
Moving the becomeFirstResponder into viewDidAppear fixed all the problems!
Thanks man! Saved my day.. I'm presenting the keyboard from within a tableview cell - I fixed it like this:
private var canPresentKeyboard: Bool = false
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
canPresentKeyboard = true
if _currentlySelectedIdType != .image {
reload(section: .idType)
}
}
func configure(cell: NumberIdTableViewCellInput) {
cell.set(delegate: self)
if canPresentKeyboard {
cell.clearAndSetFirstResponder()
}
}
I know the code is a bit out of context, but I believe the intention is clear.
I'm having a weird behaviour here. I have a UITableView inside a UIViewController that is contained in a UITabBarController.
It's working fine all the time, except when I receive a notification from iMessage and open it. Then if I go back to the app using the top left < MyApp, then the UITableView delegate (more specifically the didSelectRow method) is not called anymore but I'm still able to scroll it.
If I receive notifications from other apps (like Duolingo and Inbox), open it and go back to app, it works fine, except with iMessage.
Has this happened to anyone here before?
I'm using Swift 3 and Xcode 8.1.
Thanks
UPDATE
Here are some methods:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Here i'm just updating the navigation bar color
if let navBar = self.navigationController?.navigationBar as? NavigationBar {
navBar.apply(color: colorRGB(33, 163, 161))
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Just making navbar trasnparent
if let navBar = self.navigationController?.navigationBar as? NavigationBar {
navBar.applyTransparency()
}
}
The table view is created in the storyboard and data source and delegate is assigned there too.
I have some code I call that changes the language in the viewWillAppear section of a viewcontroller inside a navigation controller.
When I hit the back button the language change doesn't take place even though I have code for it to in the viewWillAppear. The only time it switches is when I hit back all the way to the original screen and then start moving forward it changes. Is there any way to have the function in the viewWillAppear work?
Here is my code, I'm using a language changing pod:
//MARK: Language change
//used to change language text for imediate screens
func setText(){
locationsLabel.text = "Locations".localized()
languageLabel.text = "Languages".localized()
termsOfUseLabel.text = "Terms of Use".localized()
privacyPolicyLabel.text = "Privacy Policy".localized()
pushNotificationsLabel.text = "Push Notifications".localized()
contactUsLabel.text = "Contact Us".localized()
}
// Changes text to current language
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "setText", name: LCLLanguageChangeNotification, object: nil)
}
// Remove the LCLLanguageChangeNotification on viewWillDisappear
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
The viewWillAppear method is only adding a notification observer. The observer is removed in viewWillDisappear. This means that setText will only be called if the LCLLanguageChangeNotification notification is sent while the view is visible.
The update stops as soon as the view goes off-screen due to the navigation behaviour.
To ensure that the text is updated, you also need to call setText inside viewWillAppear:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
setText()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "setText", name: LCLLanguageChangeNotification, object: nil)
}
Implement navigationcontroller delegate methods
navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
I have created this little class that solves this problem.
Just set it as a delegate of your navigation controller, and implement simple one or two methods in your view controller - that will get called when the view is about to be shown or has been shown via NavigationController
Here's the GIST showing the code
I have some cleanup that needs to be performed in a shared resource any time one of my view controllers is dismissed/popped/unloaded? This could either be when the user hits the back button on that individual screen or if a call to popToRootViewController is made (in which case, I would ideally be able to clear up every controller that was popped.)
The obvious choice would be to do this in viewDidUnload, but of course, that isn't how unload works. Is there a way to catch all cases to where the ViewController is removed from the stack?
edit:Forgot to mention that I am doing this using Xamarin so that may or may not impact the answers.
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
if (isBeingDismissed() || isMovingFromParentViewController()) {
// clean up code here
}
}
EDIT for swift 4/5
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if (isBeingDismissed || isMovingFromParent) {
// clean up code here
}
}
-dealloc is probably your best bet. The view controller will be deallocated when it is popped from the stack, unless you are retaining it elsewhere.
viewWillDisappear: and viewDidDisappear: aren't good choices because they are called any time the view controller is no longer shown, including when it pushes something else on the stack (so it becomes second-from-the-top).
viewDidUnload is no longer used. The system frameworks stopped calling this method as of iOS 6.
Building upon #Enricoza's comment, if you do have your UIViewController embedded in a UINavigationController, try this out:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if ((navigationController?.isBeingDismissed) != nil) {
// Add clean up code here
}
}