1

我已经实现了一种使用 alasset 库检索设备内部图像的方法。它与 iPhone 4、iphone 4s 和 iPad 等最新设备完美配合,但在旧 iPhone 3GS 上应用程序会在几秒钟内崩溃。我现在这可能是因为 iPhone 3gs 与 iPhone 5 或 iPad 相比资源较少,但我希望我的应用程序也能在它上面运行。问题是 iPhone 3gs 在图库中有超过 1700 张照片,如果我阅读资产,它会给我警告消息“收到内存警告”。大约在第 40 张图像之后。应用程序崩溃后。这是我正在使用的方法。我需要了解我做错了什么以及如何修改我的代码。

-(NSString *) getPhotos{
enum { WDASSETURL_PENDINGREADS = 1, WDASSETURL_ALLFINISHED = 0};
NSMutableArray *idList = [[NSMutableArray alloc] init]; //create the array that will contains the informations about the images that we want return like an xml
XMLWriter* xmlWriter = [[XMLWriter alloc]init];
__block NSString *xmlList; //xmlList is the string that we will return to the client
NSConditionLock * assetsReadLock = [[NSConditionLock alloc] initWithCondition:WDASSETURL_PENDINGREADS]; //this is the condition for lock the images when we need to find the informations about the images.
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; //declare the library that give to us the access to the media info
    //NSString *description = [[NSString alloc] init];
    __block UIDevice *aDevice = [UIDevice currentDevice];
    [library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
        __block NSString *systemVersion = [[NSString alloc] init];
        if (group) {
            NSString *album = [group valueForProperty:ALAssetsGroupPropertyName]; //take the current name of the selected album
            [group setAssetsFilter:[ALAssetsFilter allPhotos]]; //search for the photos
            [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){
                ALAssetRepresentation *representation = [asset defaultRepresentation];
                NSDictionary *metadata = [representation metadata];
                if (asset){ //when a photo is found
                    NSString *description = [asset description]; //contains the main informations about the images. It doesn't contains the TIFF informations.
                    systemVersion = [aDevice systemVersion];
                    NSRange pathRange = [systemVersion rangeOfString:@"5."];
                    if(pathRange.location == 0){
                        NSString *path = [description substringWithRange:NSMakeRange(50, [description length]-54)]; //take the correct asset removing the unnecessary words
                        [idList addObject:path]; //add the element to the list
                    } else {
                        NSString *path = [description substringWithRange:NSMakeRange(27, [description length]-27)]; //take the correct asset removing the unnecessary words
                        [idList addObject:path]; //add the element to the list
                    }
                }
            }];
        }
        if (group == nil){ //it mean that he has passed all images
            if ([idList count] != 0){
                NSString *finalNames = [[NSString alloc] init];
                [xmlWriter writeStartDocumentWithEncodingAndVersion:@"UTF-8" version:@"1.0"]; //start the xml document
                [xmlWriter writeStartElement:@"Data"]; //Write the first tag

                    int z = 0;
                    for (z = 0; z <= [idList count]-1; z++){
                            [xmlWriter writeStartElement:@"Photo"];
                            [xmlWriter writeAttribute:@"Id" value:[idList objectAtIndex:z]]; //write the id, in this case is the path
                            [xmlWriter writeEndElement:@"Photo"];
                        }
                    }
                [xmlWriter writeEndElement:@"Data"]; //close the first tag
                [xmlWriter writeEndDocument]; //close the document
                xmlList = [xmlWriter toString];
                [assetsReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
            } else {
                [xmlWriter writeStartDocumentWithEncodingAndVersion:@"UTF-8" version:@"1.0"]; //start the xml document
                [xmlWriter writeStartElement:@"Data"]; //Write the first tag
                [xmlWriter writeAttribute:@"Message" value:@"No images founded"];
                [xmlWriter writeEndElement:@"Data"]; //close the first tag
                [xmlWriter writeEndDocument]; //close the document
                xmlList = [xmlWriter toString];
                [assetsReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
            }
        }
    } failureBlock:^(NSError *error) {
        NSLog(@"error enumerating AssetLibrary groups %@\n", error);
        [assetsReadLock lock];
        [assetsReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
    }];

[assetsReadLock lockWhenCondition:WDASSETURL_ALLFINISHED];
[assetsReadLock unlock];
return xmlList;

}

