编程心得之内存是个累活儿

      进入公司做程序也有些日子了吧,做程序多少也有了些感受,真想全部都记下来,可是不行啊,人太懒了。没那个恒心。不聊那些没边得话题了,还说来说我们的内存吧。

 

     记得还在那被人们奉为圣殿的大学校园里混时,老师常给我们说编程有很多要学的东西,什么内存的分配使用,算法问题等等一系列。但是同时也说道,现在的硬件处理能力已经很强了,内存问题一般都是够用了的。所以现在内存什么的,只要我们做到了分配后需要释放的我们保证了释放就不会存在问题,也许这对多数的编程来说是真的,但是此刻我感觉好像是被忽悠了。

 

     先不谈这些,还是从自己做的事儿谈起吧,这里不得不先说明了,自己是做手机应用的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]];
    }
}

 

通过实现的两个方式,我们的问题得到了解决,但是这里还是给我们遗留下了一个问题,由于处理速度问题,滑动效果的流畅程度自然会有所降低了,所谓有得必有失嘛。

 

写这些,只是想说名一点,内存问题真的会让我们感觉到头疼,他也不仅仅是一个分配和释放问题,也涉及到我们的程序实现方式和其他要求限制问题。在内存问题上,有些问题是不太确定的,或许我们采用的方式不同,将会有不同的效果。

你可能感兴趣的:(编程心得之内存是个累活儿)