編程心得之內存是個累活兒

      進入公司做程序也有些日子了吧,做程序多少也有了些感受,真想全部都記下來,可是不行啊,人太懶了。沒那個恆心。不聊那些沒邊得話題了,還說來說我們的內存吧。

 

     記得還在那被人們奉爲聖殿的大學校園裏混時,老師常給我們說編程有很多要學的東西,什麼內存的分配使用,算法問題等等一系列。但是同時也說道,現在的硬件處理能力已經很強了,內存問題一般都是夠用了的。所以現在內存什麼的,只要我們做到了分配後需要釋放的我們保證了釋放就不會存在問題,也許這對多數的編程來說是真的,但是此刻我感覺好像是被忽悠了。

 

     先不談這些,還是從自己做的事兒談起吧,這裏不得不先說明了,自己是做手機應用的iphone手機上的應用,或許說道iphone手機,很多人都會覺得他的畫面處理效果確實很不錯。不過我們這裏也不談這個問題,這裏只是想說從iphone 1代到現在的4代,對開發的應用程序使用的內存的限制是不一樣的,而這裏要討論的就是做滿足iphone 4代品質的應用程序在iphone 3上進行測試。而這裏最大的問題就在於圖片資源的問題了,對於iphone 4其滿屏像素是640*960,而其他幾代的滿屏像素都是320*480,這樣滿足iphone 4的圖片資源要比iphone 3的圖片資源大上4倍了,與此同時,由於iphone 3能夠供沒個應用程序使用的內存本身限制,所以對內存問題就是一個不得不考慮的問題了。當然,這裏要考慮的不僅僅是內存的分配和釋放問題,還包括處理的方式問題了。

 

     談到這裏還是用個例子來說說吧,在iphone提供的類中有一個UIScrollView類,這個類主要用於滑動效果。我們先看下面這端代碼吧,如果僅僅從技術實現的角度來看,是不應該有什麼問題的,然而在若是在iphone 3代裝載就會出問題。這裏的問題就在於我們加載進去的圖片資源太多(9張),我們可以計算一下對於9張640*960的圖片大小:640*960*4 = 2457600 = 2400k = 2.34375M,然後在乘9張 = 21.09375M,如此大的一個內存使用量在iphone 3代中的應用程序是絕對不允許的。所以程序崩潰就不足爲奇了。

 

UIWindow *tmpWindow = [[UIApplication sharedApplication] keyWindow];
    CGFloat rate = tmpWindow.frame.size.width/640;
    self.navigationController.navigationBarHidden = YES;
    NSArray *listArr = [[NSArray alloc] initWithObjects:@"yoga001",@"yoga002",
                        @"yoga003",@"yoga004",@"yoga005",@"yoga006",
                        @"yoga007",@"yoga008",@"yoga009",
                        nil];
    NSInteger tmpCount = [listArr count];
    m_scrollView.contentSize = CGSizeMake(640*rate*tmpCount, 960*rate);
    for (NSInteger i = 0; i < tmpCount; i++) {
        UIImageView *tmpImageView = [[UIImageView alloc] initWithFrame:
                                     CGRectMake(640*rate*i, 0, 640*rate, 960*rate)];
        tmpImageView.tag = 100+i;

        NSString *tmpStr = [NSString stringWithFormat:@"fxjyogapic%d.png",i+1];
        tmpImageView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(tmpStr)];
        [m_scrollView addSubview:tmpImageView];
        [tmpImageView release];
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(30*rate+640*rate*i, 600*rate, 584*rate, 346*rate)];
        textView.tag = 200+i;
        textView.editable = NO;
        textView.backgroundColor = [UIColor clearColor];
        textView.font = [UIFont systemFontOfSize:32*rate];
        textView.textColor = [UIColor whiteColor];
        textView.text = NSLocalizedString([listArr objectAtIndex:i],@"");
        [m_scrollView addSubview:textView];
        [textView release];
    }
    [listArr release];

 

