I\'m using popoverPresentationController
to show my popover. The UITableViewController
used to show as popover is created programmatically and will usu
First thing first: All comments are good and help full. I have did little change in my logic which makes my VC as reusable component.
Calling this method inside viewWillAppear:(BOOL)animated
:
-(void) setPopOverPreferedContentHeight {
if (self.popoverPresentationController && self.tableView.contentSize.height < MAX_POPOVER_HEIGHT) {
self.preferredContentSize=self.tableView.contentSize;
} else if (self.popoverPresentationController){
self.preferredContentSize = CGSizeMake(self.tableView.contentSize.width, MAX_POPOVER_HEIGHT);
}
}
For swift 4 if you want to observe the content size I found this to be the optimal solution. Reporting it here since I did not find a complete example online:
class MyTableViewController: UITableViewController {
private var kvoContext = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addObserver(self, forKeyPath: #keyPath(tableView.contentSize), options: .new, context: &kvoContext)
}
override func viewDidDisappear(_ animated: Bool) {
removeObserver(self, forKeyPath: #keyPath(tableView.contentSize))
super.viewDidDisappear(animated)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &kvoContext, keyPath == #keyPath(tableView.contentSize),
let contentSize = change?[NSKeyValueChangeKey.newKey] as? CGSize {
self.popoverPresentationController?.presentedViewController.preferredContentSize = contentSize
}
}
}
In your UITableViewController's viewDidLoad()
you can add an observer:
self.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
Then add this method:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
self.preferredContentSize = tableView.contentSize
}
Lastly, in viewDidDisappear()
, make sure you remove the observer:
tableView.removeObserver(self, forKeyPath: "contentSize")
This way the popover will automatically adjust size to fit the content, whenever it is loaded, or changed.
Checkout the preferredContentSize property of UIViewController:
let height = yourDataArray.count * Int(popOverViewController.tableView.rowHeight)
popOverViewController.preferredContentSize = CGSize(width: 300, height: height)
Override the preferredContentSize
property in your extension of the uitableviewcontroller
as following:
override var preferredContentSize: CGSize {
get {
let height = calculate the height here....
return CGSize(width: super.preferredContentSize.width, height: height)
}
set { super.preferredContentSize = newValue }
}
For calculating the height check out tableView.rectForSection(<#section: Int#>)
Simple dynamic answer for Swift 4.x and Swift 5.x involving no size-computation (modern version of Bo Frese answer):
private var contentSizeObserver : NSKeyValueObservation?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
contentSizeObserver = tableView.observe(\.contentSize) { [weak self] tableView, _ in
self?.preferredContentSize = CGSize(width: 320, height: tableView.contentSize.height) // Here I fixed the width but you can do whatever you want
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
contentSizeObserver?.invalidate()
contentSizeObserver = nil
}