久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

iOS UIScrollView 性能

iOS UIScrollView performance(iOS UIScrollView 性能)
本文介紹了iOS UIScrollView 性能的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我正在嘗試提高 UIScrollView 的滾動性能.我上面有很多 UIButtons(可能有數百個):每個按鈕都有一個 png 圖像設置為背景.

I'm trying to increase the scrolling performance of my UIScrollView. I have a lot of UIButtons on it (they could be hundreds): every button has a png image set as background.

如果我在整個滾動出現時嘗試加載它,會花費太多時間.在網上搜索,我找到了一種優化它的方法(在滾動時加載和卸載頁面),但是每次我必須加載新頁面時滾動都會有一點停頓.

If I try to load the entire scroll when it appears, it takes too much time. Searching on the web, I've found a way to optimize it (loading and unloading pages while scrolling), but there's a little pause in scrolling everytime I have to load a new page.

你有什么建議讓它滾動順暢嗎?

Do you have any advice to make it scroll smoothly?

您可以在下面找到我的代碼.

Below you can find my code.

- (void)scrollViewDidScroll:(UIScrollView *)tmpScrollView {
    CGPoint offset = tmpScrollView.contentOffset;
    //322 is the height of 2*2 buttons (a page for me)
    int currentPage=(int)(offset.y / 322.0f);
    if(lastContentOffset>offset.y){
        pageToRemove = currentPage+3;
        pageToAdd = currentPage-3;
    }
    else{
        pageToRemove = currentPage-3;
        pageToAdd = currentPage+3;
    }
    //remove the buttons outside the range of the visible pages
    if(pageToRemove>=0 && pageToRemove<=numberOfPages && currentPage<=numberOfPages){
        for (UIView *view in scrollView.subviews)
        {
            if ([view isKindOfClass:[UIButton class]]){
                if(lastContentOffset<offset.y && view.frame.origin.y<pageToRemove*322){
                    [view removeFromSuperview];
                }
                else if(lastContentOffset>offset.y && view.frame.origin.y>pageToRemove*322){
                    [view removeFromSuperview];
                }
            }
        }
    }
    if(((lastContentOffset<offset.y && lastPageToAdd+1==pageToAdd) || (lastContentOffset>offset.y && lastPageToAdd-1==pageToAdd)) && pageToAdd>=0 && pageToAdd<=numberOfPages){
        int tmpPage=0;
        if((lastContentOffset<offset.y && lastPageToAdd+1==pageToAdd)){
            tmpPage=pageToAdd-1;
        }
        else{
            tmpPage=pageToAdd;
        }
        //the images are inside the application folder
        NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        for(int i=0;i<4;i++){
            UIButton* addButton=[[UIButton alloc] init];
            addButton.layer.cornerRadius=10.0;
            if(i + (tmpPage*4)<[imagesCatalogList count]){
                UIImage* image=[UIImage imageWithContentsOfFile:[NSString stringWithFormat: @"%@/%@",docDir,[imagesCatalogList objectAtIndex:i + (tmpPage*4)]]];
                if(image.size.width>image.size.height){
                    image=[image scaleToSize:CGSizeMake(image.size.width/(image.size.height/200), 200.0)];
                    CGImageRef ref = CGImageCreateWithImageInRect(image.CGImage, CGRectMake((image.size.width-159.5)/2,(image.size.height-159.5)/2, 159.5, 159.5));
                    image = [UIImage imageWithCGImage:ref];
                }
                else if(image.size.width<image.size.height){
                    image=[image scaleToSize:CGSizeMake(200.0, image.size.height/(image.size.width/200))];
                    CGImageRef ref = CGImageCreateWithImageInRect(image.CGImage, CGRectMake((image.size.width-159.5)/2, (image.size.height-159.5)/2, 159.5, 159.5));
                    image = [UIImage imageWithCGImage:ref];
                }
                else{
                    image=[image scaleToSize:CGSizeMake(159.5, 159.5)];
                }


                [addButton setBackgroundImage:image forState:UIControlStateNormal];
                image=nil;
                addButton.frame=CGRectMake(width, height, 159.5, 159.5);
                NSLog(@"width %i height %i", width, height);
                addButton.tag=i + (tmpPage*4);
                [addButton addTarget:self action:@selector(modifyImage:) forControlEvents:UIControlEventTouchUpInside];
                [tmpScrollView addSubview:addButton];
                addButton=nil;
                photos++;
            }
        }
    }
    lastPageToAdd=pageToAdd;
    lastContentOffset=offset.y;
}

推薦答案

這里有一些建議:

1) 首先,了解 scrollViewDidScroll: 將在用戶滾動時連續調用.不只是每個頁面一次.因此,我會確保您的邏輯能夠確保您的加載所涉及的實際工作僅在每頁觸發一次.

1) First, understand that scrollViewDidScroll: will get called continuously, as the user scrolls. Not just once per page. So, I would make sure that you have logic that ensures that the real work involved in your loading is only triggered once per page.

通常,我會保留一個類 ivar,例如 int lastPage.然后,當調用 scrollViewDidScroll: 時,我計算新的 當前頁面.只有當它與 ivar 不同時,我才會觸發加載.當然,那你需要將動態計算的索引(currentPage in your code)保存在你的ivar中.

Typically, I will keep a class ivar like int lastPage. Then, as scrollViewDidScroll: is called, I calculate the new current page. Only if it differs from the ivar do I trigger loading. Of course, then you need to save the dynamically calculated index (currentPage in your code) in your ivar.

2) 另一件事是我盡量不做 scrollViewDidScroll: 方法中的所有密集工作.我只在那里觸發它.

2) The other thing is that I try not to do all the intensive work in the scrollViewDidScroll: method. I only trigger it there.

