iCloud only seems to work on start up - iphone

I'm trying to create an iCloud app that uses Core Data. To do so, I use a single instance of UIManagedDocument. For persistentStoreOptions, I set "Database.data" for NSPersistentStoreUbiquitousContentNameKey and -iCloudURL-/CoreData_Logs for NSPersistentStoreUbiquitousContentURLKey. As by Apple suggested, I open the document like so:
if ([[NSFileManager defaultManager] fileExistsAtPath:[urlOfDatabase path]])
{
[_database openWithCompletionHandler:^(BOOL success) { ... }];
}
else
{
[_database saveToURL:urlOfDatabase
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) { ... }];
}
Also, I registered for NSPersistentStoreDidImportUbiquitousContentChangesNotifications, and merge the context from the notification in that method.
To test the app, I use an iPad and an iPhone. When I run it on one device, add some data, and open it up on the other device, the correct data is displayed. If I however add data while the app is running on both devices, it either doesn't update (I've waited for at least 10 minutes once) or it updates after a few minutes but only with a whole bunch of error messages: "The item failed to download.".
Did I miss something (hopefully obvious) in my set up?

Related

iOS print without allowing UIPrintInteractionController to appear

I am researching a potential app for a client, and I had a question I wasn't able to find the answer on. What I would like to do is print automatically, without having the UIPrintInteractionController get displayed. An important point I should make is this will not be a production app. I know that otherwise this could violate the user's privacy to just print without the user's consent, but again this will not be a public app on the App Store. One app I found that seems to be able to this is Printer Pro. The user is prompted to print a test page, and the page prints without the UIPrintInteractionController appearing - this app is on the store, so I'm assuming there's a legal way to do it. Anyone know how this is done?
As far as I know it is not possible to print in iOS7 without invoking the UIPrintInteractionController and displaying the system print dialog.
However, iOS8 now provides a provision for printing directly to a print without showing the dialog. The basic idea is that you obtain a UIPrinter object and use this in conjunction with the new - printToPrinter:completionHandler: method of the UIPrintInteractionController to print without showing the dialog.
Obtaining the UIPrinter object for your printer can be accomplished in a couple of ways.
The most straightforward is to use the new UIPrinterPickerController. But this would show a dialog and so doesn’t meet your needs.
The alternative is to create a printer via its URL using the UIPrinter method
+ printerWithURL:. I’m not entirely clear how to obtain this URL but it may be contained in the printer’s HTML admin pages. And I believe you can obtain it programmatically using the Bonjour API. More info here:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/NetServices/Introduction.html#//apple_ref/doc/uid/10000119i
Bonjour is a service discovery API which includes discovery of IPP printers, which the is the protocol used by AirPrint.
As for how the Printer Pro app is able to print without a dialog in iOS7, I would guess they are interacting with the printer at a very low level (e.g. raw HTTP posts, etc.).
Follow these steps to Print the Documents without prompting..
First Search for Devices Using the Below Code...
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {
UIPrinterPickerController *printPicker = [UIPrinterPickerController printerPickerControllerWithInitiallySelectedPrinter:nil];
[printPicker presentAnimated:YES completionHandler:
^(UIPrinterPickerController *printerPicker, BOOL userDidSelect, NSError *error) {
if (userDidSelect) {
//User selected the item in the UIPrinterPickerController and got the printer details.
[UIPrinterPickerController printerPickerControllerWithInitiallySelectedPrinter:printerPicker.selectedPrinter];
// Here you will get the printer and printer details.ie,
// printerPicker.selectedPrinter, printerPicker.selectedPrinter.displayName, printerPicker.selectedPrinter.URL etc. So you can display the printer name in your label text or button title.
NSURL *printerURL = printerPicker.selectedPrinter.URL;
NSLog(#"printerURL--->%#",printerURL.absoluteString);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[printerURL absoluteString] forKey:#"printURL"];
[defaults synchronize];
}
}];
}
And Print the Documents by without prompting by using the below code...
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
UIPrinter *currentPrinterObj = [UIPrinter printerWithURL:[NSURL URLWithString:[defaults stringForKey:[defaults stringForKey:#"printURL"]]]];
UIPrintInteractionController *controller = [UIPrintInteractionController sharedPrintController];
if(currentPrinterObj) {
[controller printToPrinter:currentPrinterObj completionHandler:^(UIPrintInteractionController *printController, BOOL completed, NSError *error) {
if(completed) {
} else {
NSLog(#"FAILED! due to error in domain %# with error code %u", error.domain, error.code);
}
}];
}
}

iOS5 Saving images to custom folder, ALAssetsLibrary fail

<><> ----
Aalok has answered this question, I'm just waiting for him to write it up so I can chose that as the correct answer. Until then, along with making the changes he describes below I had to call -- self.library = [[ALAssetsLibrary alloc] init]; -- before every attempt to save my image. As a precaution I also stopped the AVSession running until after the save, when is was restarted (using [session stopRunning]; and [session startRunning];
----- <><>
<><> ----- EDIT 2: You do not need to stop and restart the AV session, tested this thoroughly and it's working perfectly. ----- <><>
<><> ----- EDIT 3: after testing this on my device thoroughly, and it working perfectly, the code is not working once it's been through the review process and put on the store. Two identical devices (2x iPhone 4) running the same OS, one using my dev build, one off the app sotre, the ap store version still has the bug. Giving up with this for now ----- <><>
I'm using the category in this link to try to save to a custom folder:
http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/
Now it works some of the time, but not all. In the comments it's been suggested that the following code will detect if the group properties are nil:
if ([group valueForProperty:ALAssetsGroupPropertyURL] == nil)
{
NSLog(#”group properties are nil!”);
} else {
[group addAsset:asset];
}
Which I have, and it does detect if the properties are nil. So all good. What I'm struggling with is at that point setting the properties and saving the images. I'm guessing that at this point we can manually set the albumName and save the image, which I've tried, but the error still occurs.
Any ideas? Thank you.
I have facing the same problem with this same .h and .m file but find one solution for this after working on it for 2 to 3 days and the solution is very simple what I have to change is in .m file in
-(void)saveImage:(UIImage*)image toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletion)completionBlock
and in
-(void)addAssetURL:(NSURL*)assetURL toAlbum:(NSString*)albumName withCompletionBlock:(SaveImageCompletion)completionBlock
methods i just add this before calling the inside methods
//THE CHANGE dispatch_async(dispatch_get_main_queue(),^{ //
[self writeImageToSavedPhotosAlbum:image.CGImage orientation:(ALAssetOrientation)image.imageOrientation completionBlock:^(NSURL* assetURL, NSError* error)
{
//error handling
if (error!=nil)
{
completionBlock(error);
return;
}
//add the asset to the custom photo album
[self addAssetURL: assetURL toAlbum:albumName withCompletionBlock:completionBlock];
}];
//THE CHANGE }); //
AND Same for the other one
Happy Coding :)
EDIT
In second method I add a line below every completionBlock(nil); line
[[NSNotificationCenter defaultCenter] postNotificationName:kSaveSuccess object:nil];
And I use this notification to make sure that image is saved in album too. Till that time I Shows UIActivityIndicator with some text message and after successfully saved image one popup message is shown indicated that image is saved in album with album name. And while this time the UI is unresponsive i.e. user can't do any thing other then pressing home button of device :) ;)
Happy Coding :)

URLForUbiquityContainerIdentifier returns nil even if configured correctly

I am having the problem, that URLForUbiquityContainerIdentifier is returning nil in some cases even if the user has set up everything correctly in the settings. My code:
dispatch_async(someQueue, ^{
if (![[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]) {
ErrLog(#"iCloud container not available.");
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
[...]
});
});
Does anybody came across the same problem? I am setting nil as the container identifier which should work according to the Apple docs, but I am not so convinced anymore about that. Also this code works fine for the majority of users, but somehow not for everybody.
Check that you have enabled iCloud containers in your entitlement. The containers are not added by default when you enable entitlements. Click the "+" sign in Target/Summary/Entitlements to add your appId.
iPad mini with iOS7. I just have experienced that URLForUbiquityContainerIdentifier suddenly started to return nil. I tried restarting the device, but it didn't help.
Inside the Settings app, under the 'iCloud' menu. I noticed that 'Documents & Data' was set to Off.
Solution was to change 'Documents & Data' to 'On'.
If anyone is having the same problem using the iOS8 Betas, there seems to be a bug with the way the Entitlements are generated in Xcode 6. I was banging my head against this for days until coming across this post in the Apple Developer Forums: https://devforums.apple.com/thread/229509?
Essentially, Xcode generates a key named com.apple.developer.icloud-container-identifiers when it should be com.apple.developer.ubiquity-container-identifiers (ubiquity, not icloud). It may also have the value set as iCloud.$(CFBundleIdentifier) when it should be $(TeamIdentifierPrefix).$(CFBundleIdentifier).
Of course this may get fixed in the next Beta but for anyone as confused as me I hope this helps.
I'd look at your entitlement.plist on one app I needed to change $(TEAMID) to profile id
the numbers and letter before the dns in the profile - here is some code that will work with UIManagedDocument
/// test iCloud Access
- (void)initializeiCloudAccess {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil] != nil)
NSLog(#"iCloud is available\n");
else
NSLog(#"This Application requires iCloud, but it is not available.\n");
});
}
- (NSURL *)iCloudURL
{
return [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
}
- (NSURL *)iCloudDocumentsURL
{
return [[self iCloudURL] URLByAppendingPathComponent:#"Documents"];
}
- (NSURL *)iCloudCoreDataLogFilesURL
{
return [[self iCloudURL] URLByAppendingPathComponent:#"CoreDataLogs"];
}
URLForUbiquityContainerIdentifier alway return nil
NSURL *ubiquityURL = [fileManager URLForUbiquityContainerIdentifier:nil]; if (ubiquityURL == nil)
app build by xcode4.5
app is enable icloud
ios is loginned icloud account
ubiquityURL is normal in debug, but ubiquityURL is always nil after distribution to appstore.
Today I experienced this problem again.
This time it was because I had an invalid provisioning profile.
On the developer site, I had to generate a new provisioning profile. Afterward reload the provisioning profiles within Xcode5. Now URLForUbiquityContainerIdentifier again returns valid urls.
If you still having issue o make sure you are running on a device as simulator wont always return a valid value .
I tried you code on my app and Im not getting nil
Enable "iCloud Drive" in the iPhone's Settings

Detect and Customize UIWebView's "Unable to Read Document" error

I'm testing a UIWebview with a number of different document types - .xlsx, .jpg, etc. - and it opens most of them just fine. From time to time, I open a local file and this message appears right in the web view:
Unable to Read Document
An error occurred while reading the document
I'm not concerned with "why" this error occurs - it happens, for instance, when I feed the UIWebView a garbage file (intentionally). The problem is that I can't figure out how to detect "when" this happens. It doesn't trigger webView:didFailLoadWithError, it doesn't trigger an NSException (via #try & #catch), and when I inspect the document in webViewDidFinishLoad, webView.request.HTTPBody is null.
Anyone know how to detect when UIWebView can't display content?
just call uiwebview delegate method
- (void)webViewDidStartLoad:(UIWebView *)webView
{
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *html = [webView stringByEvaluatingJavaScriptFromString:
#"document.body.innerHTML"];
if ([html rangeOfString:#"Unable to Read Document."].location == NSNotFound) {
NSLog(#"NO Error");
}
else
{
// NSLog(#"File contains Error");
}
}
If inspecting the log does not show anything out of the ordinary, run it on the actual device. As a bit of help, my log says
Cannot find data converter callback for uti public.data
Failed to generate preview
which means that the simulator is failing. After being frustrated with this same problem, I went thru the whole final certification and installation and provisioning process, and too confirm that Word 97 and Pages / Pages.zip files containing text do indeed display just fine on the actual device. SOLVED. The simulator itself is broken, which is very...troubling, that this little note didn't seem to make it into the release notes, and also complicates development a tad bit. However, the work around is to select the Device in Xcode and deploy out, and it should work.

Where can I find my iPhone app's Core Data persistent store?

I'm diving into iPhone development, so I apologize in advance if this is a ridiculous question, but in a new iPad app project using the Core Data framework, here's the generated code for creating the persistentStoreCoordinator...
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"ApplicationName.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
Typical reasons for an error here include:
* The persistent store is not accessible
* The schema for the persistent store is incompatible with current managed object model
Check the error message to determine what the actual problem was.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
My questions are...
The first time I run the app, is the ApplicationName.sqllite database created automatically if it doesn't exist? If not, when is it created? When data is added to it programmatically?
Once the DB does exist, where can I locate the file? I'd like to open it with a different program so I can manually manipulate the data.
Thanks so much in advance for your help! I'm going to continue researching these questions right now.
Yes, the ApplicationName.sqlite database will be created if none exists already. It will be located within your application's Documents directory (assuming that's what your -applicationDocumentsDirectory method returns).
If you are running this in the Simulator, you can generally find application data within ~/Library/Application Support/iPhone Simulator. On the 3.2+ SDK, different OS versions are used to group applications built using a particular SDK, so you'll need to go into the appropriate version directory, then Applications, then find the application's numerically coded directory (pretty much by trial-and-error). The Documents directory, and the sqlite database, will be found there.
If running on the device, you can go to the Organizer, select your device (while connected to the system), and go to the Applications grouping in the Summary tab. Click the disclosure arrow next to your application's name and you can drag out the Application Data from there into a directory to pull all of your application's working data out of the application on the device.
The store is created by the
addPersistentStoreWithType:configuration:URL:options:error:
method. Use
NSLog(#"store path: %#", storeUrl);
to see the file path of the store in the applicationDocumentsDirectory.
To download and browse the whole applicationDocumentsDirectory of your device, use the Xcode Organizer: choose your device, click on the disclosure triangle of your application and then on the arrow on the right of the application bundle.