Post

Replies

Boosts

Views

Activity

Reply to Objective C to Swift with CoreData and Cloud Documents
Here the PersistentStack implementation PersistenStack.h: @import Foundation; @import CoreData; @protocol PersistentStackDelegate<NSObject> - (void)storeWillChange; - (void)storeDidChange; - (void)storeDidImport; @end @interface PersistentStack : NSObject @property (nonatomic,strong,readwrite) NSManagedObjectContext* managedObjectContext; @property (nonatomic,strong,readwrite) NSManagedObjectContext* privateQueueContext; @property (assign, nonatomic) id<PersistentStackDelegate> delegate; - (void)saveContext; - (NSManagedObjectContext *)managedObjectContext; - (void)savePrivateContext; - (NSManagedObjectContext *)privateQueueContext; - (id)initWithStoreURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL; +(BOOL)isCloudAvaible; +(void)display_iCloudAlertIfNeeded; +(NSString*)checkForiCloudString; @end
Oct ’21
Reply to Objective C to Swift with CoreData and Cloud Documents
PersistentStack.m: #import "PersistentStack.h" import "Home.h" @interface PersistentStack () @property (nonatomic,strong) NSURL* modelURL; @property (nonatomic,strong) NSURL* storeURL; @property (strong,nonatomic) NSTimer *iCloudUpdateTimer; @property (readonly,nonatomic) NSUserDefaults *defaults; @end @implementation PersistentStack -(NSUserDefaults*)defaults{ NSUserDefaults *def = ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)?[[NSUserDefaults alloc] initWithSuiteName:@"group.myapp.com"]:[NSUserDefaults standardUserDefaults]; return def; } - (id)initWithStoreURL:(NSURL*)storeURL modelURL:(NSURL*)modelURL { self = [super init]; if (self) { self.storeURL = storeURL; self.modelURL = modelURL; [self setupManagedObjectContext]; } return self; } +(BOOL)isCloudAvaible{ NSURL *ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; BOOL risp = (ubiquityURL == nil); if(risp){ NSLog(@"ubiquityurl %@",ubiquityURL); } return risp; } +(NSString*)checkForiCloudString { if ([PersistentStack isCloudAvaible]) { return NSLocalizedString(@"iCloud is not avalaible", nil); } return NSLocalizedString(@"iCloud is avalaible", nil); } +(void)display_iCloudAlertIfNeeded{ if ([PersistentStack isCloudAvaible]){ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"iCloud Not Configured" message:@"Open iCloud Settings, and make sure you are logged in." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show]; } } - (void)setupManagedObjectContext { _managedObjectContext = nil; _privateQueueContext = nil; _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; _managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; _managedObjectContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; _privateQueueContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; _privateQueueContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; __weak NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator; NSError* error; NSMutableDictionary *option = [NSMutableDictionary dictionaryWithDictionary:@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}]; if([self.defaults boolForKey:AGGIORNAMENTO_2015]){ [NSThread sleepForTimeInterval:0.2]; [option addEntriesFromDictionary:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" }]; } [self.managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:option error:&error]; if(![self.defaults boolForKey:AGGIORNAMENTO_2015]){ NSArray *messe = [Messa getMesseIn:self.managedObjectContext]; NSLog(@"Messe:%@",messe); if(messe.count>0){ [AppDelegate saveContext]; [NSThread sleepForTimeInterval:0.5]; NSArray *messepostSave = [Messa getMesseIn:self.managedObjectContext]; NSLog(@"Messe:%@",messepostSave); } } else{ [AppDelegate saveContext]; [NSThread sleepForTimeInterval:0.5]; NSLog(@"DopoCloud"); } [self.privateQueueContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:option error:&error]; NSNotificationCenter *dc = [NSNotificationCenter defaultCenter]; [dc removeObserver:self]; [dc addObserver:self selector:@selector(storesWillChange:) name:NSPersistentStoreCoordinatorStoresWillChangeNotification object:psc]; [dc addObserver:self selector:@selector(storesDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:psc]; [dc addObserver:self selector:@selector(persistentStoreDidImportUbiquitousContentChanges:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:psc]; [dc addObserver:self selector:@selector(contextDidSaveMainQueueContext:) name:NSManagedObjectContextDidSaveNotification object:_managedObjectContext]; [dc addObserver:self selector:@selector(contextDidSavePrivateQueueContext:) name:NSManagedObjectContextDidSaveNotification object:_privateQueueContext]; [dc addObserver:self selector:@selector(setupManagedObjectContext) name:AGGIORNAMENTO2015_TERMINATO object:nil]; if (error) { NSLog(@"error: %@", error); } } - (NSManagedObjectModel*)managedObjectModel { return [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL]; } - (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification*)note { NSLog(@"%s", __PRETTY_FUNCTION__); NSLog(@"%@", note); if(!note){ [[Home sharedInstance] alert:@"iCLoud Debug" andMex:[NSString stringWithFormat:@"%@",note] icon:nil okAction:nil withCancel:YES]; return; } NSManagedObjectContext *managedObjectContext = self.managedObjectContext; [managedObjectContext performBlockAndWait:^{ [managedObjectContext mergeChangesFromContextDidSaveNotification:note]; NSDictionary *changes = note.userInfo; NSMutableSet *allChanges = [NSMutableSet new]; [allChanges unionSet:changes[NSInsertedObjectsKey]]; [allChanges unionSet:changes[NSUpdatedObjectsKey]]; [allChanges unionSet:changes[NSDeletedObjectsKey]]; for (NSManagedObjectID *objID in allChanges) { NSLog(@"inporting:%@",objID); } }]; [self createCloudTimer]; if(self.delegate){ [self.delegate storeDidImport]; } }
Oct ’21
Reply to Objective C to Swift with CoreData and Cloud Documents
#pragma mark - #pragma mark Utility method void runOnMain(void (^block)(void)) { if ([NSThread isMainThread]) { block(); } else { dispatch_sync(dispatch_get_main_queue(), block); } }; - (void)storesWillChange:(NSNotification *)note { NSManagedObjectContext *managedObjectContext = self.managedObjectContext; [managedObjectContext performBlockAndWait:^{ NSError *error = nil; if ([managedObjectContext hasChanges]) { [managedObjectContext save:&error]; } [managedObjectContext reset]; }]; if(self.delegate){ [self.delegate storeWillChange]; } [self createCloudTimer]; } - (void)storesDidChange:(NSNotification *)note { [self createCloudTimer]; if(self.delegate){ [self.delegate storeDidChange]; } } -(void)createCloudTimer{ if (self.iCloudUpdateTimer != nil){ [self.iCloudUpdateTimer invalidate]; } self.iCloudUpdateTimer = nil; self.iCloudUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(notifyOfCoreDataUpdates) userInfo:nil repeats:NO]; } -(void)notifyOfCoreDataUpdates{ //aggiorno notifiche lette runOnMain(^{ [[NSNotificationCenter defaultCenter] postNotificationName:AGGIORNAMENTO_ICLOUD_NOTIFICA object:nil]; }); } #pragma mark - #pragma mark CORE-DATA SAVE - (void)saveContext{ runOnMain(^{ [self MainsaveContext]; }); } - (void)MainsaveContext { NSError *error = nil; NSManagedObjectContext *managedObjectContext = self.managedObjectContext; if (managedObjectContext != nil) { if (![managedObjectContext save:&error]) { NSLog(@"PersistenStack: Errore saving:%@",[NSString stringWithFormat:@"%@, %@\n%@", error, [error localizedDescription],[error userInfo]]); [[[UIAlertView alloc] initWithTitle:@"Errore saving" message:[NSString stringWithFormat:@"%@, %@\n%@", error, [error localizedDescription],[error userInfo]] delegate:nil cancelButtonTitle:@"abort" otherButtonTitles:nil] show]; } } } - (void)savePrivateContext{ runOnMain(^{ [self MainsavePrivateContext]; }); } - (void)MainsavePrivateContext { NSError *error = nil; @synchronized(self) { NSManagedObjectContext *managedObjectContext = self.privateQueueContext; if (managedObjectContext != nil) { if (![managedObjectContext save:&error]) { NSLog(@"AppdelegatePrivate: Errore saving:%@",[NSString stringWithFormat:@"%@, %@\n%@", error, [error localizedDescription],[error userInfo]]); abort(); } } } } #pragma mark CORE-DATA NOTIFACTION - (void)contextDidSavePrivateQueueContext:(NSNotification *)notification { @synchronized(self) { if([self.privateQueueContext hasChanges]){ [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; } } } - (void)contextDidSaveMainQueueContext:(NSNotification *)notification { if([self.managedObjectContext hasChanges]){ [self.privateQueueContext performBlock:^{ [self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification]; }]; } } @end
Oct ’21
Reply to Objective C to Swift with CoreData and Cloud Documents
@OOPER I've simplified the objective-c code when porting to swift to remove legacy work and testing pieces. So PersistentStack.swift now appear like this: class PersistentStack { var modelURL: URL var storeURL: URL var managedObjectContext: NSManagedObjectContext init(storeURL: URL, modelURL: URL) { self.storeURL = storeURL self.modelURL = modelURL var managedObjectModel: NSManagedObjectModel { return NSManagedObjectModel(contentsOf: modelURL)! } self.managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy self.managedObjectContext.persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel) weak var psc = self.managedObjectContext.persistentStoreCoordinator let option = [ NSMigratePersistentStoresAutomaticallyOption: NSNumber(value: true), NSInferMappingModelAutomaticallyOption: NSNumber(value: true), NSPersistentStoreUbiquitousContentNameKey: "iCloudStore" ] as [String: Any] do { try self.managedObjectContext.persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: option) self.saveContext() Thread.sleep(forTimeInterval: 0.5) print("DopoCloud") let dc = NotificationCenter.default dc.removeObserver(self) dc.addObserver(self, selector: #selector(self.storesWillChange), name: .NSPersistentStoreCoordinatorStoresWillChange, object: psc) dc.addObserver(self, selector: #selector(self.persistentStoreDidImportUbiquitousContentChanges), name: .NSPersistentStoreDidImportUbiquitousContentChanges, object: psc) } catch { print("error: \(error)") } } @objc func persistentStoreDidImportUbiquitousContentChanges(_ note: Notification?) { print("\(#function)") if let note = note { print("\(note)") } self.managedObjectContext.performAndWait { self.managedObjectContext.mergeChanges(fromContextDidSave: note!) if let changes = note?.userInfo { for objID in changes { guard let objID = objID as? NSManagedObjectID else { continue } print("importing:\(objID)") } } } } @objc func storesWillChange(_ note: Notification?) { self.managedObjectContext.performAndWait { if self.managedObjectContext.hasChanges { do { try self.managedObjectContext.save() } catch {} } self.managedObjectContext.reset() } } func saveContext() { do { try self.managedObjectContext.save() } catch { print("PersistenStack: Errore saving:\("\(error), \(error.localizedDescription)\n\((error as NSError).userInfo)")") } } } and this is the modified Home.swift struct Home: View { private let persistentStack: PersistentStack private var notes: [Nota]? init() { let storeUrl = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("iBreviary.sqlite") let modelURL = Bundle.main.url(forResource: "iBreviary", withExtension: "momd") self.persistentStack = PersistentStack(storeURL: storeUrl!, modelURL: modelURL!) let fetchRequest = NSFetchRequest<Nota>() fetchRequest.returnsObjectsAsFaults = false let entity = NSEntityDescription.entity(forEntityName: "Nota", in: self.persistentStack.managedObjectContext) fetchRequest.entity = entity let sortDescriptor1 = NSSortDescriptor(key: "timestamp", ascending: false) let sortDescriptors = [sortDescriptor1] fetchRequest.sortDescriptors = sortDescriptors do { self.notes = try self.persistentStack.managedObjectContext.fetch(fetchRequest) print(self.notes?.count) } catch { fatalError("Failed to fetch notes: \(error)") } } var body: some View { Text("Hello") } } But count keep returning 0. Any Idea?
Oct ’21
Reply to MPMediaItemPropertyArtwork crashes on Swift 6
Hello Quinn! setMetadata(...) is set inside the @MainActor class AudioPlayerProvider: ObservableObject along AVPlayer and some @Published properties. The function itself can be called inside the action of a SwiftUI button with: Task { try? await self.audioPlayerProvider.setMetadata(title: ..., artist: ..., artwork: ...) } or inside a .onChange event triggered by a metadata ObservableObject class, when needed. So always on the thread the enclosing view runs. Thanks again
Sep ’24