Skip to content

Commit ba91cb5

Browse files
authored
Merge pull request #206 from Kivenhaoyu/master
phasset memory fix
2 parents 0c3344a + 9133b0a commit ba91cb5

File tree

1 file changed

+90
-91
lines changed

1 file changed

+90
-91
lines changed

QiniuSDK/Common/QNPHAssetFile.m

Lines changed: 90 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,10 @@
1111
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
1212
#import <AVFoundation/AVFoundation.h>
1313
#import <Photos/Photos.h>
14-
enum {
15-
kAMASSETMETADATA_PENDINGREADS = 1,
16-
kAMASSETMETADATA_ALLFINISHED = 0
17-
};
1814

1915
#import "QNResponseInfo.h"
2016

21-
@interface QNPHAssetFile () {
22-
BOOL _hasGotInfo;
23-
}
17+
@interface QNPHAssetFile ()
2418

2519
@property (nonatomic) PHAsset *phAsset;
2620

@@ -32,6 +26,10 @@ @interface QNPHAssetFile () {
3226

3327
@property (nonatomic, strong) NSURL *assetURL;
3428

29+
@property (nonatomic, readonly) NSString *filepath;
30+
31+
@property (nonatomic) NSFileHandle *file;
32+
3533
@end
3634

3735
@implementation QNPHAssetFile
@@ -45,30 +43,69 @@ - (instancetype)init:(PHAsset *)phAsset error:(NSError *__autoreleasing *)error
4543
}
4644
_fileModifyTime = t;
4745
_phAsset = phAsset;
48-
[self getInfo];
46+
_filepath = [self getInfo];
47+
if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
48+
NSError *error2 = nil;
49+
NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:_filepath error:&error2];
50+
if (error2 != nil) {
51+
if (error != nil) {
52+
*error = error2;
53+
}
54+
return self;
55+
}
56+
_fileSize = [fileAttr fileSize];
57+
NSFileHandle *f = nil;
58+
NSData *d = nil;
59+
if (_fileSize > 16 * 1024 * 1024) {
60+
f = [NSFileHandle fileHandleForReadingAtPath:_filepath];
61+
if (f == nil) {
62+
if (error != nil) {
63+
*error = [[NSError alloc] initWithDomain:_filepath code:kQNFileError userInfo:nil];
64+
}
65+
return self;
66+
}
67+
} else {
68+
d = [NSData dataWithContentsOfFile:_filepath options:NSDataReadingMappedIfSafe error:&error2];
69+
if (error2 != nil) {
70+
if (error != nil) {
71+
*error = error2;
72+
}
73+
return self;
74+
}
75+
}
76+
_file = f;
77+
_assetData = d;
78+
}
79+
4980
}
5081
return self;
5182
}
5283

5384
- (NSData *)read:(long)offset size:(long)size {
54-
NSRange subRange = NSMakeRange(offset, size);
55-
if (!self.assetData) {
56-
self.assetData = [self fetchDataFromAsset:self.phAsset];
85+
if (_assetData != nil) {
86+
return [_assetData subdataWithRange:NSMakeRange(offset, (unsigned int)size)];
5787
}
58-
NSData *subData = [self.assetData subdataWithRange:subRange];
59-
60-
return subData;
88+
[_file seekToFileOffset:offset];
89+
return [_file readDataOfLength:size];
6190
}
6291

6392
- (NSData *)readAll {
6493
return [self read:0 size:(long)_fileSize];
6594
}
6695

6796
- (void)close {
97+
if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
98+
if (_file != nil) {
99+
[_file closeFile];
100+
101+
}
102+
[[NSFileManager defaultManager] removeItemAtPath: _filepath error: nil];
103+
104+
}
68105
}
69106

70107
- (NSString *)path {
71-
return self.assetURL.path;
108+
return _filepath;
72109
}
73110

