I have the following setup:
My app writes UIDocument instances to iCloud. The files get synced and everything works fine. But when I try to delete them they keep reappearing. Before I delete the files I close them. Here is the code that deletes the files:
- (void)deleteDocumentWithName:(NSString*)name completion:(void (^)(BOOL success))completion
{
[self stopQuery];
NSURL* toDelete = [self URLForFileWithName:name];
UIDocument* doc = [[UIDocument alloc] initWithFileURL:toDelete];
void (^deleteDocument)() = ^() {
// Wrap in file coordinator
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateWritingItemAtURL:toDelete
options:NSFileCoordinatorWritingForDeleting
error:nil
byAccessor:^(NSURL* writingURL) {
// Simple delete to start
NSFileManager* fileManager = [[NSFileManager alloc] init];
NSError* error = nil;
[fileManager removeItemAtURL:writingURL error:&error];
if (error) {
LogError(#"%s - error while deleting file: %#", __PRETTY_FUNCTION__, error);
}
dispatch_async(dispatch_get_main_queue(), ^{
[_files removeObject:toDelete];
if (completion) {
completion((error == nil));
}
[self startQuery];
});
}];
});
};
if (doc) {
if (doc.documentState == UIDocumentStateNormal) {
[doc closeWithCompletionHandler:^(BOOL success) {
if (success) {
deleteDocument();
} else {
if (completion) {
completion(NO);
}
}
}];
} else {
deleteDocument();
}
}
}
After this method was executed I get several NSMetadataQueryDidFinishGatheringNotifications. First it does not contain the deleted file. Then another NSMetadataQueryDidFinishGatheringNotification gets caught and it contains the deleted file again.
I can't find the reason for this. Any help is appreciated.
I faced similar issue. Remove the encapsulation of NSFileCoordinator instantiation from GCD, then you will be able to perform the delete operation (despite documentation that it's preferable to have this operation in the background thread, which is odd because doing so actually causes this unable-to-delete issue in the first place)
void (^deleteDocument)() = ^() {
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateWritingItemAtURL:toDelete
options:NSFileCoordinatorWritingForDeleting
error:nil
byAccessor:^(NSURL* writingURL) {
// Simple delete to start
NSFileManager* fileManager = [[NSFileManager alloc] init];
NSError* error = nil;
[fileManager removeItemAtURL:writingURL error:&error];
if (error) {
LogError(#"%s - error while deleting file: %#", __PRETTY_FUNCTION__, error);
}
[_files removeObject:toDelete];
if (completion) {
completion((error == nil));
}
[self startQuery];
}];
};
Related
i have an big problem with my situation
my main problem is i need fetch video one by one do some operation on the video name and save it to the file system and again fetch another video do some operation on the video name and save it to the file system through the loop of asset the problem is completion handler prevent me do that because it saving all videos together without i do any editing and changing the name this save all videos i think it is working on background thread please any help to fix this problem i need handle fetch video one by one
this is my code
for asset in arrayOfAssets {
if asset.mediaType == .video {
PHImageManager.default().requestAVAsset(forVideo: asset, options: nil, resultHandler: { (AVAsset, AVAudio, info) in
// i need access to this place so i can fetch the video one by one and working with the AVAsset
})
}else{
let imageOp = PHImageRequestOptions()
PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width:125,height:125), contentMode: .aspectFit, options: imageOp, resultHandler: { (img, info) in
print(img!)
})
}
}
i think this one is related to your query
for Vedios
How Can i Get the List of all Video files from Library in ios sdk
for Images
Get all of the pictures from an iPhone photoLibrary in an array using AssetsLibrary framework?
allVideos = [[NSMutableArray alloc] init];
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
[assetLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group)
{
[group setAssetsFilter:[ALAssetsFilter allVideos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
dic = [[NSMutableDictionary alloc] init];
ALAssetRepresentation *defaultRepresentation = [asset defaultRepresentation];
NSString *uti = [defaultRepresentation UTI];
NSURL *videoURL = [[asset valueForProperty:ALAssetPropertyURLs] valueForKey:uti];
NSString *title = [NSString stringWithFormat:#"video %d", arc4random()%100];
UIImage *image = [self imageFromVideoURL:videoURL];
[dic setValue:image forKey:#"image"];
[dic setValue:title forKey:#"name"];
[dic setValue:videoURL forKey:#"url"];
[`allVideos` addObject:dic];
}
}];
else
{
}
}
failureBlock:^(NSError *error)
{
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
--------for ALL PHOTOS
NSArray *imageArray;
NSMutableArray *mutableArray;
-(void)getAllPhotosFromCamera
{
imageArray=[[NSArray alloc] init];
mutableArray =[[NSMutableArray alloc]init];
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
requestOptions.synchronous = true;
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
NSLog(#"%d",(int)result.count);
PHImageManager *manager = [PHImageManager defaultManager];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:[result count]];
// assets contains PHAsset objects.
__block UIImage *ima;
for (PHAsset *asset in result) {
// Do something with the asset
[manager requestImageForAsset:asset
targetSize:PHImageManagerMaximumSize
contentMode:PHImageContentModeDefault
options:requestOptions
resultHandler:^void(UIImage *image, NSDictionary *info) {
ima = image;
[images addObject:ima];
}];
}
imageArray = [images copy]; // You can direct use NSMutuable Array images
}
I have made a singleton to handle menu changes (navigating through menu hierarchy) in my game. I don't know why the menu is not displaying. Please see my MenuManager classes singleton below.
MenuManager.h:
#interface MenuManager : NSObject
{
MenuLayerTypes currentMenuLayer;
CCLayer* runningLayer;
CCLayer* oldLayer;
}
+(MenuManager*)sharedMenuManager;
-(void)runMenuWithID:(MenuLayerTypes)menuLayerID;
#end
MenuManager.m:
#import "MenuManager.h"
#implementation MenuManager
static MenuManager* _sharedMenuManager = nil;
+(MenuManager*)sharedMenuManager
{
#synchronized([MenuManager class])
{
if (!_sharedMenuManager)
[[self alloc] init];
return _sharedMenuManager;
}
return nil;
}
+(id)alloc
{
#synchronized ([MenuManager class])
{
NSAssert(_sharedMenuManager == nil,
#"Attempted to allocated a second instance of the Menu Manager singleton");
_sharedMenuManager = [super alloc];
return _sharedMenuManager;
}
return nil;
}
-(id)init
{
self = [super init];
if (self != nil)
{
Layer = kMainMenuLayer; // default menu type
}
return self;
}
-(void)runMenuWithID:(MenuLayerTypes)menuLayerID {
//MenuLayerTypes oldMenuLayer = currentMenuLayer;
currentMenuLayer = menuLayerID;
oldLayer.tag = 321;
switch (menuLayerID)
{
case kMainMenuLayer:
CCLOG(#"main menu layer");
runningLayer = [MainMenuLayer node];
oldLayer = runningLayer;
break;
case kSettingsLayer:
runningLayer = [SettingsLayer node];
oldLayer = runningLayer;
break;
case kAckLayer:
runningLayer = [AckLayer node];
oldLayer = runningLayer;
break;
default:
CCLOG(#"Unknown ID");
return;
break;
}
MainMenuScene* mainMenuScene = (MainMenuScene *)[[CCDirector sharedDirector] runningScene];
// checks to see if a menu layer is already displayed before replacing it
if (![mainMenuScene getChildByTag:321]) {
[mainMenuScene addChild:runningLayer];
}
else {
[mainMenuScene removeChildByTag:321];
[mainMenuScene addChild:runningLayer];
}
}
#end
Also in the init of the MainMenuScene:
[[MenuManager sharedMenuManager] runMenuWithID:kMainMenuLayer];
How can I solve this display issue?
I've added iAP in cocos2d following the ray tutorials (but changed a few things to fit cocos2d) but after I make a transaction the console log says 2013-08-19 16:32:12.626 Game[2483:907] Buying *product* ...
2013-08-19 16:32:13.208 Game[2483:907] cocos2d: animation stopped
2013-08-19 16:32:16.690 Game[2483:907] completeTransaction...
2013-08-19 16:32:16.725 Game[2483:907] User defaults for *product* are YES
So I know the transaction works, but the game never resumes it just freezes. Is there a way to resume the game after the transaction? [[CCDirector sharedDirector]resume] doesn't work so I think it may have to do with UIAlert View. Any help? Here is my iAPHelper.mm:
#import "IAPHelper.h"
#import <StoreKit/StoreKit.h>
NSString *const IAPHelperProductPurchasedNotification
#"IAPHelperProductPurchasedNotification";
#interface IAPHelper () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
#end
#implementation IAPHelper {
SKProductsRequest * _productsRequest;
RequestProductsCompletionHandler _completionHandler;
NSSet * _productIdentifiers;
NSMutableSet * _purchasedProductIdentifiers;
}
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {
if ((self = [super init])) {
// Store product identifiers
_productIdentifiers = productIdentifiers;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// Check for previously purchased products
_purchasedProductIdentifiers = [NSMutableSet set];
for (NSString * productIdentifier in _productIdentifiers) {
BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];
if (productPurchased) {
[_purchasedProductIdentifiers addObject:productIdentifier];
NSLog(#"Previously purchased: %#", productIdentifier);
} else {
NSLog(#"Not purchased: %#", productIdentifier);
}
}
}
return self;
}
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
_completionHandler = [completionHandler copy];
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(#"Loaded list of products...");
_productsRequest = nil;
NSArray * skProducts = response.products;
for (SKProduct * skProduct in skProducts) {
NSLog(#"Found product: %# %# %0.2f",
skProduct.productIdentifier,
skProduct.localizedTitle,
skProduct.price.floatValue);
}
_completionHandler(YES, skProducts);
_completionHandler = nil;
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(#"Failed to load list of products.");
_productsRequest = nil;
_completionHandler(NO, nil);
_completionHandler = nil;
}
- (BOOL)productPurchased:(NSString *)productIdentifier {
return [_purchasedProductIdentifiers containsObject:productIdentifier];
}
- (void)buyProduct:(SKProduct *)product {
NSLog(#"Buying %#...", product.productIdentifier);
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction * transaction in transactions) {
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
default:
break;
}
};
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(#"completeTransaction...");
[self provideContentForProductIdentifier:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
NSLog(#"restoreTransaction...");
[self provideContentForProductIdentifier:transaction.originalTransaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
NSLog(#"failedTransaction...");
if (transaction.error.code != SKErrorPaymentCancelled)
{
NSLog(#"Transaction error: %#", transaction.error.localizedDescription);
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
- (void)provideContentForProductIdentifier:(NSString *)productIdentifier {
[_purchasedProductIdentifiers addObject:productIdentifier];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:productIdentifier];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:IAPHelperProductPurchasedNotification object:productIdentifier userInfo:nil];
NSLog(#"User defaults for %# are YES", productIdentifier);
}
- (void)restoreCompletedTransactions {
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
#end
Before you popup your alert view try running...
[[CCDirector sharedDirector] stopAnimation];
When you get a response back from the user in the alertview callback or transaction completion run...
[[CCDirector sharedDirector] startAnimation];
Cocos doesn't often play well with UIKit/Cocoa callbacks so you need to pause rendering while they do their thing. We have similar behaviour for when the app goes into background/foreground in the app delegate...
-(void) applicationDidEnterBackground:(UIApplication*)application {
[[CCDirector sharedDirector] stopAnimation];
}
-(void) applicationWillEnterForeground:(UIApplication *)application {
[[CCDirector sharedDirector] startAnimation];
}
-(void)applicationDidBecomeActive:(UIApplication *)application {
[[CCDirector sharedDirector] resume];
}
Seems we use resume inside the applicationDidBecomeActive. Can't recall the full logic there but that has seemed to work for a bunch of our projects.
I'm confussed and tried many different things to eliminate the errors im facing.
I have a NSArray of proteins, in my storyboard i have two seperate table views that i wish to both display the protiens array.
i am having errors at -(UITableViewcell *) and #end of which there are two } errors.
If anyone can help please find my ViewController.m code below: (Please disregard the segue coding near the end)
#import "JViewController.h"
#import "OneViewController.h"
#import "TwoViewController.h"
#interface JViewController ()
#end
#implementation JViewController
{
NSArray *proteins;
}
#synthesize tableView1;
#synthesize tableView2;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
proteins = [NSArray arrayWithObjects:#"Chicken", #"Turkey", #"Ham", #"Steak", #"Pork Chop", #"Roast Lamb", #"Salmon", #"Egg", #"Lentils", #"Kidney Beans", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == tableView1) {
return [proteins count];
{
if (tableView == tableView2) {
return [proteins count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProteinCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView1 == tableView2)
{
proteins;
}
else
{
proteins;
}
cell.textLabel.text = [proteins objectAtIndex:indexPath.row];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showMealOneDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
OneViewController *destViewController = segue.destinationViewController;
destViewController.proteinName = [proteins objectAtIndex:indexPath.row];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Big thankyou in advance.
You have two open brackets here, close this one:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == tableView1) {
return [proteins count];
->> {
if (tableView == tableView2) {
return [proteins count];
}
}
And what do you mean with this?
if (tableView1 == tableView2)
{
proteins;
}
else
{
proteins;
}
Try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProteinCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [proteins objectAtIndex:indexPath.row];
return cell;
}
Have you been able to show anything in one tableview? Make sure you have connected dataSource and delegate.
Hope it helps =)
Is there any one who knows how to integrate game center in Cocos2d.
Please tell me steps so i can integrate that in my Game.
UPDATE:
I created my own Helper Class that works with all kind of Apps (also Cocos2D 1 & 2+)
https://github.com/alexblunck/ABGameKitHelper
Hi I suggest you use GKHelper Class from Steffen Itterheim! I uploaded the GKHelper.h / GKHelper.m for you: http://www.cl.ly/7ReW
Then follow these instructions:
//0.0 Add GameKit Framework to Project (Ask If you don't know how to do this ;) )
//0. Change "[window addSubview: viewController.view];" in the AppDelegate.m to:
//Do this if you're using any release of cocos2D after 0.99.5:
window.rootViewController = viewController;
//1. Add Gamekithelper.h / .m to project
//2. Include following delegate in given header:
<GameKitHelperProtocol>
//3. Add Delegate Methods to .m
//4. Add GameKitHelper to "Scene":
GameKitHelper *gkHelper = [GameKitHelper sharedGameKitHelper];
gkHelper.delegate = self;
[gkHelper authenticateLocalPlayer];
//Adding score to leaderboard:
GameKitHelper *gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper submitScore:scoreValue category:#"LeaderboardID"];
//Adding achievement completion:
GameKitHelper *gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper reportAchievementWithID:#"AchievementID" percentComplete:100];
These are the delegate Methods that need to be added mentioned in Step #3:
#pragma mark GameKitHelper delegate methods
-(void) onLocalPlayerAuthenticationChanged
{
GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
CCLOG(#"LocalPlayer isAuthenticated changed to: %#", localPlayer.authenticated ? #"YES" : #"NO");
if (localPlayer.authenticated)
{
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper getLocalPlayerFriends];
//[gkHelper resetAchievements];
}
}
-(void) onFriendListReceived:(NSArray*)friends
{
CCLOG(#"onFriendListReceived: %#", [friends description]);
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper getPlayerInfo:friends];
}
-(void) onPlayerInfoReceived:(NSArray*)players
{
CCLOG(#"onPlayerInfoReceived: %#", [players description]);
}
-(void) onScoresSubmitted:(bool)success
{
CCLOG(#"onScoresSubmitted: %#", success ? #"YES" : #"NO");
}
-(void) onScoresReceived:(NSArray*)scores
{
CCLOG(#"onScoresReceived: %#", [scores description]);
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper showAchievements];
}
-(void) onAchievementReported:(GKAchievement*)achievement
{
CCLOG(#"onAchievementReported: %#", achievement);
}
-(void) onAchievementsLoaded:(NSDictionary*)achievements
{
CCLOG(#"onLocalPlayerAchievementsLoaded: %#", [achievements description]);
}
-(void) onResetAchievements:(bool)success
{
CCLOG(#"onResetAchievements: %#", success ? #"YES" : #"NO");
}
-(void) onLeaderboardViewDismissed
{
CCLOG(#"onLeaderboardViewDismissed");
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper];
[gkHelper retrieveTopTenAllTimeGlobalScores];
}
-(void) onAchievementsViewDismissed
{
CCLOG(#"onAchievementsViewDismissed");
}
-(void) onReceivedMatchmakingActivity:(NSInteger)activity
{
CCLOG(#"receivedMatchmakingActivity: %i", activity);
}
-(void) onMatchFound:(GKMatch*)match
{
CCLOG(#"onMatchFound: %#", match);
}
-(void) onPlayersAddedToMatch:(bool)success
{
CCLOG(#"onPlayersAddedToMatch: %#", success ? #"YES" : #"NO");
}
-(void) onMatchmakingViewDismissed
{
CCLOG(#"onMatchmakingViewDismissed");
}
-(void) onMatchmakingViewError
{
CCLOG(#"onMatchmakingViewError");
}
-(void) onPlayerConnected:(NSString*)playerID
{
CCLOG(#"onPlayerConnected: %#", playerID);
}
-(void) onPlayerDisconnected:(NSString*)playerID
{
CCLOG(#"onPlayerDisconnected: %#", playerID);
}
-(void) onStartMatch
{
CCLOG(#"onStartMatch");
}
-(void) onReceivedData:(NSData*)data fromPlayer:(NSString*)playerID
{
CCLOG(#"onReceivedData: %# fromPlayer: %#", data, playerID);
}
You can go through with GamKit framework . Game center is very powerful for managing your online game and game score as well . with game center there are two types of game you can create
1: Real time matches (Real time Car racing)
2: Turn Base Matches (Online card game )
I am sharing with you link of RaywenderLich :
Real time match : http://www.raywenderlich.com/3276/game-center-tutorial-for-ios-how-to-make-a-simple-multiplayer-game-part-12
Turn Based Match http://www.raywenderlich.com/5480/beginning-turn-based-gaming-with-ios-5-part-1
Although Alexander Blunck's answer is reasonable, for earlier versions of iOS (such as 3.2) the following line will fault, which is not what you want.
window.rootViewController = viewController;
If you are going to use Steffen's code (ugh) then you might want to add a method to set the ui view controller directly rather than having it assume it can be grabbed via UIApplication.