Giter VIP home page Giter VIP logo

contentful-persistence.swift's Introduction

contentful-persistence.swift

Version Carthage compatible License Platform Build Status Coverage Status

An integration to simplify persisting data from Contentful to a local CoreData database; built on top of the official Contentful Swift Library. This library specifically uses the /sync endpoint of the Content Delivery API to synchronize all content in a Contentful space to device.

What is Contentful?

Contentful provides a content infrastructure for digital teams to power content in websites, apps, and devices. Unlike a CMS, Contentful was built to integrate with the modern software stack. It offers a central hub for structured content, powerful management and delivery APIs, and a customizable web app that enable developers and content creators to ship digital products faster.

Getting started

Prerequisite

Before getting started, it is highly recommended that you familiarize yourself with Apple's CoreData framework as many issues encountered during development may be CoreData specific. Read the CoreData Programming Guide and check out other (non-Contentful) examples.

Usage

The SynchronizationManager manages the state of your CoreData database and keeps it in sync with the data from your Contentful Space:

// Tell the library which of your `NSManagedObject` subclasses that conform to `EntryPersistable` should be used when mapping API resonses to CoreData entities.
let entryTypes = [Author.self, Category.self, Post.self]

// Initialize the data store and it's schema.
let store = CoreDataStore(context: self.managedObjectContext)
let persistenceModel = PersistenceModel(spaceType: SyncInfo.self, assetType: Asset.self, entryTypes: entryTypes)

// Initialize the Contentful.Client with a persistenceIntegration which will receive messages about changes when calling `sync methods`
self.client = Client(spaceId: "<YOUR_SPACE_ID>", accessToken: "<YOUR_ACCESS_TOKEN>")

// Create the manager.
self.syncManager = SynchronizationManager(client: self.client,
                                          localizationScheme: LocalizationScheme.all, // Save data for all locales your space supports.
                                          persistenceStore: self.store, 
                                          persistenceModel: persistenceModel)

// Sync with the API. 
self.syncManager.sync { _ in
  do {
    // Fetch all `Posts` from CoreData
    let post: Post? = try self.store.fetchAll(type: Post.self, predicate: NSPredicate(value: true))
  } catch {
    // Handle error thrown by CoreData fetches.
  }
}

Define your CoreData model

To make your model classes work with contentful-persistence.swift you will need to either conform to AssetPersistable for Contentful Assets, or EntryPersistable for Contentful entry types.

Then you will need to make the corresponding model in your projects xcdatamodel file. Both EntryPersistable and AssetPersistable types must have a non-optional id property as well as optional localeCode, createdAt, and updatedAt properties.

NOTE: Optionality on CoreData entities is a bit different than Swift optionality. Optionality on CoreData entities means that the property may be absent when a save-to-database operation is performed. To configure a property's optionality, open the "Data Model Inspector" in Xcode's "Utilities" right sidebar and toggle the "Optional" checkbox:

The mapping of Contentful fields to your data model entities will be derived automatically, but you can also customize it, by implementing the static func mapping() -> [FieldName: String]? on your class.

Below is an example of a model class.

import Foundation
import CoreData
import ContentfulPersistence
import Contentful

// The following @objc attribute is only necessary if your xcdatamodel Default configuration doesn't have your module
// name prepended to the Swift class. To enable removing the @objc attribute, change the Class for your entity to `ModuleName.Post`
@objc(Post) 
class Post: NSManagedObject, EntryPersistable {
      
    // The identifier of the corresponding Content Type in Contentful.
    static let contentTypeId = "post"

    // Properties of the `sys` object of Contentful resources.
    @NSManaged var id: String
    @NSManaged var localeCode: String?
    @NSManaged var createdAt: Date? 
    @NSManaged var updatedAt: Date?

    // Custom fields on the content type.
    @NSManaged var body: String?
    @NSManaged var comments: NSNumber?
    // NOTE: Unlike date fields in sys properties, this library can't store `Date` for custom fields.
    // Use `String` and map to date after fetching from CoreData
    @NSManaged var customDateField: String? 
    @NSManaged var date: Date?
    @NSManaged var slug: String?
    @NSManaged var tags: Data?
    @NSManaged var title: String?
    @NSManaged var authors: NSOrderedSet?
    @NSManaged var category: NSOrderedSet?
    @NSManaged var theFeaturedImage: Asset?

