내 정보 UIView
가 사용자에게 표시 되는지 여부를 결정할 수 있습니까?
내보기로 추가 subview
에 여러 번 Tab Bar Controller
.
이보기의 각 인스턴스에는보기 NSTimer
를 업데이트하는가 있습니다.
그러나 사용자에게 표시되지 않는보기를 업데이트하고 싶지 않습니다.
이것이 가능한가?
감사
답변
다음 사항을 확인할 수 있습니다.
- view.hidden을 확인하면 숨겨집니다.
- 뷰 계층 구조에 있습니다.
view.superview != nil
- 보기의 경계를 확인하여 화면에 있는지 확인할 수 있습니다.
내가 생각할 수있는 유일한 다른 것은 당신의 견해가 다른 사람들 뒤에 묻혀서 그 이유로 보이지 않는 경우입니다. 당신은 그들이 당신의 시야를 가리는지 확인하기 위해 이후에 오는 모든 견해를 검토해야 할 수도 있습니다.
답변
여기서 끝나는 다른 사람을 위해 :
UIView의 오히려 검사보다 화면 어딘가에 있는지 확인하려면 superview != nil
,이 있는지 확인하는 것이 좋습니다 window != nil
. 전자의 경우 뷰에 수퍼 뷰가 있지만 수퍼 뷰가 화면에 없을 수 있습니다.
if (view.window != nil) {
// do stuff
}
물론 그것이 있는지 hidden
또는 alpha > 0
.
NSTimer
보기가 표시되지 않는 동안 실행하는 것을 원하지 않는 경우 가능하면 이러한보기를 수동으로 숨기고보기가 숨겨 질 때 타이머가 중지되도록해야합니다. 그러나 나는 당신이 무엇을하는지 전혀 확신하지 못합니다.
답변
이것은 뷰의 프레임이 모든 수퍼 뷰의 경계 내에 있는지 (루트 뷰까지) 결정합니다. 실제 사용 사례 중 하나는 스크롤 뷰 내에서 하위 뷰가 (적어도 부분적으로) 표시되는지 확인하는 것입니다.
Swift 5.x :
func isVisible(view: UIView) -> Bool {
func isVisible(view: UIView, inView: UIView?) -> Bool {
guard let inView = inView else { return true }
let viewFrame = inView.convert(view.bounds, from: view)
if viewFrame.intersects(inView.bounds) {
return isVisible(view: view, inView: inView.superview)
}
return false
}
return isVisible(view: view, inView: view.superview)
}
이전 Swift 버전
func isVisible(view: UIView) -> Bool {
func isVisible(view: UIView, inView: UIView?) -> Bool {
guard let inView = inView else { return true }
let viewFrame = inView.convertRect(view.bounds, fromView: view)
if CGRectIntersectsRect(viewFrame, inView.bounds) {
return isVisible(view, inView: inView.superview)
}
return false
}
return isVisible(view, inView: view.superview)
}
잠재적 개선 :
- 존경
alpha
과hidden
. clipsToBounds
뷰가 거짓 인 경우 수퍼 뷰의 경계를 초과 할 수 있으므로 존중하십시오 .
답변
나를 위해 일한 해결책은 먼저 뷰에 창이 있는지 확인한 다음 수퍼 뷰를 반복하고 다음 사항을 확인하는 것입니다.
- 보기가 숨겨지지 않습니다.
- 뷰가 수퍼 뷰 범위 내에 있습니다.
지금까지 잘 작동하는 것 같습니다.
스위프트 3.0
public func isVisible(view: UIView) -> Bool {
if view.window == nil {
return false
}
var currentView: UIView = view
while let superview = currentView.superview {
if (superview.bounds).intersects(currentView.frame) == false {
return false;
}
if currentView.isHidden {
return false
}
currentView = superview
}
return true
}
답변
보기가 사용자에게 표시되는지 진정으로 알고 싶습니다. 다음 사항을 고려해야합니다.
- 보기의 창이 nil이 아니고 가장 상단의 창과 동일합니까?
- 뷰이며 모든 수퍼 뷰 알파> = 0.01 (UIKit에서 터치를 처리해야하는지 여부를 결정하는 데 사용되는 임계 값)이며 숨겨지지 않습니다.
- 동일한 계층 구조에서 다른보기보다 높은보기의 Z- 색인 (누적 값)입니다.
- Z- 색인이 더 낮더라도 상단의 다른보기에 투명한 배경색 인 알파 0이 있거나 숨겨져 있으면 볼 수 있습니다.
특히 전면 뷰의 투명한 배경색은 프로그래밍 방식으로 확인하는 데 문제가 될 수 있습니다. 진정으로 확신하는 유일한 방법은 전체 화면의 스냅 샷과 함께 프레임 내에서 확인하고 비교하기 위해 뷰의 프로그래밍 방식 스냅 샷을 만드는 것입니다. 그러나 충분히 뚜렷하지 않은 뷰 (예 : 완전히 흰색)에는 작동하지 않습니다.
영감을 얻으려면 iOS Calabash-server 프로젝트의 isViewVisible 메소드를 참조하십시오.
답변
테스트 된 솔루션.
func isVisible(_ view: UIView) -> Bool {
if view.isHidden || view.superview == nil {
return false
}
if let rootViewController = UIApplication.shared.keyWindow?.rootViewController,
let rootView = rootViewController.view {
let viewFrame = view.convert(view.bounds, to: rootView)
let topSafeArea: CGFloat
let bottomSafeArea: CGFloat
if #available(iOS 11.0, *) {
topSafeArea = rootView.safeAreaInsets.top
bottomSafeArea = rootView.safeAreaInsets.bottom
} else {
topSafeArea = rootViewController.topLayoutGuide.length
bottomSafeArea = rootViewController.bottomLayoutGuide.length
}
return viewFrame.minX >= 0 &&
viewFrame.maxX <= rootView.bounds.width &&
viewFrame.minY >= topSafeArea &&
viewFrame.maxY <= rootView.bounds.height - bottomSafeArea
}
return false
}
답변
viewWillAppear에서 “isVisible”값을 true로 설정하고 viewWillDisappear에서 false로 설정합니다. UITabBarController 하위보기를 알 수있는 가장 좋은 방법은 탐색 컨트롤러에서도 작동합니다.