The document discusses best practices for working with Core Data in iOS applications. It covers 9 steps: 1) setting up Core Data, 2) accessing the managed object context, 3) creating NSManagedObject subclasses, 4) creating fetch requests, 5) integrating networking, 6) using NSFetchedResultsController, 7) protocolizing models, 8) using immutable models, and 9) modularizing the code. The overall message is that Core Data code should be organized cleanly using small, single-purpose classes and protocols to improve testability, separation of concerns, and code reuse.
26. cellForRowAtIndexPath:
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier,
forIndexPath: indexPath) as! TweetTableViewCell
let tweet = data[indexPath.row]
if let text = tweet.valueForKey("text") as? String {
cell.multilineTextLabel?.text = text
}
// set up other views
return cell
}
42. NSManagedObject with KVC
let tweet: NSManagedObject = data[indexPath.row]
if let text = tweet.valueForKey("text") as? String {
cell.multilineTextLabel?.text = text
}
45. class _ManagedTweet: NSManagedObject {
...
// MARK: - Properties
@NSManaged
var identifier: NSNumber
@NSManaged
var text: String
// MARK: - Relationships
@NSManaged
var homeTimeline: ManagedHomeTimeline?
@NSManaged
var user: ManagedUser
}
46. enum ManagedTweetAttributes: String {
case identifier = "identifier"
case text = "text"
}
enum ManagedTweetRelationships: String {
case homeTimeline = "homeTimeline"
case user = "user"
}
59. protocol Request {
typealias ResultType
var method: Method { get }
var path: String { get }
var parameters: Dictionary<String, String> { get }
func send(completion: (Result<ResultType, NSError> -> Void))
func resultFromJSON(JSON: AnyObject) throws -> ResultType
}
Result: github.com/antitypical/Result
60. extension Request {
var method: Method { return .GET }
var path: String { return "" }
var parameters: Dictionary<String, String> { return Dictionary() }
}
61. extension Request {
var method: Method { return .GET }
var path: String { return "" }
var parameters: Dictionary<String, String> { return Dictionary() }
func send(completion: (Result<ResultType, NSError> -> Void)) {
let response = RequestSender().send(self)
do {
let result = try self.resultFromJSON(response)
completion(Result(result))
} catch let nserror as NSError {
completion(Result(error: nserror))
}
}
}
62. struct Tweet {
let identifier: Int
let text: String
let user: User
}
struct User {
let identifier: Int
let name: String
let profileImageUrl: String?
let screenName: String
}
65. Value Type → NSManagedObject
» Objective-C
» Mantle with MTLManagedObjectAdapter
» Swift
» CoreValue, but too powerful
» own solution similar to JSON parsing libraries, such as Argo
or Decodable
82. protocol TweetType {
var identifier: Int { get }
var text: String { get }
var user: UserType { get }
}
protocol UserType {
var identifier: Int { get }
var name: String { get }
var profileImageUrl: String? { get }
var screenName: String { get }
}
88. Those Structs
struct Tweet: TweetType {
let identifier: Int
let text: String
let user: User
}
struct User: UserType {
let identifier: Int
let name: String
let profileImageUrl: String?
let screenName: String
}
89. class TweetListRepository: Repository {
weak var delegate: RepositoryDelegate?
var objects: [TweetType] {
// non-optimized version
let fetchedObjects = fetchedResultsController.fetchedObjects
return structsFromManagedObjects(fetchedObjects)
}
}