    // Define the mapping from the fields on your Contentful.Entry to your model class. 
    // In the below example, only the `title`, `date` and `author` fields and `featuredImage` link will be populated.
    static func fieldMapping() -> [FieldName: String] {
        return [
            "title": "title",
            "featuredImage": "theFeaturedImage",
            "author": "authors"
            "date": "date"
        ]    
    }
}

HINT: For array-based field types (like Short text, list), use the type Binary Data in the data model, and the type Data? (e.g. var tags: Data?) in the Swift code. To access the actual array contents, unpack the Data field with NSKeyedUnarchiver, e.g.:

extension Post {

    var theTags: [String]? {
        guard let tagsData = self.tags else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: tagsData) as? [String]
    }
}

Installation

CocoaPods installation

CocoaPods is the dependency manager for Objective-C and Swift, which automates and simplifies the process of using 3rd-party libraries like the ContentfulPersistence in your projects.

platform :ios, '9.3'
use_frameworks!

target :MyApp do
  pod 'ContentfulPersistenceSwift', '~> 0.13.0'
end

Carthage installation

You can also use Carthage for integration by adding the following to your Cartfile:

github "contentful/contentful.swift" ~> 0.13.0

Documentation

For further information, check out the Developer Documentation or browse the API documentation. The latter can also be loaded into Xcode as a Docset.

Contributing and development

To get started contributing, clone the project, cd into the root directory and run the following: make setup_env.

make setup_env
carthage bootstrap --platform all

This command will install all the development dependencies necessary to build the project, and execute the tests. To run the tests from the command line, execute make test. Tests should also all run directly from the Xcode app.

License

Copyright (c) 2018 Contentful GmbH. See LICENSE for further details.

contentful-persistence.swift's People

Contributors

cf-allstar[bot] avatar dependabot[bot] avatar jefnazario avatar khaledgarbaya avatar loudmouth avatar makinwab avatar manmal avatar marcin-bo avatar marcolink avatar mariuskatcontentful avatar matelo avatar mgratzer avatar neonichu avatar oryoffe avatar sajuthomaspattarmatam avatar t-col avatar tapwork avatar tomkowz avatar whitelisab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contentful-persistence.swift's Issues

Management of properties and relationships

It seems that the assumptions made around the processing of properties and relationships is problematic when the local data store includes fields which aren't in the remote model. (hopefully I'm missing something, but there's nothing I can see in the docs)

This is initially because relationships are calculated to be anything that isn't found to be a property, so to prevent invalid relationship handling you're lead to add dummy mappings to fieldMapping() for anything which is local but not remote (including transients). This however is later a problem because the field mapping from remote to local just processes everything defined in fieldMapping() and thus sets any local-only fields to nil.

At minimum the field mapping should check that the field name exists in the data coming from the server and ignore any core data content which doesn't exist in the download - but this is how empty field deletion is managed so that's actually hard...

Example scenarios are things like:

  1. A remote value needs to be converted before being stored into the model (this could be worked around by using a transient and converting on 'get' but this could be difficult for historic reasons and efficiency depending on the conversion required)
  2. The server contains general resources and a local record needs to be kept of what's been seen or something like that
  3. You want to convert the supplied strings to date objects once

Related to this, that concept of mapping is a big thing. The fieldMapping() could include an optional closure to run as a way to simply add support for it...

Updates and releases needed

The latest release of contentful-persistence is 0.3.0 from 4 month ago and it lists 'Contentful', '~> 0.3.1' as dependency (also 4 month old). Since then Contentful has been released multiple times, currently at version 0.6. The current master references Contentful 0.4.1 (only three weeks old) which unfortunately has some bugs.

