UIPopoverController getting crashing in iPhone in swift - iphone

I am working with the UIPopViewController.I have a BarButton with add option.If I click on the ‘+’ popup has to come.It is working fine when I gave connection in storyBoard.But If I am calling using the code,it is not working.It is crashing..My code is like this..
#IBAction func addingData(sender: AnyObject) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let playerInformationViewController = storyboard.instantiateViewControllerWithIdentifier("PopView") as? PopView
playerInformationViewController!.modalPresentationStyle = .Popover
playerInformationViewController!.preferredContentSize = CGSizeMake(300, 300)
playerInformationViewController!.delegate = self
let popoverPresentationViewController = playerInformationViewController!.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem
presentViewController(playerInformationViewController!, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "test" {
let popoverViewController = segue.destinationViewController
popoverViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
popoverViewController.popoverPresentationController!.delegate = self
}
}
The error Message I am getting is …
UIPopoverPresentationController: 0x7fdda8cd4ad0>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.’**
Can anyone tell me what mistake I did.Please clarify my doubt.
Thanks in Advance.

Related

How to write func..(for sequels: UIStoryboardSeque, sender: Any?) programmatically

I have these codes when I use storyboard:
override func prepare (for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == ProfilePhotoViewController.identifier {
guard let username = usernameTextField.text, let email = emailTextField.text, let password = passwordTextField.text else { return }
let profilePhotoVC = segue.destination as! ProfilePhotoViewController
profilePhotoVC.email = email
profilePhotoVC.username = username
profilePhotoVC.password = password
}
}
How do I write these code if I don't use storyboard and write them programmatically in order to pass the info from current controller to ProfilePhotoViewController?
EDIT:
After doing research I understand that doing this programmatically is through delegate. However, I don't know how I can complete the code:
Need to pass username, email and password from SignUpController ---> profilePhotoViewController
in SignUpController:
protocol SignUpControllerDelegate {
func handleSignUp(//what should I write here?)
}
var delegate: SignUpControllerDelegate?
#objc func handleSignUp() {
//...other code..//
delegate?.handleSignUp(//??)
}
In ProfileViewController:
what should I write to receive the username, email and password info from SignUpController?
We can create a view controller with/without a NIB file.
With NIB, you use init(nibName: String?, bundle: Bundle?) method. In this case, view will be defined using Interface Builder.
// bundle = nil denote the main bundle
let viewController = MyViewController(nibName:"MyViewController", bundle: nil)
Also you can define a custom UIViewController subclass without a NIB file and implement loadView() method.
override func loadView() {
self.view = UIView(...)
}
After that, we need to add the view into the view hierarchy.
self.view.addSubview(viewController.view);
// or
self.present(viewController, animated: false, completion: nil)
// or if we have UINavigationController
self.navigationController?.pushViewController(viewController, animated: false)
Try like this
guard let username = usernameTextField.text, let email = emailTextField.text, let password = passwordTextField.text else { return }
let profileVC = ProfilePhotoViewController()
profileVC.email = email

Taking a picture and passing it to a different UIViewController Swift 3.0

I'm trying to take an image in my app so I can save it to my device and pass it to the next view controller to be previewed. The way I see people doing this is storing the image they take in a uiimage. Then during prepareforsegue they set the uiimage variable in the destination view controller to the photo you took in the previous view controller. From there in the dest view controller I see people displaying the image as follows : imageName.image = imageVariable . When I pass the variable to the destination view controller and try to display it in the next view controller it appears as a nil value. Where am I going wrong?
First ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ToDetailPage" {
let nextScene = segue.destination as! PostDetailPageViewController
nextScene.itemImage = self.image
// nextScene?.myimg.image = self.image
}
}
#IBAction func TakePhotoButtonClicked(_ sender: AnyObject) {
if let videoConnection = sessionOutput.connection(withMediaType: AVMediaTypeVideo){
sessionOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: {
buffer, error in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
self.image = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData!)!, nil, nil, nil)
})
}
}
Second ViewController:
var itemImage: UIImage!
#IBOutlet weak var myimg: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.categories.dataSource = self;
self.categories.delegate = self;
setUpMap()
myimg.image = itemImage
}
You need to push viewController inside the block. Actually what is happening in this code the completion block is called after prepareForSegue. So your image is always 'nil'.
Try to push the viewController like this:
if let videoConnection = sessionOutput.connection(withMediaType: AVMediaTypeVideo){
sessionOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: {
buffer, error in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(buffer)
self.image = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(UIImage(data: imageData!)!, nil, nil, nil)
// push view controller here
let destinationVC = SecondViewController()
destinationVC.image = self.image
self.navigationController.pushViewController(destinationVC, animated: true)
})
}
Hope it will help you.. Happy Coding!!

