gpt4 book ai didi

iphone - 如何在 iOS 中减少 "Live Bytes"?

转载 作者:行者123 更新时间:2023-12-01 18:21:08 24 4
gpt4 key购买 nike

我的 iPhone 应用程序出现问题,当我在 iPod 上运行它时,它需要超过 10 分钟才会崩溃并关闭。
因此,我查找了配置文件统计信息,并且似乎是高 Live Bytes,如下图所示:

Live Bytes

任何人都可以帮助我减少此 Live Bytes 以避免崩溃?

编辑:
我在调用 viewDidLoad 时使用了三个 for 循环,这三个循环从引用中获取图像,所以我认为它会让应用程序崩溃?
那么在不导致崩溃的情况下执行这三个 for 循环的替代方法是什么?

编辑 2:
这是我的 View 加载,每个循环从不同的文件夹中获取不同的图像,所有这些都是必要的

编辑 3:文件夹 a 有 100 张图片,其中一半是每张图片的缩略图,对于文件夹 b,有 30 张图片,最后是文件夹 c 90 张图片,其中一半是每张图片的缩略图,所有文件夹都在引用中,所以它没有从互联网上获取任何图像...

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

NSInteger x = 6;
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];

NSString *aPath = [resourcePath stringByAppendingPathComponent:@"a"];
NSArray *aDirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:aPath error:nil];
for (NSString *tString in aDirContents) {
if ([tString hasSuffix:@".jpg"]) {
UIButton *item = [UIButton buttonWithType:UIButtonTypeCustom];
[item setFrame:CGRectMake(x, 5, 60, 60)];
x += 63;
NSString *result = [tString substringToIndex:[tString length] - 4];
[item setTitle:result forState:UIControlStateNormal];
[item setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[item setBackgroundImage:[UIImage imageNamed:tString] forState:UIControlStateNormal];
[item addTarget:self action:@selector(changeFont:) forControlEvents:UIControlEventTouchUpInside];

[aSlider addSubview:item];
}
}
aSlider.frame = CGRectMake(aSlider.frame.origin.x, aSlider.frame.origin.y, x, 69);
[aSliderContainer setContentSize:aSlider.frame.size];

x = 6;
NSString *bPath = [resourcePath stringByAppendingPathComponent:@"b"];
NSArray *bDirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bPath error:nil];
for (NSString *tString in bDirContents) {
if ([tString hasSuffix:@".jpg"]) {
UIButton *item = [UIButton buttonWithType:UIButtonTypeCustom];
[item setFrame:CGRectMake(x, 5, 60, 60)];
x += 63;
NSString *result = [tString substringToIndex:[tString length] - 4];
[item setTitle:result forState:UIControlStateNormal];
[item setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[item setBackgroundImage:[UIImage imageNamed:tString] forState:UIControlStateNormal];
[item addTarget:self action:@selector(changeFont:) forControlEvents:UIControlEventTouchUpInside];

[bSlider addSubview:item];
}
}
bSlider.frame = CGRectMake(bSlider.frame.origin.x, bSlider.frame.origin.y, x, 69);
[bSliderContainer setContentSize:bSlider.frame.size];

// c Slider
x = 6;
NSString *cPath = [resourcePath stringByAppendingPathComponent:@"c"];
NSArray *cDirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:cPath error:nil];
for (NSString *tString in cDirContents) {
if ([tString hasSuffix:@".jpg"]) {
UIButton *item = [UIButton buttonWithType:UIButtonTypeCustom];
[item setFrame:CGRectMake(x, 5, 60, 60)];
x += 63;
NSString *result = [tString substringToIndex:[tString length] - 4];
[item setTitle:result forState:UIControlStateNormal];
[item setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
[item setBackgroundImage:[UIImage imageNamed:tString] forState:UIControlStateNormal];
[item addTarget:self action:@selector(changeFont:) forControlEvents:UIControlEventTouchUpInside];

[cSlider addSubview:item];
}
}
cSlider.frame = CGRectMake(cSlider.frame.origin.x, cSlider.frame.origin.y, x, 69);
[cSliderContainer setContentSize:cSlider.frame.size];
}

