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]; callout ブロック内では必要ありません。これはシステム定数です。上記の宣言とともに。

  • コールアウト ブロック内に自動解放ブロックを挿入する

これらすべての変更を行い、テストします。

于 2013-11-05T12:56:22.930 に答える