更新:控制台日志显示:

Nov 21 11:12:00 T50 installd[378] <Error>: 0x2ffbc000 handle_install: Install of "/var/mobile/Media/PublicStaging/DiLand Kiosk Connect.app" requested by mobile_installation_proxy
Nov 21 11:12:00 T50 com.apple.launchd[1] (com.apple.aslmanager) <Notice>: (com.apple.aslmanager) Throttling respawn: Will start in 1 seconds
Nov 21 11:12:00 T50 installd[378] <Error>: 0x2ffbc000 MobileInstallationInstall_Server: Installing app com.fitengineering.DiLandKioskConnect
Nov 21 11:12:01 T50 installd[378] <Error>: Nov 21 11:12:01  SecTrustEvaluate  [leaf CriticalExtensions IssuerCommonName]
Nov 21 11:12:02 T50 SpringBoard[66] <Warning>: Killing com.fitengineering.DiLandKioskConnect for termination assertion
Nov 21 11:12:04 T50 installd[378] <Error>: 0x2ffbc000 MobileInstallationInstall_Server: Staging: 0.03s; Waiting: 0.00s; Installation: 2.75s; LS Sync: 0.81s; Overall: 3.62s
Nov 21 11:12:04 T50 lsd[410] <Warning>: updating identifier store
Nov 21 11:12:04 T50 lsd[410] <Warning>: Attempting to store identifiers file
Nov 21 11:12:04 T50 mobile_house_arrest[415] <Error>: Max open files: 78
Nov 21 11:12:04 T50 com.apple.launchd[1] (com.apple.aslmanager) <Notice>: (com.apple.aslmanager) Throttling respawn: Will start in 7 seconds
Nov 21 11:12:05 T50 mobile_house_arrest[416] <Error>: Max open files: 78
Nov 21 11:12:05 T50 com.apple.debugserver-199[417] <Warning>: debugserver-199 for armv7.
Nov 21 11:12:05 T50 com.apple.debugserver-199[417] <Warning>: Connecting to com.apple.debugserver service...
Nov 21 11:12:05 T50 kernel[0] <Debug>: lockbot[406] Builtin profile: debugserver (sandbox)
Nov 21 11:12:05 T50 com.apple.debugserver-199[417] <Warning>: Got a connection, waiting for process information for launching or attaching.
Nov 21 11:12:05 T50 com.apple.launchd[1] (UIKitApplication:com.fitengineering.DiLandKioskConnect[0x68e9][419]) <Warning>: (UIKitApplication:com.fitengineering.DiLandKioskConnect[0x68e9]) Spawned and waiting for the debugger to attach before continuing...
Nov 21 11:12:05 T50 com.apple.debugserver-199[417] <Warning>: Got a connection, waiting for debugger instructions.
Nov 21 11:12:06 T50 kernel[0] <Debug>: launchd[419] Builtin profile: container (sandbox)
Nov 21 11:12:06 T50 kernel[0] <Debug>: launchd[419] Container: /private/var/mobile/Applications/246DC61D-8D40-4713-A73B-C816EBCDEE6A (sandbox)
Nov 21 11:12:06 T50 mobile_house_arrest[420] <Error>: Max open files: 78
Nov 21 11:12:06 T50 ReportCrash[422] <Notice>: Not saving Jetsam log because no data from the kernel.
Nov 21 11:12:06 T50 mobile_house_arrest[421] <Error>: Max open files: 78
Nov 21 11:12:07 T50 mobile_house_arrest[423] <Error>: Max open files: 78
Nov 21 11:12:07 T50 com.apple.launchd[1] (com.apple.aslmanager) <Notice>: (com.apple.aslmanager) Throttling respawn: Will start in 4 seconds
Nov 21 11:12:07 T50 mobile_house_arrest[425] <Error>: Max open files: 78
Nov 21 11:12:08 T50 mobile_house_arrest[426] <Error>: Max open files: 78
Nov 21 11:12:12 T50 DiLand Kiosk Connect[419] <Warning>: Reachability Flag Status: -R -----l- networkStatusForFlags
Nov 21 11:12:23 T50 lockdownd[43] <Notice>: 2ff51000 spawn_and_handle_checkin: Timeout on socket /var/run/lockdown/checkin.120 waiting for com.apple.crashreportmover to checkin for Xcode. spawn=1385028728 select=1385028728 now=1385028743
Nov 21 11:12:23 T50 ReportCrash[428] <Error>: libMobileGestalt copySystemVersionDictionaryValue: Could not lookup ReleaseType from system version dictionary
Nov 21 11:12:23 T50 ReportCrash[428] <Warning>: Not internal build
Nov 21 11:12:24 T50 ReportCrash[428] <Notice>: Saved crashreport to /Library/Logs/CrashReporter/stacks-2013-11-21-111224.plist using uid: 0 gid: 0, synthetic_euid: 0 egid: 0
Nov 21 11:12:24 T50 ReportCrash[428] <Error>: libMobileGestalt copySystemVersionDictionaryValue: Could not lookup ReleaseType from system version dictionary
Nov 21 11:12:24 T50 DiLand Kiosk Connect[419] <Warning>: PATH assets-library://asset/asset.JPG?id=3B1FF4C6-55FE-44C5-9D09-C3316D5794D1&ext=JPG
LIST OF ASSETS HERE
Nov 21 11:12:28 T50 DiLand Kiosk Connect[419] <Warning>: Received memory warning.
Nov 21 11:12:28 T50 UserEventAgent[13] <Notice>: jetsam: kernel termination snapshot being created
Nov 21 11:12:28 T50 com.apple.launchd[1] (com.apple.accountsd[374]) <Notice>: (com.apple.accountsd) Idle-exit job was jettisoned. Will bypass throttle interval for next on-demand launch.
Nov 21 11:12:28 T50 com.apple.launchd[1] (com.apple.accountsd[374]) <Notice>: (com.apple.accountsd) Exited: Killed: 9
Nov 21 11:12:28 T50 com.apple.launchd[1] (com.apple.assetsd[365]) <Notice>: (com.apple.assetsd) Idle-exit job was jettisoned. Will bypass throttle interval for next on-demand launch.
Nov 21 11:12:28 T50 com.apple.launchd[1] (com.apple.assetsd[365]) <Notice>: (com.apple.assetsd) Exited: Killed: 9
Nov 21 11:12:28 T50 DiLand Kiosk Connect[419] <Warning>: Received error from assetsd.
Nov 21 11:12:28 T50 SpringBoard[66] <Warning>: Received memory warning.
Nov 21 11:12:29 T50 ReportCrash[432] <Error>: libMobileGestalt copySystemVersionDictionaryValue: Could not lookup ReleaseType from system version dictionary
Nov 21 11:12:29 T50 ReportCrash[432] <Notice>: Not saving suspended-only Jetsam log because already dumped today.
Nov 21 11:12:30 T50 MobileMail[367] <Warning>: Received memory warning.
Nov 21 11:12:31 T50 DiLand Kiosk Connect[419] <Warning>: PATH assets-library://asset/asset.JPG?id=DE6660FE-7242-4449-96A9-4D718B0D0AA4&ext=JPG
Nov 21 11:12:31 T50 UserEventAgent[13] <Notice>: jetsam: kernel termination snapshot being created
Nov 21 11:12:31 T50 com.apple.launchd[1] (com.apple.assetsd[433]) <Notice>: (com.apple.assetsd) Idle-exit job was jettisoned. Will bypass throttle interval for next on-demand launch.
Nov 21 11:12:31 T50 com.apple.launchd[1] (com.apple.assetsd[433]) <Notice>: (com.apple.assetsd) Exited: Killed: 9
Nov 21 11:12:31 T50 DiLand Kiosk Connect[419] <Warning>: Received error from assetsd.
Nov 21 11:12:31 T50 MobilePhone[369] <Warning>: Received memory warning.
Nov 21 11:12:45 T50 com.apple.debugserver-199[417] <Warning>: 1 +0.000000 sec [01a1/1303]: error: ::read ( 5, 0x2ff509fc, 18446744069414585344 ) => -1 err = Bad file descriptor (0x00000009)
Nov 21 11:12:45 T50 com.apple.launchd[1] (UIKitApplication:com.apple.mobilemail[0x409e][367]) <Notice>: (UIKitApplication:com.apple.mobilemail[0x409e]) Exited: Killed: 9
Nov 21 11:12:45 T50 com.apple.launchd[1] (UIKitApplication:com.apple.mobilephone[0x8c42][369]) <Notice>: (UIKitApplication:com.apple.mobilephone[0x8c42]) Exited: Killed: 9
Nov 21 11:12:45 T50 com.apple.launchd[1] (com.apple.tccd[371]) <Notice>: (com.apple.tccd) Exited: Killed: 9
Nov 21 11:12:45 T50 com.apple.launchd[1] (UIKitApplication:com.fitengineering.DiLandKioskConnect[0x68e9][419]) <Notice>: (UIKitApplication:com.fitengineering.DiLandKioskConnect[0x68e9]) Exited: Killed: 9
Nov 21 11:12:45 T50 backboardd[26] <Warning>: Application 'UIKitApplication:com.apple.mobilephone[0x8c42]' exited abnormally with signal 9: Killed: 9

