我在iOS 8上遇到了一个问题,资产库框架似乎是iOS 8中的一个错误。如果我创建一个名为' MyMedia'然后删除它,然后当我再次尝试创建相册时,下面这段代码返回' nil'表明专辑“MyMedia'即使它没有存在,因为我使用'照片'删除了它。应用
__block ALAssetsGroup *myGroup = nil;
__block BOOL addAssetDone = false;
NSString *albumName = @"MyMedia";
[assetsLib addAssetsGroupAlbumWithName:albumName
resultBlock:^(ALAssetsGroup *group) {
myGroup = group;
addAssetDone = true;
} failureBlock:^(NSError *error) {
NSLog( @"failed to create album: %@", albumName);
addAssetDone = true;
}];
while (!addAssetDone) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05f]];
}
return myGroup; // returns nil if group has previously been created and then deleted
同样的方法适用于制作全新专辑“MyMedia2”。'有没有其他人遇到此问题,并知道解决方法或解决方案?是唯一能够转移到新照片的解决方案吗?框架或我在这里做错了什么?请注意,此代码始终适用于iOS7.X
实际上,重现此问题的步骤如下 - > 1.卸载拍摄照片并将其保存到自定义相册的应用 2.在iOS照片下,删除已保存照片的自定义相册 3.安装您的应用程序 4.如果您使用应用程序拍摄照片或录制视频,则不会创建或存储它们。如果您在iOS相册下查看,则自定义相册不存在,并且不存在使用该应用拍摄的所有照片/视频。
答案 0 :(得分:11)
我之前的回答是不正确的。我还没有真正测试过它。我终于弄明白了要做什么,这很困难,但我得到了它的工作。这是我必须要做的就是让我的应用程序在iOS 7.x.X和iOS 8.X.x上运行并创建一个以前被应用程序删除的自定义相册 - >
我写了两个代码块:一个使用iOS 8.x.x上的Photos框架,另一个使用iOS 7.x.x上的AssetsLibrary框架
Sp可以在两个iOS版本上运行,我将应用程序链接到Photos框架,但后来将其从必需更改为可选,因此不会在iOS 7.xx上加载
因为在iOS 7.xx上无法在运行时直接调用Photos框架代码,所以我必须更改它,以便在运行时动态加载类,函数(和块!)
以下是在iPhone上运行时可以使用的代码块。这应该也适用于模拟器 - >
// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x
Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");
if (PHPhotoLibrary_class) {
/**
*
iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ...
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error creating album: %@", error);
}
}];
*/
// dynamic runtime code for code chunk listed above
id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")];
SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:");
NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges];
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig];
[inv setTarget:sharedPhotoLibrary];
[inv setSelector:performChanges];
void(^firstBlock)() = ^void() {
Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest");
SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:");
[PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName];
};
void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error) {
if (success) {
[assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([albumName isEqualToString:name]) {
groupFound = true;
handler(group, nil);
}
}
} failureBlock:^(NSError *error) {
handler(nil, error);
}];
}
if (error) {
NSLog(@"Error creating album: %@", error);
handler(nil, error);
}
};
// Set the success and failure blocks.
[inv setArgument:&firstBlock atIndex:2];
[inv setArgument:&secondBlock atIndex:3];
[inv invoke];
}
else {
// code that always creates an album on iOS 7.x.x but fails
// in certain situations such as if album has been deleted
// previously on iOS 8...x. .
[assetsLib addAssetsGroupAlbumWithName:albumName
resultBlock:^(ALAssetsGroup *group) {
handler(group, nil);
} failureBlock:^(NSError *error) {
NSLog( @"Failed to create album: %@", albumName);
handler(nil, error);
}];
}
答案 1 :(得分:3)
使用Adam的答案,以及Marin Todorov在ALAssetsLibrary上的类别,ALAssetsLibrary + CustomPhotoAlbum来创建相册,并在其中放置照片,下面的代码替换了该类别中的主要工作主体,它可以在iOS7设备和iOS 8.1设备都适用于那些需要同时使用这两种设备的人。
它给出了关于未知类的performSelector的两个警告,但是,任何改进都值得赞赏:
(它不会复制您未创建的共享相册中的照片,并且会因消息而失败,所有增强功能也会很好)
1)添加"照片"框架,设置为"可选"
2)包括导入行#import<照片/ PHPhotoLibrary.h>
//----------------------------------------------------------------------------------------
- (void)addAssetURL:(NSURL *)assetURL
toAlbum:(NSString *)albumName
completion:(ALAssetsLibraryWriteImageCompletionBlock)completion
failure:(ALAssetsLibraryAccessFailureBlock)failure
{
NSLog();
__block BOOL albumWasFound = NO;
//-----------------------------------------
ALAssetsLibraryGroupsEnumerationResultsBlock enumerationBlock;
enumerationBlock = ^(ALAssetsGroup *group, BOOL *stop)
{
NSLog(@" ALAssetsLibraryGroupsEnumerationResultsBlock");
// Compare the names of the albums
if ([albumName compare:[group valueForProperty:ALAssetsGroupPropertyName]] == NSOrderedSame)
{
NSLog(@"--------------Target album is found");
// Target album is found
albumWasFound = YES;
// Get a hold of the photo's asset instance
// If the user denies access to the application, or if no application is allowed to
// access the data, the failure block is called.
ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock =
[self _assetForURLResultBlockWithGroup:group
assetURL:assetURL
completion:completion
failure:failure];
[self assetForURL:assetURL
resultBlock:assetForURLResultBlock
failureBlock:failure];
// Album was found, bail out of the method
*stop = YES;
}
if (group == nil && albumWasFound == NO)
{
NSLog(@"--------------Target album does not exist");
// Photo albums are over, target album does not exist, thus create it
// Since you use the assets library inside the block,
// ARC will complain on compile time that there’s a retain cycle.
// When you have this – you just make a weak copy of your object.
ALAssetsLibrary * __weak weakSelf = self;
// If iOS version is lower than 5.0, throw a warning message
if (! [self respondsToSelector:@selector(addAssetsGroupAlbumWithName:resultBlock:failureBlock:)])
{
NSLog(@"--------------Target album does not exist and does not respond to addAssetsGroupAlbumWithName");
} else {
NSLog(@"--------------Target album does not exist addAssetsGroupAlbumWithName");
// ----------- PHPhotoLibrary_class will only be non-nil on iOS 8.x.x -----------
Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");
NSLog(@"PHPhotoLibrary_class %@ ", PHPhotoLibrary_class);
if (PHPhotoLibrary_class)
{
NSLog(@"iOS8");
// --------- dynamic runtime code -----------
id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")];
NSLog(@"sharedPhotoLibrary %@ ", sharedPhotoLibrary);
SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:");
NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges];
NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig];
[inv setTarget:sharedPhotoLibrary];
[inv setSelector:performChanges];
void(^firstBlock)() = ^void()
{
NSLog(@"firstBlock");
Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest");
SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:");
NSLog(@"PHAssetCollectionChangeRequest_class %@ ", PHAssetCollectionChangeRequest_class);
[PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName];
};
void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error)
{
NSLog(@"secondBlock");
if (success)
{
NSLog(@"success");
[self enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *fullStop)
{
if (group)
{
NSLog(@"group %@ ", group);
NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
if ([albumName isEqualToString:name])
{
NSLog(@"[albumName isEqualToString:name] %@ ", name);
ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock =
[self _assetForURLResultBlockWithGroup:group
assetURL:assetURL
completion:completion
failure:failure];
[self assetForURL:assetURL
resultBlock:assetForURLResultBlock
failureBlock:failure];
*fullStop = YES;
}
}
} failureBlock:failure];
}
if (error)
{
NSLog(@"Error creating album: %@", error);
}
};
// Set the success and failure blocks.
[inv setArgument:&firstBlock atIndex:2];
[inv setArgument:&secondBlock atIndex:3];
[inv invoke];
} else {
NSLog(@"iOS7");
[self addAssetsGroupAlbumWithName:albumName resultBlock:^(ALAssetsGroup *createdGroup)
{
// Get the photo's instance, add the photo to the newly created album
ALAssetsLibraryAssetForURLResultBlock assetForURLResultBlock =
[weakSelf _assetForURLResultBlockWithGroup:createdGroup
assetURL:assetURL
completion:completion
failure:failure];
[weakSelf assetForURL:assetURL
resultBlock:assetForURLResultBlock
failureBlock:failure];
}
failureBlock:failure];
}
}
// Should be the last iteration anyway, but just in case
*stop = YES;
}
};
// Search all photo albums in the library
[self enumerateGroupsWithTypes:ALAssetsGroupAlbum
usingBlock:enumerationBlock
failureBlock:failure];
}
答案 2 :(得分:2)
您可以尝试使用我的以下方法为iOS 7和iOS 8创建相册
#define PHOTO_ALBUM_NAME @"AlbumName Videos"
#pragma mark - Create Album
-(void)createAlbum{
// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x
Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");
if (PHPhotoLibrary_class) {
// iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ...
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:PHOTO_ALBUM_NAME];
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error creating album: %@", error);
}else{
NSLog(@"Created");
}
}];
}else{
[self.library addAssetsGroupAlbumWithName:PHOTO_ALBUM_NAME resultBlock:^(ALAssetsGroup *group) {
NSLog(@"adding album:'Compressed Videos', success: %s", group.editable ? "YES" : "NO");
if (group.editable == NO) {
}
} failureBlock:^(NSError *error) {
NSLog(@"error adding album");
}];
}}
答案 3 :(得分:1)
只是想更新我应该尽早更新的所有人,但我有点淹没了工作。这个问题是iOS 8的一个问题,但已经在iOS 8.0.2中得到修复,因此您需要做的就是将iOS更新为iOS 8.0.2
答案 4 :(得分:1)
我使用以下代码检查特定相册是否存在,如果不存在,请创建它并向其添加几个图像。从UIImage创建资产后,我使用其占位符将其添加到相册而不离开该块。
// from
vector.insert(data);
// to
insert_poc(vector, data);
答案 5 :(得分:0)
由于以上建议都没有帮助我,所以我就是如何解决将资产(照片)保存到自定义相册名称的问题。 此代码:" fetchCollectionResult.count == 0"你专门处理了一次删除你的自定义专辑并尝试再次保存的情况,因为我认为fetchCollectionResult可能会停止生成' nil'。 您可以轻松更改此设置以支持保存视频/电影。
此代码仅适用于iOS 8! 如果设备在早期版本上运行,您必须确保不要调用它!
#define PHOTO_ALBUM_NAME @"MyPhotoAlbum"
NSString* existingAlbumIdentifier = nil;
-(void)saveAssetToAlbum:(UIImage*)myPhoto
{
PHPhotoLibrary* photoLib = [PHPhotoLibrary sharedPhotoLibrary];
__block NSString* albumIdentifier = existingAlbumIdentifier;
__block PHAssetCollectionChangeRequest* collectionRequest;
[photoLib performChanges:^
{
PHFetchResult* fetchCollectionResult;
if ( albumIdentifier )
fetchCollectionResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[albumIdentifier] options:nil];
// Create a new album
if ( !fetchCollectionResult || fetchCollectionResult.count==0 )
{
NSLog(@"Creating a new album.");
collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:PHOTO_ALBUM_NAME];
albumIdentifier = collectionRequest.placeholderForCreatedAssetCollection.localIdentifier;
}
// Use existing album
else
{
NSLog(@"Fetching existing album, of #%d albums found.", fetchCollectionResult.count);
PHAssetCollection* exisitingCollection = fetchCollectionResult.firstObject;
collectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:exisitingCollection];
}
NSLog(@"Album local identifier = %@", albumIdentifier);
PHAssetChangeRequest* createAssetRequest;
createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:myPhoto];
[collectionRequest addAssets:@[createAssetRequest.placeholderForCreatedAsset]];
}
completionHandler:^(BOOL success, NSError *error)
{
if (success)
{
existingAlbumIdentifier = albumIdentifier;
NSLog(@"added image to album:%@", PHOTO_ALBUM_NAME);
}
else
NSLog(@"Error adding image to album: %@", error);
}];
}