Paste the following code into a project:
No image shows next to 'Device Honey' ie the UIMenu
However the image shows up next to 'Copy' ie the UIACtion
.
Am I doing something wrong? If this is a bug? Is there a workaround?
class ViewController: UIViewController {
let tableview: UITableView = {
let tv = UITableView()
tv.frame = UIScreen.main.bounds
return tv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableview)
tableview.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableview.delegate = self
tableview.dataSource = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if cell.detailTextLabel == nil {
cell = UITableViewCell(style: .value1, reuseIdentifier: "cell")
}
cell.textLabel?.text = "Honey"
cell.detailTextLabel?.text = "iOS developer"
return cell
}
@available(iOS 13.0, *)
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { suggestedActions in
return self.makeContextMenu(for: indexPath)
})
}
@available(iOS 13.0, *)
func makeContextMenu(for indexPath: IndexPath) -> UIMenu? {
let copyAction = UIAction(title: "Copy", image: UIImage(systemName: "square.and.arrow.up")) { [weak self] _ in
guard let self = self else { return }
let cell = self.tableview.cellForRow(at: indexPath)
let pasteboard = UIPasteboard.general
pasteboard.string = cell?.detailTextLabel?.text
}
guard let cell = self.tableview.cellForRow(at: indexPath), let title = cell.textLabel?.text else { return nil}
return UIMenu(title: "Device \(title) ", image: UIImage(systemName: "square.and.arrow.up"), children: [copyAction])
}
}
In Apple's WWDC demo they're able to do it as shown below:
A context menu has two parts: the preview and the menu. Both are optional. The "groceries" thing in the Apple screenshot is the preview, not the menu. By default, the cell is snapshotted and the snapshot is displayed as the preview. The menu itself in the Apple screenshot has no image and no title. And that's what you should do too! The last line
return UIMenu(...
...should have no title and no image. This menu, the one that wraps everything else and is returned, is the top-level menu, and it is displayed differently (as your own screenshot shows). It looks best without a title, and it cannot display an image at all. Its job is to wrap everything else and to provide an identifier, and that's all.
You will then get something like this: