Tracing 1.0.1

Tracing 1.0.1

TestsTested
LangLanguage SwiftSwift
License MIT
ReleasedLast Release Jul 2017
SwiftSwift Version 3.0
SPMSupports SPM

Maintained by incetro.



Tracing 1.0.1

  • By
  • incetro

Tracing

Tracing is a framework written in Swift that makes it easy for you to divide your cache (CoreData, Realm, etc.) and UI layer. The idea is based on the great article. As you can read in this article, you can use this framework for easy updates your UITableView or something else.

Features

  • [x] Beautiful observation of your objects
  • [x] Universal standard mapping through Transformer
  • [x] Custom mappers support
  • [x] Generics support

Usage

Simple usage with CoreData

In this case we are using built-in mapper. For this your plain objects must support protocol Mappable. So, let’s create some models:

import Tracing

// MARK: - Storable

protocol Storable: class {
    static var entityName: String { get }
}

// MARK: - NSManagedObject

extension Storable where Self: NSManagedObject {
    
    static var entityName: String {
        return NSStringFromClass(self).components(separatedBy: ".").last ?? ""
    }
    
    init(in context: NSManagedObjectContext) {
        
        guard let entity = NSEntityDescription.entity(forEntityName: Self.entityName, in: context) else {
            fatalError("Cannot create entity for entity name: \(Self.entityName)")
        }
        
        self.init(entity: entity, insertInto: context)
    }
}

// MARK: - CategoryModelObject

class CategoryModelObject: NSManagedObject, Storable {
    
    @NSManaged var id: Int64
    @NSManaged var name: String
    @NSManaged var positions: NSSet
}

// MARK: - PositionModelObject

class PositionModelObject: NSManagedObject, Storable {
    
    @NSManaged var id: Int64
    @NSManaged var name: String
    @NSManaged var price: Double
    @NSManaged var category: CategoryModelObject?
}

// MARK: - CategoryPlainObject

class CategoryPlainObject: Mappable {
    
    let id: Int64
    let name: String
    
    var positions: [PositionPlainObject] = [] // Array of objects
    
    required init(with resolver: Resolver) throws {
        
        self.id        = try resolver.value("id")
        self.name      = try resolver.value("name")
        self.positions = (try? resolver.value("positions")) ?? []
    }
}

// MARK: - CategoryPlainObject

class PositionPlainObject: Mappable {
    
    let id: Int64
    let name: String
    let price: Double
    
    var category: CategoryPlainObject? = nil // Nested object
    
    required init(with resolver: Resolver) throws {
        
        self.id       = try  resolver.value("id")
        self.name     = try  resolver.value("name")
        self.price    = try  resolver.value("price")
        self.category = try? resolver.value("category")
    }
}

Okay, we have 2 model object classes (CategoryModelObject, PositionModelObject) and 2 plain object classes (CategoryPlainObject, PositionPlainObject). Now you can use Tracing:

/// Create request for cache
let request = CacheRequest(entityName: CategoryModelObject.entityName)
        
/// Create tracker that tracks changes with CategoryModelObject (Your NSManagedObject)
/// and notify you about this with CategoryPlainObject (Your plain object)
let tracker = Tracing.coreTracker(cacheType: CategoryModelObject.self, plainType: CategoryPlainObject.self)

/// Setup the tracker
tracker.setup(with: request, context: context) { transactionBatch in
    
    /// Transactions with inserted objects
    transactionBatch.insertedTransactions
    
    /// Transactions with updated objects
    transactionBatch.updatedTransactions
    
    /// Transactions with removed objects
    transactionBatch.removedTransactions
    
    /// Transactions with moved objects  
    transactionBatch.movedTansactions
    
    /// Checking for empty
    transactionBatch.isEmpty
    
    /// Or you can get inserted/updated/removed/moved objects
    for category in transactionBatch.insertedObjects {
        
        /// CategoryPlainObject
        category
        
        /// Use category's simple properties
        category.id
        category.name
        
        /// And nested objects
        category.positions
    }
}

Custom mappers

class CategoryMapper: CacheMapper {
    
    typealias CacheType = CategoryModelObject
    typealias PlainType = CategoryPlainObject
    
    func map(from cacheObject: CategoryModelObject) throws -> CategoryPlainObject {
        
        /// Map CategoryModelObject to CategoryPlainObject
    }
}

/// And use it

let mapper  = CategoryMapper()
let tracker = Tracing.coreTracker(with: mapper)

You can track your models with more request settings

let name = CategoryModelObject.entityName
let filter = "id > 5"
let sortDesriptor = SortDescriptor(withKey: "name", ascending: true)

let request = CacheRequest(entityName: name, predicate: filter, sortDescriptors: [sortDesriptor])

Requirements

  • iOS 9.0+ / macOS 10.12+ / tvOS 9.0+ / watchOS 2.0+
  • Xcode 8.1, 8.2, 8.3, and 9.0
  • Swift 3.0, 3.1, 3.2, and 4.0

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Installation

Manually

If you prefer not to use any dependency managers, you can integrate Tracing into your project manually.

Embedded Framework

  • Open up Terminal, cd into your top-level project directory, and run the following command “if” your project is not initialized as a git repository:

    $ git init
  • Add Tracing as a git submodule by running the following command:

    $ git submodule add https://github.com/incetro/Tracing.git
  • Open the new Tracing folder, and drag the Tracing.xcodeproj into the Project Navigator of your application’s Xcode project.

    It should appear nested underneath your application’s blue project icon. Whether it is above or below all the other Xcode groups does not matter.

  • Select the Tracing.xcodeproj in the Project Navigator and verify the deployment target matches that of your application target.

  • Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the “Targets” heading in the sidebar.

  • In the tab bar at the top of that window, open the “General” panel.

  • Click on the + button under the “Embedded Binaries” section.

  • You will see two different Tracing.xcodeproj folders each with two different versions of the Tracing.framework nested inside a Products folder.

    It does not matter which Products folder you choose from, but it does matter whether you choose the top or bottom Tracing.framework.

  • Select the top Tracing.framework for iOS and the bottom one for OS X.

    You can verify which one you selected by inspecting the build log for your project. The build target for Tracing will be listed as either Tracing iOS, Tracing macOS, Tracing tvOS or Tracing watchOS.

  • And that’s it!

    The Tracing.framework is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.

Author

incetro, [email protected]

License

Tracing is available under the MIT license. See the LICENSE file for more info.