![](/img/trans.png)
[英]iOS Swift - How to reference a NSOperationQueue in an extension to cancel existing operations?
[英]NSOperationQueue cancel specific operations
問題是我管理的 scrollView 中有很多圖塊。 每個可見圖塊顯示從 URL 加載的圖像或(在第一次 URL 加載后)后台緩存文件。 隱形瓷磚回收(設置新框架並重繪)。
圖像加載取決於平鋪位置。
對於長距離滾動,每個圖塊都會調用多次重繪:每個圖塊在顯示正確的圖像之前多次加載(並顯示)不同的圖像。
所以問題是在添加新之前取消所有先前添加的 tile 操作。
我子類化 NSInvocationOperation 只是為了包含上下文對象來檢測附加到的操作,在添加新操作之前我取消了同一個圖塊的所有操作:
-(void)loadWithColler:(TileView *)coller {
if (queue == nil) {
queue = [NSOperationQueue new];
}
NSInvocationOperationWithContext *loadImageOp = [NSInvocationOperationWithContext alloc];
[loadImageOp initWithTarget:self selector:@selector(loadImage:) object:loadImageOp];
[loadImageOp setContext:coller];
[queue setSuspended:YES];
NSArray *opers = [queue operations];
for (NSInvocationOperationWithContext *nextOperation in opers) {
if ([nextOperation context] == coller) {
[nextOperation cancel];
}
}
[queue addOperation:loadImageOp];
[queue setSuspended:NO];
[loadImageOp release];
}
在操作本身中,我檢查 isCancelled:
-(void)loadImage:(NSInvocationOperationWithContext *)operation {
if (operation.isCancelled) return;
TileView *coller = [operation context];
/* TRY TO GET FILE FROM CACHE */
if (operation.isCancelled) return;
if (data) {
/* INIT WITH DATA IF LOADED */
} else {
/* LOAD FILE FROM URL AND CACHE IT */
}
if (operation.isCancelled) return;
NSInvocationOperation *setImageOp = [[NSInvocationOperation alloc] initWithTarget:coller selector:@selector(setImage:) object:cachedImage];
[[NSOperationQueue mainQueue] addOperation:setImageOp];
[setImageOp release];
}
但它什么都不做。 有時提前返回有效,但圖塊仍會在正確的圖像之前加載許多圖像。
那我怎么能成功呢? 滾動時這么多不需要的操作會導致主線程延遲嗎? (因為存在延遲,我不知道為什么......所有在后台加載......)
更新:
使用 NSLog: isCancelled 執行時: > 取消 loadImage 方法: >
所以取消工作。
現在我保存對 TileView 對象中最后一個操作的引用,並且僅當調用的操作等於 TileView 操作時才執行 setImage 操作。
沒什么區別...
看起來有很多操作可以將不同的圖像加載到一個接一個調用的圖塊。
還有其他建議嗎?
清關:
有單例 DataLoader(來自它的所有代碼)。 並且所有圖塊都在 drowRect 中調用它:
[[DataLoader sharedDataLoader] loadWithColler:self];
更新:
NSInvocationOperation 子類:
@interface NSInvocationOperationWithContext : NSInvocationOperation {
id context;
}
@property (nonatomic,retain,readwrite) id context;
@end
@implementation NSInvocationOperationWithContext
@synthesize context;
- (void)dealloc
{
[context release];
[super dealloc];
}
@end
非常感謝您的幫助!
解決方案:
從下面的答案:需要從 NSOperation 子類化
當我繼承 NSOperation 並將所有 loadImage: 代碼放入它的“main”方法中時(只需將所有代碼移到此處而沒有其他任何內容),並且所有工作都非常完美!
至於滾動延遲:它發生導致將圖像加載到 UIImageView (由於解壓縮和光柵化(據我所知)需要很長時間)。
所以更好的方法是使用 CATiledLayer。 它在后台加載數據並且加載速度更快。
NSOperationQueue 與“setSuspended”相關的工作方式是它不會開始運行在那之后添加到它的新添加的 NSOperations,並且不會開始運行任何當前在其中但尚未開始運行的NSOperations . 您確定您要取消的操作尚未開始嗎?
另外 - 您的 NSOperation 子類是否正確處理鍵值觀察? 並發隊列子類 NSOperations 必須為這里的某些屬性調用willChangeValueForKey
和didChangeValueForKey
- 但看起來不是問題,因為您的隊列沒有設置isConcurrent
。 如果你走那條路,僅供參考。
主線程的延遲是由於滾動時運行循環的模式。 我建議您觀看 WWDC2011 網絡應用程序會議。 我不知道將NSInvocationOperation
子類化是否可以,它是NSOperation
的具體子類。 我將NSOperation
。 根據我的經驗,如果您想避免緩慢滾動,您應該創建NSOperation
子類,將它們的主要加載到特定線程以進行網絡操作(您必須創建它)。 蘋果有一個很棒的示例代碼https://developer.apple.com/library/ios/#samplecode/MVCNetworking/Introduction/Intro.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.