因此,例如,如果您將發布的大部分代碼放入名為 loadAndReleasePages 的方法中,那么您可以在 scrollViewDidScroll: 方法中執行此操作,將執行推遲到 scrollViewDidScroll: 完成后:

So, for example, if you take most of the code you posted and put it in a method called loadAndReleasePages, then you could do this in the scrollViewDidScroll: method, which defers the execution until after scrollViewDidScroll: finishes:

- (void)scrollViewDidScroll:(UIScrollView *)tmpScrollView {
    CGPoint offset = tmpScrollView.contentOffset;
    //322 is the height of 2*2 buttons (a page for me)
    int currentPage = (int)(offset.y / 322.0f);

    if (currentPage != lastPage) {
        lastPage = currentPage;
        // we've changed pages, so load and release new content ...
        // defer execution to keep scrolling responsive
        [self performSelector: @selector(loadAndReleasePages) withObject: nil afterDelay:0];
    }
}

這是我從早期 iOS 版本開始使用的代碼,因此您當然也可以將 performSelector: 調用替換為異步 GCD 方法調用.關鍵是不要在內部滾動視圖委托回調.

This is code that I've used since early iOS versions, so you can certainly replace the performSelector: call with an asynchronous GCD method call, too. The point is not to do it inside the scroll view delegate callback.

3) 最后,您可能希望嘗試使用略有不同的算法來計算滾動視圖何時實際滾動到您想要加載和釋放內容的程度.您目前使用:

3) Finally, you might want to experiment with slightly different algorithms for calculating when the scroll view has actually scrolled far enough that you want to load and release content. You currently use:

int currentPage=(int)(offset.y / 322.0f);

這將根據 / 運算符和 floatint 轉換的方式產生整數頁碼.那可能沒問題.但是,您可能會發現您需要一個稍微不同的算法,以在稍微不同的點觸發加載.例如,您可能希望在頁面從一個頁面滾動到下一個頁面時恰好滾動 50% 時觸發內容加載.或者,您可能只想在您幾乎完全離開第一頁(可能 90%)時才觸發它.

which will yield integer page numbers based on the way the / operator, and the float to int cast works. That may be fine. However, you might find that you want a slightly different algorithm, to trigger the loading at a slightly different point. For example, you might want to trigger the content load as the page has scrolled exactly 50% from one page to the next. Or you might want to trigger it only when you're almost completely off the first page (maybe 90%).

我相信我編寫的一個滾動密集型應用程序確實需要我在加載大量資源時調整頁面滾動的精確時刻.因此,我使用了一個稍微不同的舍入函數來確定當前頁面何時發生了變化.

I believe that one scrolling intensive app I wrote actually did require me to tune the precise moment in the page scroll when I did the heavy resource loading. So, I used a slightly different rounding function to determine when the current page has changed.

你也可以玩弄它.

再查看您的代碼后,我還看到您正在做的工作是加載和縮放圖像.這實際上也是一個后臺線程的候選者.您可以從文件系統加載 UIImage,并在后臺線程上進行縮放,然后使用 GCD 最終設置按鈕的背景圖像(加載的圖像)并將其框架更改回 UI線程.

after looking at your code a little more, I also see that the work you're doing is loading and scaling images. This is actually also a candidate for a background thread. You can load the UIImage from the filesystem, and do your scaling, on the background thread, and use GCD to finally set the button's background image (to the loaded image) and change its frame back on the UI thread.

UIImage 自 iOS 4.0 起在后臺線程中使用是安全的.

UIImage is safe to use in background threads since iOS 4.0.

這篇關于iOS UIScrollView 性能的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

how to set scrollview content size in swift 3.0(如何在 swift 3.0 中設置滾動視圖內容大小)
Stop a UITableView from automatically scrolling(阻止 UITableView 自動滾動)
iOS UIScrollView Lazy Loading(iOS UIScrollView 延遲加載)
using iOS 6.0 SDK and building for iOS 5 Target causes UIScrollView setMinimumZoomScale to fail when running on iOS 5 simulator(在 iOS 5 模擬器上運行時,使用 iOS 6.0 SDK 并為 iOS 5 Target 構建會導致 UIScrollView setMinimumZ
Create partial-screen UIPageViewController programmatically(以編程方式創建部分屏幕 UIPageViewController)
how to make an ImageView zoomable with or without ScrollView.?(如何使用或不使用 ScrollView 使 ImageView 可縮放?)
主站蜘蛛池模板: 亚洲国产aⅴ成人精品无吗 欧美激情欧美激情在线五月 | 精品国产99 | 国产一区二区视频免费在线观看 | 国产一区二区三区四区在线观看 | 国产91精品在线 | 色播99 | 精品国产一区二区三区久久狼黑人 | 欧美jizzhd精品欧美巨大免费 | 欧美理论片在线观看 | 久久久久久久久久久一区二区 | 久久视频免费观看 | 91五月婷蜜桃综合 | 韩日av片| 国产激情一区二区三区 | 亚洲国产中文在线 | 91天堂| 亚洲精品在线视频 | 欧美aa在线| 久久草在线视频 | 国产精品美女久久久久 | 国产日韩欧美 | 中文字幕一区在线 | 国产日韩欧美 | 亚洲a视频 | 国产精品成人在线播放 | 福利片一区二区 | 亚洲免费一区二区 | 成人区一区二区三区 | 超碰在线网站 | 天天躁日日躁性色aⅴ电影 免费在线观看成年人视频 国产欧美精品 | 中文天堂网 | 国产欧美精品一区二区 | 91福利在线导航 | 国产精品久久久久久久久久 | 亚洲精品资源 | 99精品视频免费观看 | 亚洲成人av在线播放 | 91高清视频在线 | www日韩高清 | 天天想天天干 | 日韩欧美国产一区二区 |