I am using XLPagerStrip to show two tabs. I have a search bar to search on each ViewController. I have I filter button that should be clicked from ViewcontrollerOne to change the visibility of a UIView in ViewControllerTwo. Here is what I have implemented but I'm getting
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional on the view
ViewcontrollerOne
viewControllerTwo.getFilterStatus(status: isFilter)
ViewControllerTwo
func getFilterStatus(status: Bool){
if (status) {
viewFilter.isHidden = false
} else {
viewFilter.isHidden = true
}
}
I have a service class, AuthManager, that has a method in it as below:
public func logoutAuth(from viewController: UIViewController, completion:((_ result: Bool) -> Void)? = nil) {
let logoutString = "\(self.oAuthBaseServerURL)/logout.jsp"
// Present the Sign Off ViewController
if let logoutURL = URL(string: logoutString) {
let logoutController = SFSafariViewController(url: logoutURL)
let logoutDelegate = SFSafariViewDelegate(completion: completion)
logoutController.delegate = logoutDelegate
viewController.present(logoutController, animated: true, completion: nil)
}
}
I call this service from an instance of it (singleton in a global state) in my view controller like this:
GlobalState.AUTHMANAGER().logoutAuth(from: self, completion: self.completeLogout)
However, I am getting this error:
[Warning] Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<SFSafariViewController: 0x7ff9b1060800>)
I'm not sure why that is deallocating too early. I've tried making the SFSafariViewController an instance variable and assigning it in the method instead, which yields the same error.
i am trying to use UIImagepickerController to pick an image from photos.
I am using the function below in my gameScene class
(this is for importing images into a game)
But I get the error "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
on this line
self.view!.window!.rootViewController!
the function is below. I am not sure how to fix it and have searched for an answer without much luck, so any help would be great.
func getPhotoFromSource(source:UIImagePickerControllerSourceType ){
if UIImagePickerController.isSourceTypeAvailable(source)
{
let imagePicker = UIImagePickerController()
imagePicker.modalPresentationStyle = .currentContext
imagePicker.delegate = self
imagePicker.sourceType = source
imagePicker.allowsEditing = false
if (source == .camera){
imagePicker.cameraDevice = .front
}
let vc:UIViewController = self.view!.window!.rootViewController! //Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
vc.present(imagePicker, animated: true, completion: nil)
} }
instead of
let vc:UIViewController = self.view!.window!.rootViewController!
, use optional chaining and try
guard let vc = self.view?.window?.rootViewController else {
print("something went wrong")
}
Seeing how it's either your view or your window or your rootViewController that's not there when you try to force unwrap, if you run the code above your code will just run the print statement above.
Can you share your code for setting up your viewController?
I have application that works well on ios8. However after updating everything to ios9 I am having problem with nill values. I cant figure out what value is nil. Here is the code:
func resetToChosenPage(index: Int!) {
/* Getting the page View controller */
pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
self.pageViewController.dataSource = self
pageContentViewController = self.viewControllerAtIndex(index)
if pageContentViewController != nil {
self.pageViewController.setViewControllers([pageContentViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
}
/* We are substracting 30 because we have a start again button whose height is 30*/
self.pageViewController.view.frame = CGRectMake(0, self.navigationController!.navigationBar.frame.height , self.view.frame.width, self.view.frame.height - 30)
self.addChildViewController(pageViewController)
self.view.addSubview(pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
}
func viewControllerAtIndex(index : Int) -> UIViewController? {
if((dataArray.count == 0) || (index >= dataArray.count)) {
return nil
}
let pageContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("SingleArticleViewController") as! SingleArticleViewController
self.delegate = pageContentViewController
pageContentViewController.delegate = self
// pageContentViewController.delegateWebView = self
pageContentViewController.singleArticleIndex = index
pageContentViewController.categoryID = categoryID
pageContentViewController.dateOfPub = dataArray[index].pubDate
pageContentViewController.category = dataArray[index].category
pageContentViewController.newsTitle = dataArray[index].pageTitle
pageContentViewController.videoLink = dataArray[index].videoLink
return pageContentViewController
}
One line self.pageViewController.SetViewControllers([pageContentViewController]... I have error "fatal error: unexpectedly found nil while unwrapping an Optional value". The fact is this code works well on ios8. I checked and could not find nil values. Moreover, I checked all identifiers of storyboard but they are correct. Guys, what can be a problem if this code works on ios8?
I suggest try changing the if clause that wraps the setViewControllers: call so that it explicitly checks for both the pageContentViewController and the pageViewController:
if let pageVC = self.pageViewController, let contentVC = self.pageContentViewController {
pageVC.setViewControllers([contentVC], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
}
As a general thing, I would try to avoid using Implicitly Unwrapped Optionals (like that Int! in your resetToChosenPage: method. As they lead to these 'unexpectedly found nil' errors.
Also, since your resetToChosenPage: method doesn't check if the pageViewController has already been instantiated, calling it multiple times will result in many instances of the PageViewController being instantiated and piled on top of each other. Which is probably not what you want.
Good day guys, I'm learning Swift, needed some help here.
The user are signing up and selected their image. Upon dismissing the image picker, I would like to have the ComposeViewController appear.
Here is the code:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: NSDictionary!) {
let pickedImage:UIImage = info.objectForKey(UIImagePickerControllerOriginalImage) as UIImage
//Scale Down Image
let scaledImage = self.scaleImageWith(pickedImage, and: CGSizeMake(100,100))
let imageData = UIImagePNGRepresentation(scaledImage)
let imageFile:PFFile = PFFile(data: imageData)
PFUser.currentUser().setObject(imageFile, forKey: "profileImage")
PFUser.currentUser().saveInBackgroundWithTarget(nil, selector: nil)
picker.dismissViewControllerAnimated(true, completion: nil)
//this is the line seems to have problem.
self.navigationController?.popToViewController(ComposeViewController, animated: true)
}
Then I got these error:
ComposeViewController.Type' is not convertible to 'UIViewController
Expected member name or constructor call after type name
It has suggestion to fix by putting () after ComposeViewController but then it gives out more errors after fixing.
Hope someone could help. Thanks! :-)
let controllers = self.navigationController?.viewControllers
for vc in controllers! {
if vc is YourVC {
_ = self.navigationController?.popToViewController(vc as! YourVC, animated: true)
}
}
I know this is old, but it's like what Saqib said, you can't pop to a viewcontroller that doesn't exist yet.
A lot of the answers here seem to be from people that didn't read your question, just the title. I'll leave this code here in case it helps anyone.
let vcIndex = self.navigationController?.viewControllers.indexOf({ (viewController) -> Bool in
if let _ = viewController as? ComposeViewController {
return true
}
return false
})
let composeVC = self.navigationController?.viewControllers[vcIndex!] as! ComposeViewController
self.navigationController?.popToViewController(composeVC, animated: true)
There's a method that lets you get access to an array of all the ViewControllers on the current stack, and you can capture the one you want by using its index, for instance:
let switchViewController = self.navigationController?.viewControllers[1] as! ComposeViewController
self.navigationController?.popToViewController(switchViewController, animated: true)
if let composeViewController = self.navigationController?.viewControllers[1] {
self.navigationController?.popToViewController(composeViewController, animated: true)
}
I ended up replaceing the following code inside the main view and it works. I'm not sure if this is the right way, would you mind giving me some comments?
//self.navigationController?.popToViewController(ComposeViewController, animated: true)
let switchViewController = self.storyboard?.instantiateViewControllerWithIdentifier("view2") as ComposeViewController
self.navigationController?.pushViewController(switchViewController, animated: true)
I defined "view2" as the destination storyboard ID.
What I found more useful was to do a first lookup with viewControllers, that way you get the first instance you find in the stack, without having to guess the actual index.
e.g.
let mainViewControllerVC = self.navigationController?.viewControllers.first(where: { (viewcontroller) -> Bool in
return viewcontroller is ComposeViewController
})
if let mainViewControllerVC = mainViewControllerVC {
navigationController?.popToViewController(mainViewControllerVC, animated: true)
}
For Swift 4.0 and above Using Filter
guard let VC = self.navigationController?.viewControllers.filter({$0.isKind(of: YourViewController.self)}).first else {return}
self.navigationController?.popToViewController(VC, animated: true)
navigation controller maintains the stack of views you are pushing. Its like a Last in first out queue.
In order to pop to ComposeViewController, that view must already exist in the queue and you should have reference to it.
You will need to pass the instance of ComposeViewController. for simplicity you might save that reference in appdelegate. (this approach is not recommended)
for (var i = 0; i < self.navigationController?.viewControllers.count; i++)
{
if(self.navigationController?.viewControllers[i].isKindOfClass(DestinationViewController) == true)
{
self.navigationController?.popToViewController(self.navigationController!.viewControllers[i] as! DestinationViewController, animated: true)
break;
}
}
In Swift 4.1 and Xcode 9.4.1
Suppose if you moved from 1st ViewController to 2nd, then 2nd to 3rd. Now if you want to come back from 3rd to 1st directly this code is enough.
if let composeViewController = self.navigationController?.viewControllers[1] {//Here you mention your view controllers index, because navigation controller can store all VC'c in an array.
print(composeViewController)
self.navigationController?.popToViewController(composeViewController, animated: true)
}