更新 2:这是设备日志

Incident Identifier: 5CC39233-317D-490D-B21C-813B629F95D5
CrashReporter Key:   4911764fc74ada97463a46613032769e29097835
Hardware Model:      iPhone2,1
OS Version:          iPhone OS 6.1.3 (10B329)
Kernel version:      Darwin Kernel Version 13.0.0: Wed Feb 13 21:35:42 PST 2013; root:xnu-2107.7.55.2.2~1/RELEASE_ARM_S5L8920X
Date:                2013-11-21 11:12:23 +0100
Exception Code:      0xdeadfeed
Reason:              Timeout on socket /var/run/lockdown/checkin.120 waiting for com.apple.crashreportmover to checkin for Xcode. spawn=1385028728 select=1385028728 now=1385028743
Thermal Level:       0
Thermal Sensors:    3041 2846 3516 2799 2767 5161 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Frontmost process PID:    419
Frontmost process PID:    66
Jetsam Level:              0
Free Pages:            14798
Active Pages:           9223
Inactive Pages:         5756
Purgeable Pages:           4
Wired Pages:           12255
Speculative Pages:      8286
Throttled Pages:       14717
Busy Buffer Count:         0
Pages Wanted:              0
Pages Reclaimed:           0

Process 0 info:
resident memory bytes:  33886208
page faults:                382
page-ins:                     0
copy-on-write faults:         0
user   time in task:  1109.081110 seconds
system time in task:     0.000000 seconds

