Shared Core Data - What am I missing? - ios

I have an app with a Today extension. Using App Groups, I am able to have a single repository for both the app and the extension. However, I must be missing something as the solution only partially works. If I am in the App I can add a record and will see that same record in the widget. However, if a change the value of a column, for example, setting a boolean from true to false. The app won't see the change if it were made in the extension and vice versa. I am saving the change to Core Data:
_record?.managedObjectContext?.save()
Using DB Browser, I am able to verify that the change was made; is in the DB. Clearly, I am missing something. Any ideas would be appreciated.

Make sure you're using the same db in both sides
- (void)viewDidLoad {
[super viewDidLoad];
if ([self.extensionContext respondsToSelector:#selector(setWidgetLargestAvailableDisplayMode:)]) { // iOS 10+
[self.extensionContext setWidgetLargestAvailableDisplayMode:NCWidgetDisplayModeExpanded];
} else {
self.preferredContentSize = CGSizeMake(0, 110.0); // iOS 10-
}
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreAtURL:[MagicalRecord urlAppGroupStore]];
}
As you can see i'm using magical record but I'm specifying to use the share sqlite file
NSString *const kAppGroupIdentifier = #"group.com.carlosduclos.myapp";
+ (NSURL *)urlAppGroupStore {
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:kAppGroupIdentifier];
return [groupURL URLByAppendingPathComponent:#"mydb.sqlite"];
}

Related

iMessageExt app Error starting application

