Search code examples
iosswiftuiimageviewuitabbaruitabbaritem

Unable to get UIImageView from UITabBar swift


I am following tutorial to animate tab bar images. The given line of code doesn't work for me

secondItemView.subviews.first as! UIImageView

as it gets data of type UITabBarButtonLabel and not UIImageView. I added tag value 1 so that I can get UIImageView using tag value enter image description here

secondItemView.viewWithTag(1)

returns nil. What is the other way to get UIImageView's reference?

Code

@objc public class MTMainScreenTabsController : UITabBarController {
var secondItemImageView: UIImageView!
public override func viewDidLoad() {
    super.viewDidLoad()
    let secondItemView = self.tabBar.subviews[0]


    print(secondItemView.subviews)
    print(secondItemView.viewWithTag(1))

    //self.secondItemImageView = secondItemView.subviews.secon
    var item: UITabBarItem! = self.tabBar.items![0]


    //self.secondItemImageView = secondItemView.viewWithTag(1) as! UIImageView
}

public override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
}

public override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    if item.tag == 1 {
        self.secondItemImageView.transform = .identity
        UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 1, options: .curveEaseInOut, animations: {
            () -> Void in
                //let rotation = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
            let rotation = CGAffineTransform.init(rotationAngle: CGFloat(Double.pi/2))
                self.secondItemImageView.transform = rotation
        }, completion: nil)
    }
}

}


Solution

  • It's not a good practice to strictly depend on the order of subviews as it may change in the future. If you are sure that secondItemView.subviews contain an instance of UIImageView you can find it like this:

    let imageView = secondItemView.subviews.flatMap { $0 as? UIImageView }.first
    

    An imageView variable would be an optional containing either nil or an actual UIImageView if there was any subview of this type. Flat map would iterate through subviews and try to cast each to UIImageView - if it fails the result will be filtered out, if not it will then be put in the result array from which you're taking first element.