既然遇到問題了,那麼我們很自然就必須解決了,我們再來看看下面的程序

    UIWindow *tmpWindow = [[UIApplication sharedApplication] keyWindow];
    CGFloat rate = tmpWindow.frame.size.width/640;
    NSArray *listArr = [[NSArray alloc] initWithObjects:@"yoga001",@"yoga002",
                        @"yoga003",@"yoga004",@"yoga005",@"yoga006",
                        @"yoga007",@"yoga008",@"yoga009",
                        nil];
    NSInteger tmpCount = [listArr count];
    m_scrollView.contentSize = CGSizeMake(640*rate*tmpCount, 960*rate);
    for (NSInteger i = 0; i < tmpCount; i++) {
        UIImageView *tmpImageView = [[UIImageView alloc] initWithFrame:
                                     CGRectMake(640*rate*i, 0, 640*rate, 960*rate)];
        tmpImageView.tag = 100+i;
        [m_scrollView addSubview:tmpImageView];
        [tmpImageView release];
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(30*rate+640*rate*i, 600*rate, 584*rate, 346*rate)];
        textView.tag = 200+i;
        textView.editable = NO;
        textView.backgroundColor = [UIColor clearColor];
        textView.font = [UIFont systemFontOfSize:32*rate];
        textView.textColor = [UIColor whiteColor];
        textView.text = NSLocalizedString([listArr objectAtIndex:i],@"");
        [m_scrollView addSubview:textView];
        [textView release];
    }
    [listArr release];
    m_scrollView.contentOffset = CGPointMake(0, 0);
    UIImageView *currentView = (UIImageView *)[m_scrollView viewWithTag:100];
    currentView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(@"fxjyogapic1.png")];

 

在這個過程中我們只加載了其中一張,當然佔用的內存少了。很自然程序能夠正常運行了,不過我們這裏有了另外一個問題,就是我們必須實現滑動效果,怎麼辦呢?還好UIScrollView有個代理叫做UIScrollViewDelegate能幫我們做一些事,我們就看看下面的代碼了。

 

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    NSInteger currentPage = (NSInteger)(scrollView.contentOffset.x/320);
    NSLog(@"Begin : currentPage = %d",currentPage);
    if (currentPage <= 0) {
        UIImageView *nextImageView = (UIImageView *)[m_scrollView viewWithTag:101];
        nextImageView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(@"fxjyogapic2.png")];
        //nextImageView.image = [UIImage imageNamed:@"fxjofficeExciresebg2.png"];
    } else if (currentPage >= 8) {
        UIImageView *lastImageView = (UIImageView *)[m_scrollView viewWithTag:107];
        lastImageView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(@"fxjyogapic8.png")];
        //lastImageView.image = [UIImage imageNamed:@"fxjofficeExciresebg8.png"];
    } else {
        UIImageView *lastImageView = (UIImageView *)[m_scrollView viewWithTag:100+currentPage-1];
        NSString *tmpStr = [NSString stringWithFormat:@"fxjyogapic%d.png",currentPage];
        lastImageView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(tmpStr)];
        //lastImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"fxjofficeExciresebg%d.png",currentPage]];
        UIImageView *nextImageView = (UIImageView *)[m_scrollView viewWithTag:100+currentPage+1];
        NSString *tmpStr1 = [NSString stringWithFormat:@"fxjyogapic%d.png",currentPage+2];
        nextImageView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(tmpStr1)];
        //nextImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"fxjofficeExciresebg%d.png",currentPage+2]];
    }
   
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSInteger currentPage = (NSInteger)(scrollView.contentOffset.x/320);
    NSLog(@"End : currentPage = %d",currentPage);
    for (NSInteger i = 0; i < 9; i++) {
        if (i != currentPage) {
            UIImageView *otherImageView = (UIImageView *)[m_scrollView viewWithTag:100+i];
            otherImageView.image = nil;
        }
    }
    UIImageView *currentView = (UIImageView *)[m_scrollView viewWithTag:100+currentPage];
    if (currentView.image == nil) {
        NSString *tmpStr = [NSString stringWithFormat:@"fxjyogapic%d.png",currentPage+1];
        currentView.image = [UIImage imageWithContentsOfFile:BUNDLE_PATH(tmpStr)];
        //currentView.image = [UIImage imageNamed:[NSString stringWithFormat:@"fxjofficeExciresebg%d.png",currentPage+1]];
    }
}

 

通過實現的兩個方式,我們的問題得到了解決,但是這裏還是給我們遺留下了一個問題,由於處理速度問題,滑動效果的流暢程度自然會有所降低了,所謂有得必有失嘛。

 

寫這些,只是想說名一點,內存問題真的會讓我們感覺到頭疼,他也不僅僅是一個分配和釋放問題,也涉及到我們的程序實現方式和其他要求限制問題。在內存問題上,有些問題是不太確定的,或許我們採用的方式不同,將會有不同的效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章