Process 0 kernel_task threads:
thread 0x1 TH_WAIT|TH_UNINT 0x803282e0
thread priority:          92
thread sched flags:     none
kernel cont 800622ed
user   time in thread:     2.045010 seconds
system time in thread:     0.000000 seconds
… Many Threads here …
thread 0x132c TH_WAIT|TH_UNINT 0x98e5d79c
thread priority:          81
thread sched flags:     none
kernel cont 802582fd
user   time in thread:     0.000028 seconds
system time in thread:     0.000000 seconds

Process 1 info:
resident memory bytes:  614400
page faults:              16083
page-ins:                  1153
copy-on-write faults:      8901
user   time in task:     5.258988 seconds
system time in task:     0.000000 seconds

Process 1 binary images:
0x2fe56000 <280610df5ed43ec7aa00629a27009302>
0x2d000 <10ff8d45040239d1b479cddf29e6b50e>

Process 1 launchd threads:
thread 0xfe TH_WAIT 0
thread priority:          31
thread sched flags:     none
kernel cont 800104f1
user 0x3ac23eb4 0x3ac2404d 0x3ac7f85b 0x3ac7f943 0x320f7 0x3063f 0x3ab6db20
user   time in thread:     4.761893 seconds
system time in thread:     0.000000 seconds

… HERE THERE ARE MANY OTHER PROCESS THAT I HAVE REMOVED FOR REDUCE THE DIMENSION OF THE LOG