How can I pass Data to multi ViewController in swift

I want to pass Data from for example ViewController "A" to ViewController "B" and pass another Data from "A" to "C" when for example "OK" button tapped . How can I do that ?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
println("YES")
var mojodiTemp : B = segue.destinationViewController as B println("NO")
mojodiTemp.tempMojoodi = mablagh.text!
var HesabeHarFard : C = segue.destinationViewController as C
HesabeHarFard.person = person
HesabeHarFard.year = year
HesabeHarFard.month = month
HesabeHarFard.day = day
}
There is a detailed example in this post:
Best temporary storage measure
In summary:
use performSegueWithIdentifier and also use prepareForSegue to support it as shown below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "segueTitle") {
// pass data to next view
let destinationVC = segue.destinationViewController as! YourNextViewController
destinationVC.transferObject = self.transferObject;
}
}
First create dataToPass class variable/property in viewControllerB and C with appropriate dataType and follow the steps below:
SOLUTION 1:
//IN ViewControllerA write following function before creating that you need segues from A to B and A to C with identifiers for each.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "identifierForB" {
let instanceOfViewControllerB = segue.destinationViewController as! ViewControllerB
instanceOfViewControllerB.dataToPass = dataOne
} else if segue.identifier == "identifierForC" {
let instanceOfViewControllerC = segue.destinationViewController as! ViewControllerC
instanceOfViewControllerB.dataToPass = nextData
}
}
SOLUTION 2:
If you go to ViewControllerB or C by code: do like this: (keep like this code in action of OK button pressed)
//First you need to give storyboard id to view controller associated with ViewControllerB and C then in action function of OK button
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
if (showViewControllerB == true) {
let instanceOfViewControllerB = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerBIdentifier") as! ViewControllerB
instanceOfViewControllerB.dataToPass = dataOne
self.presentViewController(instanceOfViewControllerB, animated: true, completion: nil)
} else if showViewControllerC == true {
let instanceOfViewControllerC = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerCIdentifier") as! ViewControllerC
instanceOfViewControllerC.dataToPass = dataOne
self.presentViewController(instanceOfViewControllerC, animated: true, completion: nil)
}
SOLUTION 3
You create two properties in class A:
var vcB: B!
var vcC: C!
keep if just below the definition of class A
now on OK button clicked:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
vcB = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerBIdentifier") as! ViewControllerB
vcB.dataToPass = dataOne
vcC = storyBoard.instantiateViewControllerWithIdentifier("ViewControllerCIdentifier") as! ViewControllerC
vcC.dataToPass = dataOne
Be sure to present vcC when you want to open C view controller in screen and be sure to present vcB when you want to open B view controller.
when you click button or from trigger to show view of C: just put following code in function/Action:
self.presentViewController(vcC, animated: true, completion: nil)
when you click button or from trigger to show view of B: just put following code in function/Action:
self.presentViewController(vcB, animated: true, completion: nil)
HOPE THIS IS WHAT YOU WANT, Is It?

How to load popover in swift

I am trying to get a popover working in swift.
The view i am trying to put into the popover is in its own separate xib.
The code to load is below
let view = OrganisationDetails()
view.modalPresentationStyle = .Popover
let popoverMenuViewController = view.popoverPresentationController
view.preferredContentSize = CGSizeMake(550,550)
popoverMenuViewController?.permittedArrowDirections = .Any
popoverMenuViewController?.delegate = self
popoverMenuViewController?.sourceView = sender
popoverMenuViewController?.sourceRect = CGRect(x: 1, y: 1, width: 60, height: 60)
presentViewController(view, animated: true, completion: nil)
What is happening atm is the popover is loading totally blank and not displaying the view.
Any ideas what I'm doing wrong
Thanks
Actually it is much simpler than that. In the storyboard you should make the viewcontroller you want to use as popover and make a viewcontroller class for it as usual. Make a segue as shown below from the object you want to open the popover, in this case the UIBarButton named "Config".
In the "mother viewcontroller" implement the "UIPopoverPresentationControllerDelegate" and the delegate method:
func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
//do som stuff from the popover
}
Override the "prepareForSeque" method like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//segue for the popover configuration window
if segue.identifier == "yourSegueIdentifierForPopOver" {
if let controller = segue.destinationViewController as? UIViewController {
controller.popoverPresentationController!.delegate = self
controller.preferredContentSize = CGSize(width: 320, height: 186)
}
}
}
And your done. And you can now treat the popover view as any other view, ie. add fields and what not!
This is how I do it
//MARK:idPopupFileTable
let popoverVC = storyboard?.instantiateViewControllerWithIdentifier("idPopupFileTable") as UIViewController
popoverVC.modalPresentationStyle = .Popover
popoverVC.preferredContentSize = CGSizeMake(300, 200)
if let popoverController = popoverVC.popoverPresentationController {
popoverController.sourceView = sender
popoverController.sourceRect = sender.bounds
popoverController.permittedArrowDirections = .Any
popoverController.delegate = self
}
presentViewController(popoverVC, animated: true, completion: nil)
}