The awesome advancements in one repository are pretty useless if other project dependencies are tied to old releases :-(

Do you have a timeline or roadmap when we can expect a synced set of up-to-date releases?

Missing relationships between entries

Hi,

We experience issues with missing relationships between entries.

Our sync request has many pages and it takes around one minute to download and save all entries in our database. If user quits the app in the middle of synchronization we loose some relationships between entries. They are not recreated even after restarting the application and completing the data synchronization process.

When I do not interrupt the data synchronization process and wait one minute to sync all data, the relationships appear in the database.

Probably the problem is with resolveRelationships() function: it stores those missing relationships in relationshipsToResolve property in memory and after quiting the app we loose the content of it. Is it possible?

I reported similar issue few months ago #47 (when seeding database).

Cheers!

Update podspec

Is it possible to update spec.dependency 'Contentful', '~> 4.1.3' to 5.0.2, as in Cartfile?

Sync not removing invalid relationships if a full sync is performed

Similar to the issue #122 when performing a full sync to work around the issue described in #94 relationships that should be removed aren't. The issue is that if there is object A with references to objects B, C, and D if the reference to object C is removed and replaced with a reference to object E then when a full sync is performed A will have references to B, C, D, and E. This issue does not occur when performing partial syncs.

As described in #122 the view context has it's merge policy set to overwrite like so
persistentContainer.viewContext.mergePolicy = NSMergePolicy.overwrite

The method we are using to perform a full sync is to delete all the CoreData stores then call sync. We clear the CoreData stores before passing them to the SynchronizationManager like this

// delete any existing stores to remove existing data
let coordinator = persistentContainer.persistentStoreCoordinator
for persistentStore in persistentContainer.persistentStoreDescriptions {
    guard let url = persistentStore.url else {
        continue
     }
     do {
         try coordinator.destroyPersistentStore(at: url, ofType: persistentStore.type, options: nil)1
    } catch {
        Logger.service.log("Failed to delete CoreData store: \(persistentStore.debugDescription)")
    }
 }

We then create a PersistenceContainer and use it to initialise the SynchronizationManager like this

persistentContainer.viewContext.mergePolicy = NSMergePolicy.overwrite

let context = persistentContainer.newBackgroundContext()
let coreDataStore = CoreDataStore(context: context)
let synchronizationManager = SynchronizationManager(
    client: client,
    localizationScheme: .default,
    persistenceStore: coreDataStore,
    persistenceModel: persistenceModel
)

We then call sync on this SynchronizationManager and have the issue where deleted relationships are persisted.

[BUG] SynchronizationManager.seedDBFromJSONFiles throwing incorrect invalidFilePath

persistence-sdk information

  • version: 0.16.1

Describe the bug

SynchronizationManager.seedDBFromJSONFiles throws incorrect invalidFilePath while providing correct folder name and bundle.

example:
try syncManager.seedDBFromJSONFiles(in: "ContentfulSeed", in: Bundle.main) (ContentfulSeed is a correct folder reference and added to the bundle)

results in:
DatabaseSeedingError.invalidFilePath

Debug logs

While debugging I can tell the filePaths are correct, however the localesJSONFilePath and firstFilePath are empty, causing the above error.

Example simulator log:
"filesPaths:" [ "/Users/bas/Library/Developer/CoreSimulator/Devices/<redacted>/data/Containers/Bundle/Application/<redacted>/<redacted>.app/ContentfulSeed/locales.json", "/Users/bas/Library/Developer/CoreSimulator/Devices/<redacted>/data/Containers/Bundle/Application/<redacted>/<redacted>.app/ContentfulSeed/10.json", ... "/Users/bas/Library/Developer/CoreSimulator/Devices/<redacted>/data/Containers/Bundle/Application/<redacted>/<redacted>.app/ContentfulSeed/23.json" ] "localesJSONFilePath:" nil "firstFilePath:" nil

Example device log:
"filesPaths:" [ "/private/var/containers/Bundle/Application/<redacted>/<redacted>.app/ContentfulSeed/19.json" ] "localesJSONFilePath:" nil "firstFilePath:" nil

Possible fix

When changing inside: file
The occurrences of:
URL(string: $0)?
with
URL(fileURLWithPath: $0)

The synchronisation succeeds.

[Documentation] Missing reference to contentful-utilities

Situation

Dealing with large data sets that need to be synchronised before loading the rest of the app.
Caused me to look into possibilities to ship my app with a seeded JSON.

I quickly found seedDBFromJSONFiles

But it was really difficult to find how to create a seed from a space.

Using google and searching the website you get directed to:
https://github.com/contentful/contentful-cli

However you specifically need:
https://github.com/contentful/contentful-utilities.swift

Which I could only find because I found:
https://github.com/contentful/contentful-persistence.swift/blob/master/Tests/ContentfulPersistenceTests/PreseedingTests.swift#L17

Suggestion

Update documentation, readMe and/or website tutorial, to make people aware of contentful-utilities

Sync, Replacing Content

I am using Swift 3 with contentful-persistance and am having an issue with updating content, so for example if i add new content it replaces the existing content. I have noticed that deleting the content from core data and then calling self.sync.sync works fine.

Any idea when the Contentful PersistanceTests will be updated?

it("can continue syncing from an existing data store") {
     // TODO: implement test
} 

Thank you for your help.

Sync not removing invalid relationships?

This is the problem I'm having, and I think it's on the Contentful sync side…

The problem is this:

  1. Content synced where model A has relationship to model B
  2. Later, content is updated, removing the relationship between A & B. Both A & B content still exist though, just the relationship is removed
  3. Next sync, the relationship still exists in the synced data. I can't see anything in the code that would remove this relationship?

Use of unresolved identifier 'SyncInfo'

I don't understand what sync info should be in your documentation? does it represent a Post? And what is the managedObjectContext variable in your example readme.md? Do you have an example app i can reference?

Thanks :)