I created my iMessage extension, when I try to open it, the first screen appears but it is totally frozen, and it does not react in any way.
I've put logs in the viewDidLoad of that first view and nothing appears there, after a few seconds I can already see those logs.
To make the application freezing lose that status, user has to slide screen left or right and back again.
I've tried looking all over the web for someone who happens to be the same, but I could not find anything.
It does not come to mind more screenshots or portions of code add, if you think I should provide some additional information, just let me know
Any help would be appreciated.
Thank you.
UPDATE:
This is my Project Structure.
This is my viewDidLoad code.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"here viewDidLoad iMessage ext~~~!");
[self applyCornerRadiusToBtn];
[self registerPresentationAction];
NSDictionary *user = [self getUserInfoFromHostApp];
if (user) {
NSLog(#"Here != null user info");
//It is assumed that when you enter this point and run this log, the app should navigate to the next screen, but it does not.
[self performSegueWithIdentifier:#"goToYoutubeListIm" sender:nil];
} else {
NSLog(#"Here userInfo null");
}
}
- (NSDictionary *)getUserInfoFromHostApp
{
NSUserDefaults *myDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxxxx"];
NSDictionary *userNameSaved = [myDefaults objectForKey:#"userInfoExt"];;
NSLog(#"userNameSaved in xxxx Ext ==> %#",userNameSaved);
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.com.xxxx"];
NSLog(#"groupURL ==> %#",groupURL);
return userNameSaved;
}
For all concerned I have found the problem or problems to be accurate.
1) I was creating my controllers type MSMessagesAppViewController. Apparently there should only be one controller of this type.
2) I had logic in the viewDidAppear in my MSMessagesAppViewController. For some strange reason this also caused the problem, I had to get the logic out there and force the user to interact with a button to execute the logic that was in the didAppear

iOS Extension - Fatal Exception: com.firebase.core Default app has already been configured

iOS Extension - Fatal Exception: com.firebase.core Default app has already been configured.
I run the Fir.configure() in the viewDidLoad() method and some events pass and get through to Firebase.
Can someone help me figure this out.. Google is not friendly enough.
PS: Yes I created a second .plist, and a second app in Firebase Console.
PPS: Yes I selected the correct target for each GoogleServices plist
I'm seeking the solution..
I don't know if you're still looking for a solution but I had the same issue, using firebase with extension.
I ended up doing this :
if(FIRApp.defaultApp() == nil){
FIRApp.configure()
}
This will check if the app is already configured so that there is no crash.
I had the same issue and I resolved it by making changes in two places in my application (check your syntax for swift version):
In AppDelegate.swift override a following method:
override init()
{
FirebaseApp.configure()
}
In your ViewController.swift's viewDidLoad() method, write this code:
if FirebaseApp.app() == nil {
FirebaseApp.configure()
}
Use this instead for latest firebase_ml_vision: ^0.9.3+8
if(FirebaseApp.app() == nil){
FirebaseApp.configure()
}
The answer is in the exception. You're configuring the app twice. You've got a few options to fix this:
1) Configure your app once in your app delegate.
2) Match a configure with an unconfigure. There is a method on FIRApp that allows you to unconfigure it (the actual name escapes me).
I also got this issue in a today extension code too. I solved if with an extra check if your Firebase instance is already configured:
// define in your constants or somewhere
NSString* const UNIQUE_FIREBASE_INSTANCE_IDENTIFIER_WIDGET = #"Widget_FirebaseAppInstance";
if([FIRApp appNamed:UNIQUE_FIREBASE_INSTANCE_IDENTIFIER_WIDGET] == nil) // there should be only one app instance!
{
NSString *resourceName = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"FirebaseResource"];
NSString *filePath = [[NSBundle mainBundle] pathForResource:resourceName ofType:#"plist"];
FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
[FIRApp configureWithName:UNIQUE_FIREBASE_INSTANCE_IDENTIFIER_WIDGET options:options];
}
In your main app you should also use a different unique name for it. So you can have multiple instances but every instance is configured only once.

Metaio SDK - Creating a new AR Application

I am following a tutorial on the Metaio website - Creating a New AR Application, and it seems to work (I get the Metaio splash screen, and the watermark shows up on the camera view when I build and run it on an ipad.
I'm trying to get the Hello World tutorial to work, using code directly copied from the Metaio SDK, but I am not able to get the model to appear over the racking image.
The implementation file code is below - I am getting no errors when I run it on an ipad, and get the camera view etc, but no 3d model - any suggestions? Thx:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void) viewDidLoad
{
[super viewDidLoad];
// load our tracking configuration
NSString* trackingDataFile = [[NSBundle mainBundle] pathForResource:#"TrackingData_MarkerlessFast"
ofType:#"xml"
inDirectory:#"Assets"];
if(trackingDataFile)
{
bool success = m_metaioSDK->setTrackingConfiguration([trackingDataFile UTF8String]);
if( !success)
NSLog(#"No success loading the tracking configuration");
}
// load content
NSString* metaioManModel = [[NSBundle mainBundle] pathForResource:#"metaioman"
ofType:#"md2"
inDirectory:#"Assets"];
if(metaioManModel)
{
metaio::IGeometry* theLoadedModel = m_metaioSDK->createGeometry([metaioManModel UTF8String]);
if( theLoadedModel )
{
// scale it a bit up
theLoadedModel->setScale(metaio::Vector3d(1.0,1.0,1.0));
}
else
{
NSLog(#"error, could not load %#", metaioManModel);
}
}
}
#end
Did you also use the xml tracking file, that should be in the assets folder?
As I see it, it could come from several errors:
- The tracking image doesn't have the same name in the xml file and in your folders
- the tracking file is empty or contains errors
Maybe you could share the xml tracking file as well so we could help you more.
Good luck

UIDocument open/close behavior

I have a UIDocument based app, without iCloud support. The user is able to create documents, and save them to app's Document directory.
I have also created few "sample" documents, and passing them with the app's bundle. I want the user to be able to open sample documents the same way as they can open their own documents:
NSArray *samplesContent = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"doco" subdirectory:#"Samples"];
for (NSURL *sampleURL in samplesContent) {
Doco *doco = [[Doco alloc] initWithFileURL:sampleURL];
[doco disableEditing];
[doco openWithCompletionHandler:^(BOOL success) {
if (success) {
[self.docos addObject:doco];
if (self.docos.count >= samplesContent.count) {
[self.tableView reloadData];
}
} else DLog(#"Failed to open %#", [sampleURL pathExtension]);
}];
}
What I am seeing is this:
On viewDidLoad, docs array gets populated with sample docs and displayed in the tableView the first time app launches. No issues here, all is smooth and nice.
Then I back out of the view with the following code to close all open docs:
int count = 0;
for (Doco *doco in self.docos) {
if (doco.documentState == UIDocumentStateNormal) {
[doco closeWithCompletionHandler:nil];
count++;
}
}
DLog(#"Closed %i docs", count);
When I open the view again, the array of docs should get populated again and tableView re-populated, but nothing happens.
The completion handler below never gets called, although the URL is pointing to the same file and it is valid:
[doco openWithCompletionHandler:^(BOOL success) {}
I do not have this issue for user generated docs stored in Documents, so my assumption is that it has something to do with auto-save, that gets called on read-only bundle and fails
But I am sort of stuck on this part, any help will be appreciated.
The problem has already been identified, but I think it's worth describing a couple of simple solutions since including sample documents in an app's bundle is not uncommon.
So the problem is that the sample document is trying to save changes when it is closed, but saving cannot succeed in a read-only app bundle.
I think there are two main solutions here:
Copy the sample document into the Documents directory, where it can be treated like any other document and saved successfully (if you want user edits to the sample document to be saved, use this approach).
Prevent the document from trying to save (for read-only sample documents).
So here are some simple examples...
1. Copy sample documents into Documents directory
On first launch (or indeed whenever you decide to 'refresh' the sample document), use NSFileManager to copy the file into place:
- (void)refreshSampleDocuments
{
NSArray *sampleFromURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"doc" subdirectory:#"Samples"];
for (NSURL *sampleFromURL in sampleFromURLs) {
NSString *sampleFilename = [sampleFromURL lastPathComponent];
NSURL *sampleToURL = [[self documentsDirectoryURL] URLByAppendingPathComponent:sampleFilename];
// ...
// Do some checks to make sure you won't write over any user documents!
// ....
NSError *error;
BOOL copySuccessful = [[NSFileManager defaultManager] copyItemAtURL:sampleFromURL toURL:sampleToURL error:&error];
if (!copySuccessful) {
// Handle error...
}
}
}
2. Prevent sample documents from trying to save
This approach is much simpler (for read-only documents), and easier than trying to prevent updates wherever they might occur in the document.
When closeWithCompletionHandler: is called on UIDocument, autosaveWithCompletionHandler: is invoked to ensure the document file is saved before closing. This in turn invokes hasUnsavedChanges to decide whether a save is necessary. So if hasUnsavedChanges returns NO, then any invocation of the autosaving mechanism will result in no changes being written out.
(N.B. manually calling saveToURL:forSaveOperation:completionHandler: will still force a save, regardless of what hasUnsavedChanges returns.)
So in your UIDocument subclass, override hasUnsavedChanges to return NO if the document is read-only.
#interface MyDocument : UIDocument
#property(nonatomic, getter = isReadOnly) BOOL readOnly;
#end
#implementation MyDocument
- (BOOL)hasUnsavedChanges
{
return [self isReadOnly] ? NO : [super hasUnsavedChanges];
}
#end
If UIDocument is updated it will try to save changes on close.
Since UIDocument was loaded from read-only bundle, I had to make sure that it does not get updated, otherwise close block returns success=NO, and document is not closed...

iCloud - renaming open documents on another device sometimes fails

The issue: I'm working on an iCloud document on device A, e.g. iPod Touch. Then I change the name of the document on device B, e.g. my Mac (via the Finder). The change goes up to the cloud and after a pause device A gets to hear about it.
And then:
some of the time all is just fine - I pick up the change of name via a changed fileURL property and can update my interface accordingly - the document continues to behave just as it should
some of the time, the document's fileURL is returned as something such as: file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95 Not surprisingly this file won't save.
Can anyone explain what is going on and how to work around it?
Background
The name change is picked up fine by by NSMetadataQuery. So, for e.g., I can rename documents that are not open and all my iCloud functionality works fine. The issue only seems to occur with open documents.
Other iCloud features are working fine, e.g. I can change content on one device, e.g. my Mac, and detect and then update my interface on another device, e.g. my iPod Touch, that has the relevant iCloud document open.
I first spotted this when I added an override for presentedItemDidMoveToURL: to my UIDocument subclass. The override reliably picks up name changes made in the cloud, e.g. renaming the document on another device. Then sometimes newURL is the final expected URL for the renamed document, i.e. something sensible from which I can extract the new name use `lastPathComponent', update my interface etc. On other occasions newURL is a document in some other directory with a last path component beginning 'purg-', e.g. purg-012fdcfbe3b3bbce6e603fdfd2f000b2cb28649e95.
- (void) presentedItemDidMoveToURL:(NSURL *) newURL;
{
[super presentedItemDidMoveToURL: newURL];
if ([(id)[self delegate] respondsToSelector:#selector(documentNameChanged:)])
{
[[self delegate] documentNameChanged: self];
}
}
The presentedItemDidMoveToURL: method does not seem to be the root cause of the problem. For example, if I don't override that method at all, but periodically check in the viewController that is looking after the open document, then sometimes after a rename fileURL will return the new name and sometimes it will return `purg-.....'. So the issue appears to be to do with how renaming is handled.
Update
As al_lea pointed out, the issue here was related to accommodatePresentedItemDeletionWithCompletionHandler:. Expanding on al_lea's answer, I added the code below to my UIDocument subclass. This fixed the issue.
- (void) accommodatePresentedItemDeletionWithCompletionHandler: (void (^) (NSError *errorOrNil)) completionHandler
{
PresentedDocument* presentedDocument = [self retain];
[presentedDocument closeWithCompletionHandler: ^(BOOL success) {
NSError* error = nil;
if (!success)
{
NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
#"Could not close document that is being deleted on another device",
NSLocalizedDescriptionKey, nil];
error = [NSError errorWithDomain: #"some_suitable_domain"
code: 101
userInfo: userInfo];
}
completionHandler(error); // run the passed in completion handler (required)
dispatch_async(dispatch_get_main_queue(), ^
{
[[NSNotificationCenter defaultCenter] postNotificationName: NOTIFY_presentedDocumentDeletedOnAnotherDevice
object: presentedDocument
userInfo: nil];
[presentedDocument tidyUpAfterDelete]; // app specific tidy up
[presentedDocument release];
});
}];
}
With this code in place, there are no spurious and confusing presentedItemDidMoveToURL: calls made and, in addition, the relevant object can listen for notifications of deletions on other devices.
This type of URL appears when a UIDocument is opened on local and get deleted from a remote device:
file://localhost/var/mobile/Library/Mobile%20Documents/.ubd/peer-43A0AEB6-84CE-283E-CA39-FCC4EF3BC8F8-v23/ftr/purg-
You need to close the document first before it get deleted - detect this in NSFilePresenter's accommodatePresentedItemDeletionWithCompletionHandler:

Resources