UIPopoverController, Xcode 6, IOS 8 using Swift

I'm having some trouble getting a UIPopover to appear using swift. The code that is commented out works fine in Objective-C, but doesn't work using Swift. When I tap the + in my view controller I do get the "click" in my debugger, however no popover appears.
class PlayerInformationTableViewController: UITableViewController, NSFetchedResultsControllerDelegate, UIPopoverControllerDelegate {
#IBOutlet weak var addBarButtonItem: UIBarButtonItem!
var playerInformationViewController = PlayerInformationViewController()
var popover:UIPopoverController? = nil
override func viewDidLoad() {
super.viewDidLoad()
/*
//setup the popover
_cuesPopoverViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"CuesPopoverViewController"];
self.cuesPopover = [[UIPopoverController alloc] initWithContentViewController:_cuesPopoverViewController];
self.cuesPopover.popoverContentSize = CGSizeMake(540, 300);
self.cuesPopover.delegate = self;
*/
playerInformationViewController.storyboard?.instantiateViewControllerWithIdentifier("PlayerInformationViewController")
popover?.contentViewController = playerInformationViewController
popover?.popoverContentSize = CGSizeMake(300, 300)
popover?.delegate = self
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
#IBAction func addPopover(sender: AnyObject) {
println("Click")
popover?.presentPopoverFromBarButtonItem(addBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
Solution
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addPopover(sender: AnyObject) {
var popoverViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PlayerInformationViewController") as UIViewController
popoverViewController.modalPresentationStyle = .Popover
popoverViewController.preferredContentSize = CGSizeMake(450, 450)
let popoverPresentationViewController = popoverViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationViewController?.barButtonItem = sender as UIBarButtonItem
presentViewController(popoverViewController, animated: true, completion: nil)
}
Here is a simple example for iOS 8. Popover are presented using adaptivity apis in iOS 8.
class PlayerInformationTableViewController: UITableViewController, UIPopoverPresentationControllerDelegate, NSFetchedResultsControllerDelegate{
...
#IBAction func addPopover(sender: UIBarButtonItem){
let playerInformationViewController = PlayerInformationViewController()
playerInformationViewController.modalPresentationStyle = .Popover
playerInformationViewController.preferredContentSize = CGSizeMake(300, 300)
let popoverPresentationViewController = playerInformationViewController.popoverPresentationController
popoverPresentationViewController?.permittedArrowDirections = .Any
popoverPresentationViewController?.delegate = self
popoverPresentationController?.barButtonItem = sender
presentViewController(playerInformationViewController, animated: true, completion: nil)
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle{
return .None
}
}
Display Popover with contentView from xib
func showPopover(sender: AnyObject) {
let contentViewController = UINib(nibName: "ContentVC", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as ContentVC
contentViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
var detailPopover: UIPopoverPresentationController = contentViewController.popoverPresentationController!
detailPopover.delegate = self
detailPopover.barButtonItem = sender as UIBarButtonItem
detailPopover.permittedArrowDirections = UIPopoverArrowDirection.Any
presentViewController(contentViewController,
animated: true, completion:nil)
}
Next allows to make not full screen PopoverView on iPhone
for this do not forget to inherit MainViewController: UIPopoverPresentationControllerDelegate and set delegate to PopoverView
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController!) -> UIModalPresentationStyle
{
return .None
}
It looks like your popover is nil. Where are you assigning/instantiating it?
Try changing this:
popover?.presentPopoverFromBarButtonItem(addBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
To this:
if let pop = popover {
pop.presentPopoverFromBarButtonItem(addBarButtonItem, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
} else {
NSLog("Error: Popover was nil")
}
I imagine you'll see that error message in your console. In the .XIB for your PlayerInformationTableViewController, do you have a UIPopoverController?
If so, you probably need to ensure that the var popover is either (1) being manually instantiated in your awakeFromNib, or that it's an #IBOutlet and is being connected properly.
Alternatively, can you simply use the popover already present in your playerInformationViewController?