[BUG] Incremental sync issues with 0.17.1

Hi,

After updating to the 0.17.1 SDK, I noticed that incremental syncing seems to have broken. What happens is the following:

  • I do a clean sync from scratch, everything is all good.
  • I update some content in our Contentful space, like for example lets say we have a 'Person' object and there is a name on it, I change the name from 'Paul' to 'Jacob'
  • I restart the app to perform the incremental sync to make sure the CoreData database is up to date again, now there are suddenly two person objects, both the old one and the new one, respectively 'Paul' and 'Jacob', where I would expect there to only be 'Jacob'.

This obviously causes a variety of issues. I did some more research and found out the last version where incremental syncs still seemed to work is 0.16.1. When I do some logging, I can see there are no 'create' calls occurring during this incremental sync, only fetches (and saves). When I log with 0.17.1 I suddenly see a batch of 'create' calls occurring for the 'Person' objects (presumably the updated version with the new 'Jacob' name), but no 'delete' calls, indicating that indeed, new entities are created for the updated entries, but the old outdated entries are never deleted, thus ending up with an 'entity leak'.

Cannot convert return expression of type

I updated to
Contentful 0.10.2
ContentfulPersistenceSwift 0.7.0

But when compiling I get the error in SynchronizationManager.swift

Cannot convert return expression of type '[(key: FieldName, value: String)]' (aka 'Array<(key: String, value: String)>') to return type '[FieldName : String]' (aka 'Dictionary<String, String>')

also deleted the entire Pods folder and cleaned the target, but issue remains

To One relationship with mapped relationship name results in crash while trying to sync

Steps to reproduce:

  1. Define a content model SomeModel in Contentful with a to-one relationship to another model SomeOtherModel. Let's call this relationship in Contentful toOneRelationship
  2. Define the core data model with the to-one relationship, but in the core data model, call the relationship justOne
  3. Define the core data NSManagedObject class as EntryPersistable, with the following field mapping:
class SomeOtherModel: NSManagedObject, EntryPersistable {}
class SomeModel: NSManagedObject, EntryPersistable {
    // this is called "toOneRelationship" in the Contentful model
    @NSManaged var justOne: SomeOtherModel?

    static func fieldMapping() -> [FieldName: String] {
        [
            "toOneRelationship": "justOne"
        ]
    }
}

During the sync operation, ContentfulPersistence will attempt to set the relationship on this managed object using the toOneRelationship name, rather than the justOne field name, resulting in a crash.

Only workaround seems to be to rename the relationship in the Contentful model definition.

Resolve all relationships after seeding data from all JSON files

Hello,

I found an issue in the library in resolving relationships between entities. I'm using contentful-utilities to generate JSON files with data.

The output of contentful-utilities is:

0.json
1.json
2.json

I seed those files at first launch of the app. I have two entities in one-to-many relationship.
Parent entity is defined in 0.json file.
One of child entities is defined in 1.json. And after seeding database there is no conection between them.

The problem is that the library resolves relationships after seeding each file. That's why there is no relationship between entites from different JSON files. It should be done after data from all files is seeded and only once. See my quick fix:

// 
// file: SynchronizationManager.swift
// 

