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

iOS UIScrollView 性能

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

問題描述

我正在嘗試提高 UIScrollView 的滾動性能.我上面有很多 UIButtons(可能有數(shù)百個):每個按鈕都有一個 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.

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

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: 將在用戶滾動時連續(xù)調(diào)用.不只是每個頁面一次.因此,我會確保您的邏輯能夠確保您的加載所涉及的實際工作僅在每頁觸發(fā)一次.

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.然后,當調(diào)用 scrollViewDidScroll: 時,我計算新的 當前頁面.只有當它與 ivar 不同時,我才會觸發(fā)加載.當然,那你需要將動態(tài)計算的索引(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: 方法中的所有密集工作.我只在那里觸發(fā)它.

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

因此,例如,如果您將發(fā)布的大部分代碼放入名為 loadAndReleasePages 的方法中,那么您可以在 scrollViewDidScroll: 方法中執(zhí)行此操作,將執(zhí)行推遲到 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: 調(diào)用替換為異步 GCD 方法調(diào)用.關鍵是不要在內(nèi)部滾動視圖委托回調(diào).

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) 最后,您可能希望嘗試使用略有不同的算法來計算滾動視圖何時實際滾動到您想要加載和釋放內(nèi)容的程度.您目前使用:

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);

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

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%).

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

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.

你也可以玩弄它.

再查看您的代碼后,我還看到您正在做的工作是加載和縮放圖像.這實際上也是一個后臺線程的候選者.您可以從文件系統(tǒng)加載 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模板網(wǎng)!

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

相關文檔推薦

how to set scrollview content size in swift 3.0(如何在 swift 3.0 中設置滾動視圖內(nèi)容大小)
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 構(gòu)建會導致 UIScrollView setMinimumZ
Create partial-screen UIPageViewController programmatically(以編程方式創(chuàng)建部分屏幕 UIPageViewController)
how to make an ImageView zoomable with or without ScrollView.?(如何使用或不使用 ScrollView 使 ImageView 可縮放?)
主站蜘蛛池模板: 女人夜夜春 | 97国产一区二区精品久久呦 | www.国产精品 | 一区二区三区四区不卡视频 | 国产三级 | 成人精品影院 | 国产一区二区三区久久久久久久久 | 在线播放一区二区三区 | 日本三级黄视频 | 高清一区二区三区 | 毛片视频免费 | 国产精品一区二区在线 | 97国产爽爽爽久久久 | 国产精品久久久久久久免费观看 | 欧美精品在线视频 | 天堂网中文字幕在线观看 | 成人在线观 | 黄色网页在线观看 | 日本久草视频 | 嫩呦国产一区二区三区av | 中文字幕视频在线观看 | 国产精品日韩一区二区 | 成人不卡视频 | 国产四区 | 国产成人a亚洲精品 | 草草草网站 | 亚洲字幕在线观看 | 成人在线视频一区 | 日日草夜夜草 | 99riav国产一区二区三区 | 午夜天堂精品久久久久 | 日本成人中文字幕在线观看 | 国产女人精品视频 | 欧洲一区在线观看 | 日本精品一区二区三区四区 | 久久久精品视频一区二区三区 | 不卡欧美| 日韩视频一区二区在线 | 天天爽夜夜操 | 国产一区不卡在线观看 | 二区三区在线观看 |