Process 428 binary images:
0x2fe3a000 <280610df5ed43ec7aa00629a27009302>
0x6c000 <68e323272a9d37c58ba4cdf1279764c4>

Process 428 ReportCrash threads:
thread 0x267c TH_WAIT 0x803020d4
thread priority:          30
thread sched flags:     none
kernel cont 80027845
user 0x3ac346a4 0x3ab923d3 0x3abf2deb 0x76063 0x3ab6db20
user   time in thread:     0.031530 seconds
system time in thread:     0.000000 seconds
thread 0x267d TH_WAIT 0
thread priority:          33
thread sched flags:     none
kernel cont 801d1795
user 0x3ac24648 0x3ab5d4f1 0x3ab4fdf8 0
user   time in thread:     0.000822 seconds
system time in thread:     0.000000 seconds
thread 0x267e TH_WAIT 0x9cd64900
thread priority:          29
thread sched flags:     none
kernel cont 802196cd
user 0x3ac34d98 0x3ab82cfb 0x3ab82a16 0x3ab828a4
user   time in thread:     0.001473 seconds
system time in thread:     0.000000 seconds
thread 0x2680 TH_RUN 0
thread priority:          24
thread sched flags:     none
kernel 0x80024ea1
user 0x3ac34bd8 0x7a365 0x75677 0x6d76f 0x6d877 0x3ac325a7 0x74625 0x3ab8d311 0x3ab8d1d8
user   time in thread:     0.083545 seconds
system time in thread:     0.000000 seconds
thread 0x2681 TH_WAIT 0
thread priority:          31
thread sched flags:     none
kernel cont 800104f1
user 0x3ac23eb4 0x3ac2404d 0x3ac32541 0x74625 0x3ab8d311 0x3ab8d1d8
user   time in thread:     0.000125 seconds
system time in thread:     0.000000 seconds
thread 0x2682 TH_WAIT 0x9d0e6b40
thread priority:          29
thread sched flags:     none
kernel cont 802196cd
user 0x3ac34d98 0x3ab82cfb 0x3ab82a16 0x3ab828a4
user   time in thread:     0.000198 seconds
system time in thread:     0.000000 seconds


Global binary images:
0x319b9000  <b3cd09ef40143ad78034d6d3c9e204f2>
… AND HERE THERE ARE MANY GLOBAL BINARY IMAGES …

谢谢

4

1 回答 1

1

我认为这段代码在进一步调查之前需要一些改进,尽管通过观察很难想象,字符串的集合会占用内存。尽管如此,您在测试时还没有写任何关于可用内存的内容。

  • 问问自己是否真的需要锁定资源。应用程序运行 iPhone,并且其他进程在您现在访问此应用程序的同时访问照片资产的可能性很小。你当时肯定不会拍照吧?锁并不便宜。

  • 如果您需要锁,则将资源锁定在异步线程内,而不是在主线程之外,即在块内。在您的情况下,无论如何您都不清楚您要锁定什么。

  • 将 __block 指令放在 idList 声明的前面

  • 无论如何,方法 enumerateGroupsWithTypes 是异步的,所以不需要另外 dispatch_async 任何东西

  • 你在你的 UIApplicationDelegate 中实现了 applicationDidReceiveMemoryWarning: 吗?

  • 用仪器追踪事故。枚举方法很可能是自动释放某些东西,所以也有可能是僵尸,特别是因为它发生在后端线程上。

让我们稍后看看它将如何执行。尝试不同的组合。

编辑:

好的。让我们进一步更新这段代码:

  • 从行中删除 __block 指令,这是不必要的:

    __block NSString *systemVersion = [[NSString alloc] init];

  • 这是错误的,请进一步阅读 NSString 类的文档,不要初始化 NSString,只需声明它:

NSString *systemVersion;

  • move __block UIDevice *aDevice = [UIDevice currentDevice]; 在 enumerateGroupsWithTypes 方法和块前面

  • 这个:systemVersion = [aDevice systemVersion]; 在标注块内不需要,这是系统常量。连同上述声明。

  • 在标注块内插入自动释放块

进行所有这些更改并进行测试。

于 2013-11-05T12:56:22.930 回答