最佳答案

鉴于修改后的问题,您正在将图像从持久存储加载到(大概)一系列 ScrollView 中,有几个想法:

  • 有多少张图片?

    如果每个只有 5 或 6 个,那么追求无限滚动类(class)是徒劳的。如果有 50+,那么无限滚动是非常重要的模式。 (谷歌“UIImageView 无限滚动”。)这是我原始答案中“延迟加载”讨论的变体,但面向 ScrollView 的独特情况。
  • 图片有多大?

    它们已经是 60x60(或者可能,对于视网膜,120x120)?如果它们比这大得多,您可能希望将它们调整为适合您的 UI 的最佳尺寸。您可以对应用程序包中的原始 Assets 执行此操作,也可以 programmatically resize them .
  • 当您的应用程序崩溃时,您会看到什么异常/错误日志?

    您能否准确确认崩溃日志和/或错误消息、异常代码等的详细信息?
  • 虽然它可能看起来很神秘,但这些信息在诊断问题方面是非常宝贵的。我们真的很想确保 viewDidLoad代码实际上是问题所在,如果是这样,错误究竟是什么。
  • 如果你还没有,我可能会打开 exception breakpoint (继续为“所有”异常执行此操作)。有时它可以帮助突出显示有问题的代码行(如果问题不仅仅是内存不足或被看门狗进程杀死)。

  • 请继续使用相关详细信息更新您的问题。

    原始答案(在看到 viewDidLoad 代码之前):

    我鼓励您追求图像的“延迟加载”,仅在 UI 需要它们时加载它们,并在不再需要它们时释放它们(或删除对它们的所有强引用)(即有问题的图像滚出屏幕)。我会非常警惕在 viewDidLoad 中循环加载图像.它浪费了宝贵的内存,如果您同步执行此操作,您的应用程序甚至可能被看门狗进程杀死,因为您的应用程序始终应该在主队列中响应。如果您收到 0x8badf00d 的异常代码,您可以判断看门狗是否会杀死您的应用程序。 (极客幽默:看门狗报告“吃了不好的食物”;见 TN2151 对一些异常代码的描述)。

    最简单的解决方案是使用 UIImageView SDWebImage 中的任何一个类别或 AFNetworking .如果您使用 UITableViewUICollectionView ,这非常简单。如果您使用 UIScrollView ,那么它需要更多的工作(除非您使用第三方“无限滚动”类)。

    图像会占用大量内存,因此请仅在任何给定时刻保留 UI 所需的内容,并且不要不必要地“预取”图像。我鼓励你用谷歌搜索“UIImage 延迟加载”这个短语,你会得到大量的点击。

    如果你想做一个无限滚动,为每个 InfiniteScrollerButton 定义一个模型对象:
    @interface InfiniteScrollerButton : NSObject

    @property (nonatomic, copy, readonly) NSString *filename; // what is the full path of the image
    @property (nonatomic, weak, readonly) UIButton *button; // the UIButton; nil if no button yet created for this icon
    @property (nonatomic, readonly) CGRect frame; // the frame that the icon does (or would) occupy
    @property (nonatomic, readonly) NSInteger tag; // the tag number for the button

    - (id)initWithFilename:(NSString *)filename index:(NSInteger)index;
    - (void)addButtonToView:(UIView *)view target:(id)target action:(SEL)action;
    - (void)removeButton;

    @end

    其实现可能如下所示:
    @interface InfiniteScrollerButton ()

    @property (nonatomic, copy) NSString *filename;
    @property (nonatomic, weak) UIButton *button;
    @property (nonatomic) CGRect frame;
    @property (nonatomic) NSInteger tag;

    @end

    @implementation InfiniteScrollerButton

    - (id)initWithFilename:(NSString *)filename index:(NSInteger)index
    {
    self = [super init];
    if (self) {
    _filename = [filename copy];
    _frame = CGRectMake(6 + index * 63, 5, 60, 60);
    _tag = index;
    }
    return self;
    }

    - (void)addButtonToView:(UIView *)view target:(id)target action:(SEL)action
    {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    self.button = button;

    // on old devices, even retrieving an image from persistent storage can affect the smoothness
    // of the UI, so let's do that asynchronously

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImage *image = [UIImage imageWithContentsOfFile:self.filename];

    dispatch_async(dispatch_get_main_queue(), ^{
    button.frame = self.frame;
    button.tag = self.tag;
    NSString *tString = [self.filename lastPathComponent];
    NSString *result = [tString substringToIndex:[tString length] - 4];
    [button setTitle:result forState:UIControlStateNormal];
    [button setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
    [button setBackgroundImage:image forState:UIControlStateNormal];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:button];
    });
    });
    }

    - (void)removeButton
    {
    if (self.button)
    {
    [self.button removeFromSuperview];
    self.button = nil;
    }
    }

    @end

    然后您的 View Controller 可能如下所示:
    @interface ViewController () <UIScrollViewDelegate>

    @property (nonatomic, strong) NSMutableArray *icons;

    @end

    @implementation ViewController

    - (void)viewDidLoad
    {
    [super viewDidLoad];

    [self loadModel];
    [self scrollViewDidScroll:self.scrollView]; // call this once, manually, so the initial load of visible images takes place
    }

    // load the model backing our scrollview

    - (void)loadModel
    {
    self.icons = [NSMutableArray array];

    NSString *resourcePath = [[NSBundle mainBundle] resourcePath];

    NSString *aPath = [resourcePath stringByAppendingPathComponent:@"a"];
    NSArray *aDirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:aPath error:nil];
    [aDirContents enumerateObjectsUsingBlock:^(NSString *tString, NSUInteger idx, BOOL *stop) {
    InfiniteScrollerButton *icon = [[InfiniteScrollerButton alloc] initWithFilename:[aPath stringByAppendingPathComponent:tString] index:idx];
    [self.icons addObject:icon];
    }];

    InfiniteScrollerButton *lastObject = [self.icons lastObject];
    self.scrollView.contentSize = CGSizeMake(lastObject.frame.origin.x + lastObject.frame.size.width + 6, 69);
    }

    - (void)changeFont:(id)sender
    {
    NSLog(@"%s", __FUNCTION__);
    }

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
    static NSInteger kMargin = 100;

    // get the CGRect for the visible portion of the scroll view,
    // adding a bit of a margin so it, effectively, will also load
    // the next UIButton, too

    CGRect contentRect = CGRectMake(scrollView.contentOffset.x - kMargin,
    scrollView.contentOffset.y,
    scrollView.bounds.size.width + kMargin * 2,
    scrollView.bounds.size.height);

    // iterate through all of the icons

    for (InfiniteScrollerButton *icon in self.icons)
    {
    if (CGRectIntersectsRect(contentRect, icon.frame)) // if the icon should be visible ...
    {
    if (icon.button == nil) // ... but it's not, then add it
    [icon addButtonToView:scrollView
    target:self
    action:@selector(changeFont:)];
    }
    else // if the icon is no longer visible ...
    {
    if (icon.button != nil) // ... but it exists, then remove it
    [icon removeButton];
    }
    }
    }

    @end

    只要确保将您的 View Controller 指定为 ScrollView 的委托(delegate),您就可以参加比赛了。显然,这只有一个 ScrollView ,但希望你明白这一点。您的 viewDidLoad不应创建 UIButton控件,而只是填充支持您的 UI 的模型数组。然后您的 ScrollView 将调用委托(delegate)方法 scrollViewDidScroll ,它将根据需要加载和卸载图像。如果你有成千上万的图像,我可能会建议其他优化,但希望这能说明这个概念。

    关于iphone - 如何在 iOS 中减少 "Live Bytes"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17302981/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com