public func update(with syncSpace: SyncSpace) {
      // ...

      self?.update(syncToken: syncSpace.syncToken)
      // self?.resolveRelationships() -> remove this line
      self?.save()

      // ...
}

// define new function that handles resolving relationships
public func lateResolveRelationships() {
      persistentStore.performAndWait { [weak self] in
            self?.resolveRelationships()
            self?.save()
      }
}
//
// file: SynchronizationManager+SeedDB.swift
//

// ...
public func seedDBFromJSONFiles(in directory: String, in bundle: Bundle) throws {
      // ...
      self.lateResolveRelationships() // in last line call new function after data from all JSONs is seeded
}

Usin native @NSManaged Dates for fields are not supported (sys dates work though)

While of course sys.updatedAt and sys.createdAt can successfully be stored on custom NSManagedObject classes for content types, if a date is the type of a field on a content type, this library has no way of storing it as a native @NSManaged var dateField: Date?

While this can be worked around using a String instead of a Date as the type, it is preferable to implement this feature on the library itself.

Carthage Build Fails / Fix Included

I have the following pull request to fix the Carthage build. It appears that the CocoaPod Dependencies are missing. I updated the .gitignore file to include the /Pods directory to check in the the depend pods for the framework.

#14

Please ensure to update your documentation, and include the Carthage badge so that user's are aware of the support. This actually sent me for a loop, as I was attempting create a standalone library to share between the iOS / tvOS without realizing that version 0.3.0 had full intended to build with Carthage.

Seeding multilanguage database does not work properly

contentful-persistence.swift version number: 0.7.0
Xcode version number: 9.0.1 (9A1004)

Hello,

I try to seed database with data from contentful-utilities.swift. I have entites that are in multiple languages (I use LocalizationScheme.all). And it fails to save entities in database. When I open sqlite file it does not contain any of my custom entries. But it does contain SyncInfo entity with token.

Here's my seed code:

let persistenceModel = PersistenceModel(spaceType: CFSyncInfo.self, assetType: CFAsset.self, entryTypes: entryTypes)
client = Client(spaceId: spaceId, accessToken: accessToken)
syncManager = SynchronizationManager(client: client,
                                     localizationScheme: LocalizationScheme.all,
                                     persistenceStore: store,
                                     persistenceModel: persistenceModel)

do {
    try syncManager.seedDBFromJSONFiles(in: bundleDirectoryName, in: bundle)
} catch {
    print("Error: \(error)")
}

The problem is that when seeding client does not contain localeCodes and that's why for LocalizationScheme.all no entities are created. To make it work it is required to set localeCodes before seeding database:

