I'm trying to get the content size of UITableView in runtime, where I working on library that will do some moves when pop over the views and to do this I wrote this code inside the library to figure out that inside the presented view will be UITableView:
if view.isKind(of: UIView.self) {
for subView in view.subviews {
for sv in subView.subviews {
if sv.isKind(of: UITableView.self) {
print(sv.frame.size.height)
Here I got the table view, but I couldn't get the contentSize property
print("table view found")
}
}
}
}
Any tips how to get its content size ?!
Use a cast instead of a test so that the compiler knows the object's properties:
if view.isKind(of: UIView.self) {
for subView in view.subviews {
for sv in subView.subviews {
if let tableView = sv as? UITableView {
print(tableView.contentSize.height)
}
}
}
}
Related
I am trying to get all views inside my UIViewController.
I am using this code:
for subview : UIView in self.view.subviews{
//code here
}
the problem is that I don't get views that are inside a UIView.
so I get all view except of their children.
please, how can I get ALL Views that are either child or parent inside my UIViewController? even if a view has a child that has a child that has a child. I want to go through all views.
thanx in advance :)
(please in swift 4.0)
You need to recursively process all subviews.
func processSubviews(of view: UIView) {
// 1. code here do something with view
for subview in view.subviews {
// 2. code here do something with subview
processSubviews(of: subview)
// 3. code here do something with subview
}
// 4. code here do something with view
}
You need to put your code at either position 1, 2, 3, or 4 (or possibly two or more of those places) depending on the results you want.
Then you can call this as:
processSubviews(of: self.view)
For get all views (as Label, Button, View, ...) in your view hierarchy and access to all child view in your viewController you should using from a recursive func to iterate all views :
func getAllSubviews(view:UIView) {
for subview in view.subviews {
if let takenLabel = subview as? UILabel {
takenLabel.backgroundColor = UIColor.red
}
getAllSubviews(view:subview)
}
}
You can using from this func to access other view like button and change them .
in this case i'm changing background color of all label in viewController to red
There are many different way to get subviews
To Get all the subviews in the parent view
for subview in view.subviews{
// you can get all of your views one by one here.
}
To Filter if any tagged view is available or not (lets assume view is tagged by 100)
view.subviews.filter{$0.tag == 100}
Extensions to check if Any view contains sub views
extension UIView{
func isAvailabletoParentView(inParentView : UIView, subViewTag : Int) -> Bool{
var isAvailable = false
for subviews in inParentView.subviews{
if subviews.tag == subViewTag{
isAvailable = true
return true
}else{
isAvailable = false
}
}
return isAvailable
}
}
Call Extension like
subview.isAvailabletoParentView(inParentView: parentView, subViewTag: anyTagToSubView)
Hope it will helps , Happy coding 🙂.
Does anybody know is there any way to call status bar tapping programmatically when view appeared? My view is not on the top when appearing.
Thank you!
I'm going to assume that what you want to do is scroll your view to the top, which is what tapping the status bar does. If that's the case then here is a nice little view controller extension to achieve that.
extension UIViewController {
func scrollToTop() {
func scrollToTop(view: UIView?) {
guard let view = view else { return }
switch view {
case let scrollView as UIScrollView:
if scrollView.scrollsToTop == true {
scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: true)
return
}
default:
break
}
for subView in view.subviews {
scrollToTop(view: subView)
}
}
scrollToTop(view: view)
}
var isScrolledToTop: Bool {
for subView in view.subviews {
if let scrollView = subView as? UIScrollView {
return (scrollView.contentOffset.y == 0)
}
}
return true
}
}
Then in the viewDidAppear of your view controller, you can call
myViewController.scrollToTop()
I have many views and for each views, many subviews.
I tried to specify for each subviews
scrollsToTop = false
but my TableView doesn't scroll to top when I press the status bar.
I suppose I missed some views...
I know there is a similar post but it doesn't answer (UITableView scroll to top when tapping status bar at top of the screen)
So I decided to implement this function:
override func viewDidLoad() {
super.viewDidLoad()
checkForScrollViewInView(self.view)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.scrollsToTop = true
}
func checkForScrollViewInView(view:UIView) {
for subview in view.subviews as [UIView] {
if subview.isKindOfClass(UITextView) {
(subview as! UITextView).scrollsToTop = false
}
if subview.isKindOfClass(UIScrollView) {
(subview as! UIScrollView).scrollsToTop = false
}
if subview.isKindOfClass(UITableView) {
(subview as! UITableView).scrollsToTop = false
}
if (subview.subviews.count > 0) {
self.checkForScrollViewInView(subview)
}
}
}
But it doesn't work too. I don't know what I miss.
You may stuggle with 2 problems:
You have more than one instance of UIScrollView. You should disable scrollsToTop (eg. self.collectionView?.scrollsToTop = false in viewDidLoad) for the parent UIScrollView or objects that inherit from it (like UITableView or UICollectionView).
From Apple scrollViewShouldScrollToTop(_:)
If the delegate doesn’t implement this method, true is assumed. For the scroll-to-top gesture (a tap on the status bar) to be effective, the scrollsToTop property of the UIScrollView must be set to YES.
If your hierarchy is highly customized method scrollViewShouldScrollToTop won't be called. You should check why does happen. Otherwise you will have to some dirty work: add some gestures and handle them.
Interesting links:
Scroll to top of UITableView by tapping status bar
Why doesn't UIScrollView/UITableview respond to taps on the status bar, and scroll to the top?
https://developer.apple.com/library/prerelease/ios//documentation/UIKit/Reference/UIScrollViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIScrollViewDelegate/scrollViewShouldScrollToTop:
Ok I found why my tableview wouldn't scroll!
I called my checkForScrollViewInView() function only in the viewDidLoad of my table view's view controller. In order to disable scrollToTop for every child views.
But I forgot that I had another "active" view controller... In my app I have a left menu which opens to swipe. Calling checkForScrollViewInView() in the left menu's view controller solves my issue.
func checkForScrollViewInView(view:UIView) {
for subview in view.subviews as [UIView] {
if subview.isKindOfClass(UITextView) {
(subview as! UITextView).scrollsToTop = false
}
if subview.isKindOfClass(UIScrollView) {
(subview as! UIScrollView).scrollsToTop = false
}
if subview.isKindOfClass(UITableView) {
(subview as! UITableView).scrollsToTop = false
}
if (subview.subviews.count > 0) {
self.checkForScrollViewInView(subview)
}
}
}
I have UIButton inside cell of UITableView, When i touch the button it is actually working but the animation of highlighted is not being seen, I have tried setting delaysContentTouches = false on viewDidLoad and also on IB
I even tried to find UIScrollVIew of table view so that i can set that properties to false, like...
for cls in cell.subviews
{
println("name of class is ::\(NSStringFromClass(cls.classForCoder))")
if NSStringFromClass(cls.classForCoder) == "UITableViewCellScrollView"
{
cls.scrollView.delaysContentTouches = false
break
}
}
Thanks in advance!
UITableView subclass
override public var delaysContentTouches: Bool {
didSet {
if let subviews = self.subviews as? [UIView] {
for view in subviews {
if let scroll = view as? UIScrollView {
scroll.delaysContentTouches = delaysContentTouches
}
break
}
}
}
}
I have a random child view in a view hierarchy. What is the best/fastest/cleverest way to get to the root superview?
Cheers,
Doug
If your app only has one UIWindow (usually true), and if that window's only subview is your root controller's view (also usually true):
[randomChildView.window.subviews objectAtIndex:0]
Or you could recursively climb out of the hierarchy, by checking view.superview until you find a view whose superview is nil.
It's an insignificant amount of processor time to go straight up the superview hierarchy. I have this in my UIView category.
- (UIView *)rootView {
UIView *view = self;
while (view.superview != Nil) {
view = view.superview;
}
return view;
}
swift3/4:
func rootSuperView() -> UIView
{
var view = self
while let s = view.superview {
view = s
}
return view
}
I like this one.
extension UIView {
func rootView() -> UIView {
return superview?.rootView() ?? superview ?? self
}
}
Fast solution (fast as in minimalist):
extension UIView {
var rootView: UIView {
superview?.rootView ?? self
}
}