How to get parent splitviewcontroller from view(xib) - swift

I'm currently able to achieve this with Storyboards using:
var parentSplit : NSSplitViewController? {
guard let splitVC = parent as? NSSplitViewController else { return nil }
return splitVC
}
but it returns nil if I try it in a xib file. My view is a subview in a SplitView.

Related

XCode Preview Error: "Replaced Accessor for 'keyWindow'"

Adding the some code to one of my files in XCode causes the following error to show when trying to run previews for that file:
Compiling failed: replaced accessor for 'keyWindow' occurs in multiple places.
The error only happens when the following code is used in the file:
extension UIApplication {
var keyWindow: UIWindow? {
return UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.first(where: { $0 is UIWindowScene })
.flatMap({ $0 as? UIWindowScene })?.windows
.first(where: \.isKeyWindow)
}
var keyWindowPresentedController: UIViewController? {
var viewController = self.keyWindow?.rootViewController
if let presentedController = viewController as? UITabBarController {
viewController = presentedController.selectedViewController
}
while let presentedController = viewController?.presentedViewController {
if let presentedController = presentedController as? UITabBarController {
viewController = presentedController.selectedViewController
} else {
viewController = presentedController
}
}
return viewController
}
}
I know very little about UIKit, and this code was copy/pasted from online. Why is this code crashing my preview, and how can I fix it?
I'm running XCode 13.4.1 on macOS Monterey
UIApplication already has keyWindow property and it seems there is already other extension with same property in workspace, so just use different name for your, like
extension UIApplication {
var currentWindow: UIWindow? {
*or find which one another is and see if you can reuse it.

Find a view at specific location in swift

I have got a simple view in swift and put 9 buttons as a 3x3 grid onto it, now i need the tag for each button and don't know how to get each button so I can get the tag property using a for loop. Does anyone know how i can get the button? Is there a function to get a view at a specified location?
Frankenstein's answer with .subviews works fine, but you can even do it more swifter using the built-in function viewWithTag(_:):
override func viewDidLoad() {
super.viewDidLoad()
// ...
// targeted view must have been added to the subview by now
if let taggedView = view.viewWithTag(1) {
print("Got the view!")
}
// you can even try to cast directly
if let taggedButton = view.viewWithTag(1) as? UIButton {
print("Got the button!")
}
// if you insist on using a for loop, you could use it like this
let highestTag = 10
for i in 0...highestTag {
if let taggedButton = view.viewWithTag(i) as? UIButton {
// here you go
}
}
}
For both approaches keep in mind, that the view you're looking for has already been added as a subview beforehand, otherwise you won't be able to search for it
You can use the subviews property of UIView and loop through each subview to check for tag you need:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
for subview in view.subviews {
if subview.tag == 1, let button = subview as? UIButton {
print("Got the button I need.")
}
}
if let button = view.viewWithTag(1) as? UIButton {
print("Got the button I need.")
}
}
}
Update: You can also use viewWithTag to find you view with a particular tag from within your subviews.

Update Tab Item Badge after getting data (Swift)

I'd like to update a Badge on a Custom Tab Bar Item when I receive some data. I am able to update the badge on the initial viewDidLoad() but then when I try to call viewDidLoad again later with the data, my tab items are nil. Here is how I have set it up...
class CustomTabBar: UITabBarController {
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
print("this prints correctly every time I call reload with the updated count: " + count)
if let tabItems = self.tabBar.items {
let tabItem = tabItems[0]
tabItem.badgeValue = String(count)
}else{
print("tab items nil")
}
}
func reload(count: Int){
self.count = count
viewDidLoad()
}
}
I'm calling reload() from another view controller after I get the data I need.
func updateBadge(){
let tabBar = CustomTabBar()
let username = UserUtil.username
let db = Firestore.firestore()
let upcomingContestsRef = db
.collection("NBAContests")
.whereField("EnteredUsers", arrayContains: username)
.whereField("Stage", isEqualTo: 2)
upcomingContestsRef.getDocuments()
{
(querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
print("count is " + String(querySnapshot!.count))
tabBar.reload(count: querySnapshot!.count)
}
}
}
I've check that viewDidLoad is getting called each time in custom tab bar controller, but after the initial load I don't have access to change the tab items anymore.
Does anyone know whats going on?
I've check out these similar questions
Reload / Refresh tab bar items in a ViewController ?
Setting badge value in UITabBarItem in UIViewController
This creates
let tabBar = CustomTabBar()
a new instance instead you need
guard let tabBar = self.tabBarController as? CustomTabBar else { print("returned") ; return }

Cannot convert value of type '(SwipeableTabBarController).Type' to expected argument type 'UIView'

I want to add Tabbar to my application. But when I try to add it, it gives the error in the header. How do I activate the Tabbar function?
public extension UIViewController {
public func setTabBarSwipe(enabled: Bool) {
if let swipeTabBarController = tabBarController as? SwipeableTabBarController {
swipeTabBarController.isSwipeEnabled = enabled
}
}
}
class MainTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(SwipeableTabBarController)
}
You can't add a user defined type SwipeableTabBarController tab as a subview here
view.addSubview(SwipeableTabBarController)
you need to add an instance like
let vc = SwipeableTabBarController()
self.addChild(vc)
vc.view.frame = self.view.bounds
view.addSubview(vc.view)
vc.willMove(toParent:self)
if your tabBarController is the root view controller of the app, use this, please.
if let window = UIApplication.shared.keyWindow,
let tabBar = window.rootViewController as? SwipeableTabBarController {
tabBar.isSwipeEnabled = enabled
}

Pass object from tableview to destination with revealviewcontroller in between

I am trying to pass an object from my tableview to the detail view. I am using the revealviewcontroller framework to have a slide out menu. Therefore I need to create a segue from the tableview to the revealviewcontroller and from here another one to the final detailviewcontroller.
That is why I canĀ“t set the object in the detail view - any idea how to do so?
This is the used code:
if segue.identifier == "communityDetailSegue" {
// Get the cell that generated this segue.
if let selectedCommunityCell = sender as ? UITableViewCell {
let destination = segue.destinationViewController as!CommunityViewController
if let communityIndex = self.tableView.indexPathForCell(selectedCommunityCell) {
destination.community = self.communitiesOfCurrentUser[communityIndex.row]
print(self.communitiesOfCurrentUser[communityIndex.row].name)
}
}
}
And this is the exception.
Could not cast value of type 'SWRevealViewController' (0x10027b9f0) to 'CommunityViewController'
You get the error because the segue's destination VC is the SWRevealViewController and not the CommunityViewController.
One way of solving your problem would be to pass the value in two steps:
First, in prepareForSegue() you pass the value to the SWRevealViewController (you'll need a subclass for this one, e.g. MyRevealViewController):
if segue.identifier == "communityDetailSegue" {
// Get the cell that generated this segue.
if let selectedCommunityCell = sender as ? UITableViewCell {
let destination = segue.destinationViewController as! MyRevealViewController
if let communityIndex = self.tableView.indexPathForCell(selectedCommunityCell) {
destination.community = self.communitiesOfCurrentUser[communityIndex.row]
print(self.communitiesOfCurrentUser[communityIndex.row].name)
}
}
}
Then, in MyRevealViewControlleryou can pass the value as soon as it is set:
class MyRevealViewController : SWRevealViewController {
// Let's assume this is the outlet to your final VC:
IBOutlet let communityViewController: CommunityViewController!
var community: YourCommunityType {
didSet {
if let communityVC = self.communityViewController {
communityVC.community = self.community
}
}
}
}