// SynchronizationManager+SeedDB.swift
public func seedDBFromJSONFiles(in directory: String, in bundle: Bundle) throws {
// ...
Client.update(jsonDecoder, withLocalizationContextFrom: space)

// update localeCodes here
let localeCodes = space.locales.map { $0.code }
self.update(localeCodes: localeCodes)

When I use sync() from SynchronizationManager database is populated properly. It's because SynchronizationManager has proper localeCodes set before saving to database.

One-to-many references not updated

Hey,

We're having several major issues with syncing

  1. Model A has linked multiple reference type sub-model B. We've recently added more content defined by model B and attached it to existing data held by A entry. Although changes are logged and visible inside Contentful panel, the client side seems to ignore it, even though updates were made more than a month ago.

I've tried to initiate sync on both: empty and already existing databases.

  1. Same data structure. I've added additional locale (no new data, just locale), filled all the missing pieces on existing entries and it seems that Assets (images) are not synced properly for newly added language, it doesn't affect other properties.

Note: asset is not localized and is used for all locales. This issue only exists when trying to sync on non-empty Database.

Use contentful 5.0.0

I cannot use this with the newest contentful 5.0.0. Can you please update this?

Localised assets do not contain URL when they fallback to default value

  • contentful-persistence version number: 0.12.0
  • Xcode version number: 9.4.1
  • Target operating system(s) and version number(s)
    • iOS: iOS 10
    • tvOS:
    • watchOS:
    • macOS:
  • Package manager:
    • Carthage
    • Cocoapods

When syncing assets, URL for localized assets do not fall-back to default localization, it's showed as nil.

All assets can be localized but it's a very rare case that you need different images for different languages. So I would expect that it's enough to have one version of the image and when the asset is synced default URL is saved for all locales. This is not a case now. You need to add images for all languages if you want to have a URL for different locales. If you don't add different versions, the asset is created but URL is nil.

Please let me know if this is a bug or expected behavior.

Xcode is crashing when NOT assigning a value to localeCode

Hi,

I just had a weird issue after updating to the latest contentful SDKs:
I have a custom model where I forgot to set the localeCode (regarding to your Docs it should not be empty.)
Creating this model (without assign a string value to localeCode) caused Xcode to crash.
After digging into the console.app I found out that something is wrong with that model and the property localeCode.
Setting the property fixed the issue.
Just to let you know. It was tough to find it.

Add methods for fetching asset data

While methods exist on the main SDK for fetching binary data for an asset, these methods only take Asset instances and therefore AssetPersistable don't have an easy way of retrieving the binary data. either the main SDK or this library should provide a way of fetching data for AssetPersistable instances.

Seeding DB from JSON files - add completion handler

Hi,

It could be useful to call some code just after your DB was seeded with data form JSON files. Then seeding function would be like this:

// SynchronizationManager+SeedDB.swift

public func seedDBFromJSONFiles(in directory: String, 
                                in bundle: Bundle, 
                                completion: @escaping(() -> ()))

What do you think?

Memory leak on method fetchAll<T>

Hi,
I have seen on Instruments console a memory leak when method fetchAll<T> at the class CoreDataStore.swift is called. Unfortunately, I still don't know the exact cause, but I have found some people facing the same leak issue.

The code snippet where the memory leak occurs can be seen below:

    public func fetchAll<T>(type: Any.Type, predicate: NSPredicate) throws -> [T] {
        let request = try fetchRequest(for: type, predicate: predicate)
        return try context.fetch(request).flatMap { $0 as? T }   <--- memory leak here
    }

For some reason when we call NSManagedObjectContext.fetch().flatMap() all the same time, a huge bunch of memory is consumed by it, check this out:
screen shot 2018-03-22 at 17 40 55

Well, the simple and easy solution for that it's separates the fetch() call from the flatMap()call. The difference of memory allocation it's really considerable. See image below:
screen shot 2018-03-23 at 15 30 27

That's it. I'm sending a PR to solve this issue.
Thanks for reading.

Contributing is too difficult

I just opened an issue, do have a fix and wanted to implement it to open a PR. When I got to work, I hit a few obstacles:

  • I get a compiler error for import Contentful, so I can't build the project.
  • There's no scheme for the unit test target, so I can't run them.
  • make setup fails with [!] No 'Podfile' found in the project directory. make: *** [setup] Error 1

I'm unsure how to proceed now.

Coredata relationship not getting synced when un-publishing and publishing an entry with reference

In the contetful portal, when i un-publish an entry which has reference to other entries and then republish it again, the reference between them are re-instated. However, when syncing this does not happen.

In the iOS DB when entry is unpublished, the relationship is nullified according to delete rule, however when the entry is republished the relationship is not getting synced.

For example - suppose we have an 'Article' entry which references another 'Category' entry. If i unpublish the 'category' entry it is getting synced to the local DB and the relationship between them is nullified, however when i republish the 'Category' entry again, the entry itself is synced but the relationship between 'article' entry and 'category' entry is lost (in contentful portal this relationship exists as before). It is not getting synced.

In case of Android it is working without issues and the relationship is also getting synced.

ContentfulBundleSync tool??

Comments in the SynchronizationManager+SeedDB.swift file make reference to a command line tool that should be used to generate seed files. Where can one obtain this tool.

Feature: Support for non-default locales

Currently, contentful-persistence.swift will only save information to CoreData for the default locale of a Contentful space.

The SDK and persistence library are currently not working in tandem to introspect a fields localizable fields dictionary, and therefore the ability to specify a locale before a save to CoreData is not available.

We need to enable setting the locale on the in-memory Entry and Asset instances before saving to CoreData.

Persisting RichTextDocument

Syncing Entities containing a RichTextDocument attribute via CoreData Transformable does not work for me. Anyone has a trick up his sleeve to make this work?

Use of try! should be avoided

During my Unit Tests I had some crashes that are caused by an error during CoreData save

public func save() {
        try! persistentStore.save()
    }

I saw plenty of places in the SynchronizationManager where error handling is ignored / disabled by the usage of try!.
Why don't you properly use do-catch or just try?.
But try! should only be used if you're certain that there is no error thrown

See: #26

'Cannot find 'SyncInfo' in scope' when loaded via SPM

Added Contentful and ContentfulPersistence SDKs via SPM, I am stuck at
let persistenceModel = PersistenceModel( spaceType: SyncInfo.self, assetType: Asset.self, entryTypes: entryTypes )
Here SyncInfo.self line gives an error "Cannot find SyncInfo in scope"

Can't use the same asset for more than one Entry

I wasn't sure if this issue belongs to this repo or the standard Contentful.swift repo.
The issue is as follows:
I have two Entry items in Contentful and both have a relationship to the same Asset (image) in contentful.
This works fine in the Contentful admin web frontend. Also our Android app shows for both entries the same image.
But the iOS app with CoreData does not show the image for both entries. Only the last entry will show the image.
The first entry has image = nil.
This behavior seems to be expected (not nice) since the Entry model has a one-to-one relationship to the Asset in CoreData and is mapped via the id (same) . What is the best practise to avoid this?

Xcode 9 Asset object could not be created

Can't start our app with Xcode 9. The ContentfulPersistence's SynchronizationManager can't find the Type Asset.
It will be loaded as standard NSManagedObject
Therefore the SynchronizationManager will leave at line 142
screen shot 2017-08-23 at 12 39 53

Core Data is saying: "CoreData: warning: Unable to load class named 'Asset' for entity 'Asset'. Class not found, using default NSManagedObject instead."

I am using NSManagedObject subclasses created with mogenerator

I cannot synchroize my model

screen shot 2017-03-05 at 07 03 33
screen shot 2017-03-05 at 07 03 51
screen shot 2017-03-05 at 07 12 03
First screen is core data model and second is content type model.
This makes a crash now such this.
How can I solve this problem?

Error when syncing

Whenever I call sync I get the following error

Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection

<__NSCFSet: 0x7f83cc1c93f0> was mutated while being enumerated.'

Once I remove the relationships between entities in the model I no longer get the error.

Crash on launch; dyld Symbol not found in Swift 5.4 / XCode 12.5

Created a fresh project, linked Contentful and ContentfulPersistence and get a crash immediately on launch. Only happens when ContentfulPersistence is linked; if I just link the Contentful library, there's no crash. Did not have any issues on the previous version of XCode

My .xcframeworks were built using Carthage 0.38.0.

dyld: Symbol not found: __ZN5swift34swift50override_conformsToProtocolEPKNS_14TargetMetadataINS_9InProcessEEEPKNS_24TargetProtocolDescriptorIS1_EEPFPKNS_18TargetWitnessTableIS1_EES4_S8_E
  Referenced from: /Users/dodge/Library/Developer/Xcode/DerivedData/CarthageTest-ccdjadqjfvdesbgzwfcwneffqihd/Build/Products/Debug-iphonesimulator/ContentfulPersistence.framework/ContentfulPersistence
  Expected in: /Users/dodge/Library/Developer/Xcode/DerivedData/CarthageTest-ccdjadqjfvdesbgzwfcwneffqihd/Build/Products/Debug-iphonesimulator/Contentful.framework/Contentful
 in /Users/dodge/Library/Developer/Xcode/DerivedData/CarthageTest-ccdjadqjfvdesbgzwfcwneffqihd/Build/Products/Debug-iphonesimulator/ContentfulPersistence.framework/ContentfulPersistence

Sync crashes if the contentful output does not contain default locale data

Our output only contains de_DE data. That leads to the assertion assert(mapping.count > 0, "Empty mapping for \(type)") in ContentfulSynchronizer.swift:165 in create(_:fields:type:mapping) to fail.

In the create methods the ContentfulSynchronizer calls deriveMapping with foo.fields.keys. foo.fields takes the fields set from the localizedFields map that's mapped to the "current locale", or the defaultLocale as fallback (see Contentful/Assets.swift or Entry.swift).

The "current locale" is saved on the json NSDictionary (Client.swift:164). But not as additional entry or anything, but using objc_setAssociatedObject (in Decoding.swift). When tried to be retrieved in determineDefaultLocale it's not there anymore.

The bug comes down to Client.swift:166:

(lldb) po (json as! NSDictionary).client
▿ Optional<Client>
  ▿ some : <Client: 0x6000000b9020>
(lldb) po ((json as! [String: Any]) as! NSDictionary).client
nil

p.s. personal opinion: objc_setAssociatedObject is almost never a good idea and should be avoided.

Changing of handling symbol arrays causes crash while seeding DB

During the seeding we get symbol arrays as [String], but new condition
if attributeType == .binaryDataAttributeType, let array = fieldValue as? [NSCoding] {
doesn't catch them. The old one
if let array = fieldValue as? [Any] {
works good.
So currently it crashes like that:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "tagsData"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = (
    "Not searchable"
).'

Crash after mutating model that removes a references within resolveRelationships when cached.

When updating a Contentful object type that removes an existing relationship with another Contentful object type, will resolve in an app crash when trying to resolve this relationship from cachedUnresolvedRelationships.

For example I have a ContentfulDashboardItem Content Type with a reference to ContentfulColor Content Type called backgroundColor. When I update the ContentfulDashboardItem Content Type that removes the reference to ContentfulColor Content Type and restart my app, 9 out of 10 times it works as expected. Though when the SynchronizationManager.swift find unresolved relationships (see cachedUnresolvedRelationships variable), the app will crash because the reference backgroundColor does not exist anymore.

The crash log:

Fatal Exception: NSUnknownKeyException
[<ContentfulDashboardItem 0x28290af80> setValue:forUndefinedKey:]: the entity ContentfulDashboardItem is not key value coding-compliant for the key "backgroundColor".

The line (220) where it crashes in SynchronizationManager.swift:

entryPersistable.setValue(target, forKey: fieldName)

Could the resolve relationships be updated so that it first checks if it can call setValue before calling it and making it crash?

Error with Realm

I implemented Persistence store Protocol for Realm database. Throws me the error "IncorrectThreadException: Realm accessed from incorrect thread."

`class RealmPersistanceStore: PersistenceStore {

private var realm: Realm

init(realm: Realm) {

    self.realm = realm
}

func create<T>(type: Any.Type) throws -> T {
    var type = type
    if let c = type as? AnyClass {
        if let o = c as? Object.Type {
            let object = realm.create(o)
            if let object = object as? T {
                return object
            }
            else {
                type = object.dynamicType
            }
        }

    }
    throw Errors.InvalidType(type: type)
}

func fetchAll<T>(type: Any.Type, predicate: NSPredicate) throws -> [T] {
    if let c = type as? AnyClass {
        let objects = realm.objects(c as! Object.Type).filter(predicate)
        var array: [T] = []
        for i in objects {
            if let o = i as? T {
                array.append(o)
            }
        }
        return array
    }
    throw Errors.InvalidType(type: type)

}

func propertiesFor(type type: Any.Type) throws -> [String] {
    if let c = type as? AnyClass {
        if let o = c as? Object.Type {
            let properties = o.init().objectSchema.properties
            return try properties.map { $0.description }.filter {
                try relationshipsFor(type: type).contains($0)
            }
        }
    }

    throw Errors.InvalidType(type: type)
}
func delete(type: Any.Type, predicate: NSPredicate) throws {
    let objects: [Object] = try fetchAll(type, predicate: predicate)
    objects.forEach {
        self.realm.delete($0)
    }
}

func relationshipsFor(type type: Any.Type) throws -> [String] {
    if let c = type as? AnyClass {
        if let o = c as? Object.Type {
            let relationShips = o.init().objectSchema.properties.filter {
                let objectRelationShips = $0.type == PropertyType.Object
                let linkedObjectRelationShips = $0.type == PropertyType.LinkingObjects
                return objectRelationShips || linkedObjectRelationShips
            }.map {
                $0.description
            }
            return relationShips
        }
    }
    throw Errors.InvalidType(type: type)
}

func save() throws {

}

}`

Please Help.

After updating to the latest version of SDK 0.17.4, app crashes while syncing

In model, wherever array-based field types are implemented based on the hint provided in github description, it crashes. In console the reason for crash is shown as ‘unacceptable type of value for attribute, desired type NSData, given type = SwiftDefferedArray’

Will there be a fix for this from the SDK side or should we change the model accordingly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.