有沒有辦法得到一個通知,回調或其他方式來調用一個方法,每當一個UIView變得可見的用戶,即當一個UIScrollview是一些UIViews的超級視圖,並且這樣一個UIView的ViewController應該得到當用戶看到它的視圖時通知它?如何在UIView變得可見時得到通知?
我知道的可能,但檢查不那麼優雅的解決了滾動滾動哪個位置(通過UIScrollViewDelegate的方法)和計算,如果子視圖中的任何一個可見...
但我正在尋找以更普遍的方式來做到這一點。
有沒有辦法得到一個通知,回調或其他方式來調用一個方法,每當一個UIView變得可見的用戶,即當一個UIScrollview是一些UIViews的超級視圖,並且這樣一個UIView的ViewController應該得到當用戶看到它的視圖時通知它?如何在UIView變得可見時得到通知?
我知道的可能,但檢查不那麼優雅的解決了滾動滾動哪個位置(通過UIScrollViewDelegate的方法)和計算,如果子視圖中的任何一個可見...
但我正在尋找以更普遍的方式來做到這一點。
如果您的視圖呈現行爲,它應該位於視圖控制器內。在視圖控制器上,每次出現視圖時都會調用viewDidAppear方法。
- (void)viewDidAppear:(BOOL)animated
viewDidAppear的問題在於,它僅在使用導航控制器時被調用。在我的情況下,視圖從屏幕上滾動*滾動,然後滾動回來。滾動似乎不觸發viewDidAppear .... – 2010-03-19 11:19:56
那麼,什麼可以表明視圖是否出現在屏幕上與滾動? – 2014-05-21 08:01:12
「它應該在視圖控制器內。」 - 並且視圖控制器僅適用於全屏視圖。有時候我們只能看到屏幕的一部分。 – Jonny 2016-02-09 06:29:28
視圖的圖層屬性應該告訴我們,如果這種觀點是可見或不可見
[view.layer visibleRect];
但心不是爲我工作。
因此,解決方法是使用UiScrollView contentOffset屬性來計算特定的視圖是否可見。
那麼如何添加一個觸發器,當該值發生變化時觸發? – 2015-08-07 14:55:26
很久以前我就回答了這個問題,即使我忘記了上下文。 子類UIView並使用以下方法。 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/doc/uid/TP40006816-CH3-SW139 – 2015-08-10 11:31:36
這就是我現在正在做的。我想聽一門外部課程。 – 2015-08-17 19:43:45
我不認爲有一種通用的方式來做到這一點的意見。聽起來像你被困在scrollViewDidEndScrolling和其他ScrollViewDelegate方法。但我不確定爲什麼你說它很優雅,它們很簡單。
我已經設法解決這個問題是這樣的:
首先,添加一個類別的UIView以下方法:
// retrieve an array containing all super views
-(NSArray *)getAllSuperviews
{
NSMutableArray *superviews = [[NSMutableArray alloc] init];
if(self.superview == nil) return nil;
[superviews addObject:self.superview];
[superviews addObjectsFromArray:[self.superview getAllSuperviews]];
return superviews;
}
然後,在你看來,檢查窗口屬性設置:
-(void)didMoveToWindow
{
if(self.window != nil)
[self observeSuperviewsOnOffsetChange];
else
[self removeAsSuperviewObserver];
}
如果它被設置,我們會觀察每個上海華盈的「contentOffset」上的任何變化。如果窗口是零,我們將停止觀察。您可以將的keyPath更改爲任何其他財產,也許「幀」如果在你的superviews沒有的UIScrollView:
-(void)observeSuperviewsOnOffsetChange
{
NSArray *superviews = [self getAllSuperviews];
for (UIView *superview in superviews)
{
if([superview respondsToSelector:@selector(contentOffset)])
[superview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}
}
-(void)removeAsSuperviewObserver
{
NSArray *superviews = [self getAllSuperviews];
for (UIView *superview in superviews)
{
@try
{
[superview removeObserver:self forKeyPath:@"contentOffset"];
}
@catch(id exception) { }
}
}
現在實行「observeValueForKeyPath」 - 方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"contentOffset"])
{
[self checkIfFrameIsVisible];
}
}
最後,檢查是否視圖的框架在窗口框架內可見:
-(void)checkIfFrameIsVisible
{
CGRect myFrameToWindow = [self.window convertRect:self.frame fromView:self];
if(myFrameToWindow.size.width == 0 || myFrameToWindow.size.height == 0) return;
if(CGRectContainsRect(self.window.frame, myFrameToWindow))
{
// We are visible, do stuff now
}
}
感謝您的詳細解決方案。我嘗試了一下,但問題是在我有機會移除觀察者之前,超級視圖正在被釋放。我甚至觀察他們的「超級觀點」關鍵路徑的變化,但它沒有幫助。這絕對是KVO最糟糕的部分。 – phatmann 2015-08-27 18:13:58
這應該是沒有問題的,我猜。如果superview被釋放,觀察視圖(我們想知道它的視圖是否可見)也應該被釋放,因爲它是子視圖。 – Thomas 2015-08-27 22:20:52
你說得對。我的問題是我沒有在所有關鍵路徑上調用removeObserver。也就是說,KVO最佳實踐是保留所有觀察對象的所有權。在這種情況下,這意味着將由'observeSuperviewsOnOffsetChange'創建的超級視圖列表放入成員變量中,並在'removeAsSuperviewObserver'中使用此保留的超級列表列表。這也有輕微的性能優勢。 – phatmann 2015-08-28 19:16:33
我的應用程序的導航基於水平滾動UIScrollView。我也通過分類的UIWindow攔截觸摸。因此,當前可見視圖的ViewController需要將自己註冊爲委託給子類UIWindow。這就是我希望在視圖變得可見時得到通知的原因。 – 2010-03-17 21:09:52