74111
- (int64_t)modifyTime {
@@ -79,91 +116,53 @@ - (int64_t)size {
79116
return _fileSize;
80117
}
81118

82-
- (void)getInfo {
83-
if (!_hasGotInfo) {
84-
_hasGotInfo = YES;
85-
86-
if (PHAssetMediaTypeImage == self.phAsset.mediaType) {
87-
PHImageRequestOptions *request = [PHImageRequestOptions new];
88-
request.version = PHImageRequestOptionsVersionCurrent;
89-
request.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
90-
request.resizeMode = PHImageRequestOptionsResizeModeNone;
91-
request.synchronous = YES;
119+
- (NSString *)getInfo {
120+
__block NSString * filePath = nil;
121+
if (PHAssetMediaTypeImage == self.phAsset.mediaType) {
122+
PHImageRequestOptions *options = [PHImageRequestOptions new];
123+
options.version = PHImageRequestOptionsVersionCurrent;
124+
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
125+
options.resizeMode = PHImageRequestOptionsResizeModeNone;
126+
//不支持icloud上传
127+
options.networkAccessAllowed = NO;
128+
options.synchronous = YES;
92129

93130
[[PHImageManager defaultManager] requestImageDataForAsset:self.phAsset
94-
options:request
131+
options:options
95132
resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
133+
_assetData = imageData;
96134
_fileSize = imageData.length;
97135
_assetURL = [NSURL URLWithString:self.phAsset.localIdentifier];
136+
filePath = _assetURL.path;
98137
}];
99138
} else if (PHAssetMediaTypeVideo == self.phAsset.mediaType) {
100-
PHVideoRequestOptions *request = [PHVideoRequestOptions new];
101-
request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
102-
request.version = PHVideoRequestOptionsVersionCurrent;
103-
104-
NSConditionLock *assetReadLock = [[NSConditionLock alloc] initWithCondition:kAMASSETMETADATA_PENDINGREADS];
105-
[[PHImageManager defaultManager] requestPlayerItemForVideo:self.phAsset options:request resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) {
106-
AVURLAsset *urlAsset = (AVURLAsset *)playerItem.asset;
107-
NSNumber *fileSize = nil;
108-
[urlAsset.URL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil];
109-
_fileSize = [fileSize unsignedLongLongValue];
110-
_assetURL = urlAsset.URL;
111-
112-
[assetReadLock lock];
113-
[assetReadLock unlockWithCondition:kAMASSETMETADATA_ALLFINISHED];
139+
NSArray * assetResources = [PHAssetResource assetResourcesForAsset: self.phAsset];
140+
PHAssetResource * resource;
141+
for (PHAssetResource * assetRes in assetResources) {
142+
if (assetRes.type == PHAssetResourceTypePairedVideo || assetRes.type == PHAssetResourceTypeVideo) {
143+
resource = assetRes;
144+
}
145+
}
146+
NSString * fileName = @"tempAssetVideo.mov";
147+
if (resource.originalFilename) {
148+
fileName = resource.originalFilename;
149+
}
150+
PHVideoRequestOptions * options = [[PHVideoRequestOptions alloc] init];
151+
options.version = PHImageRequestOptionsVersionCurrent;
152+
//不支持icloud上传
153+
options.networkAccessAllowed = NO;
154+
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
155+
NSString * PATH_VIDEO_FILE = [NSTemporaryDirectory() stringByAppendingPathComponent: fileName];
156+
[[NSFileManager defaultManager] removeItemAtPath: PATH_VIDEO_FILE error: nil];
157+
[[PHAssetResourceManager defaultManager] writeDataForAssetResource: resource toFile: [NSURL fileURLWithPath: PATH_VIDEO_FILE] options: options completionHandler: ^(NSError * _Nullable error) {
158+
if (error) {
159+
filePath = nil;
160+
} else {
161+
filePath = PATH_VIDEO_FILE;
162+
}
114163
}];
115-
[assetReadLock lockWhenCondition:kAMASSETMETADATA_ALLFINISHED];
116-
[assetReadLock unlock];
117-
assetReadLock = nil;
118-
}
119-
}
120-
}
121-
122-
- (NSData *)fetchDataFromAsset:(PHAsset *)asset {
123-
__block NSData *tmpData = [NSData data];
124-
125-
// Image
126-
if (asset.mediaType == PHAssetMediaTypeImage) {
127-
PHImageRequestOptions *request = [PHImageRequestOptions new];
128-
request.version = PHImageRequestOptionsVersionCurrent;
129-
request.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
130-
request.resizeMode = PHImageRequestOptionsResizeModeNone;
131-
request.synchronous = YES;
132-
133-
[[PHImageManager defaultManager] requestImageDataForAsset:asset
134-
options:request
135-
resultHandler:
136-
^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
137-
tmpData = [NSData dataWithData:imageData];
138-
}];
139164
}
140-
// Video
141-
else {
142-
143-
PHVideoRequestOptions *request = [PHVideoRequestOptions new];
144-
request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
145-
request.version = PHVideoRequestOptionsVersionCurrent;
146-
147-
NSConditionLock *assetReadLock = [[NSConditionLock alloc] initWithCondition:kAMASSETMETADATA_PENDINGREADS];
148-
149-
[[PHImageManager defaultManager] requestAVAssetForVideo:asset
150-
options:request
151-
resultHandler:
152-
^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
153-
AVURLAsset *urlAsset = (AVURLAsset *)asset;
154-
NSData *videoData = [NSData dataWithContentsOfURL:urlAsset.URL];
155-
tmpData = [NSData dataWithData:videoData];
156-
157-
[assetReadLock lock];
158-
[assetReadLock unlockWithCondition:kAMASSETMETADATA_ALLFINISHED];
159-
}];
160-
161-
[assetReadLock lockWhenCondition:kAMASSETMETADATA_ALLFINISHED];
162-
[assetReadLock unlock];
163-
assetReadLock = nil;
164-
}
165-
166-
return tmpData;
165+
return filePath;
167166
}
168167

169168
@end

0 commit comments

Comments
 (0)