Continue major surgery. Everything is wildly broken.

This commit is contained in:
Brent Simmons 2017-07-03 10:29:44 -07:00
parent 944f05c71e
commit d9cfab7d68
35 changed files with 1732 additions and 717 deletions

View File

@ -0,0 +1,114 @@
//
// Account.swift
// DataModel
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
// Various model objects include an accountInfo property that Accounts can use to store extra data.
public typealias AccountInfo = [String: Any]
public enum AccountType: Int {
// Raw values should not change since theyre stored on disk.
case onMyMac = 1
case feedly = 16
case feedbin = 17
case feedWrangler = 18
case newsBlur = 19
// TODO: more
}
public final class Account: Hashable {
public let identifier: String
public let type: AccountType
public var nameForDisplay: String?
public let delegate: AccountDelegate
public let hashValue: Int
let settingsFile: String
let dataFolder: String
var topLevelObjects = [AnyObject]()
var feedIDDictionary = [String: Feed]()
var username: String?
var accountInfo = AccountInfo()
init(settingsFile: String, type: AccountType, dataFolder: String, identifier: String, delegate: AccountDelegate) {
self.identifier = identifier
self.type = type
self.settingsFile = settingsFile
self.dataFolder = dataFolder
self.delegate = delegate
self.hashValue = identifier.hashValue
}
public class func ==(lhs: Account, rhs: Account) -> Bool {
return lhs === rhs
}
}
extension Account: Container {
public func hasAtLeastOneFeed() -> Bool {
return !feedIDDictionary.isEmpty
}
public func flattenedFeeds() -> Set<Feed> {
return Set(feedIDDictionary.values)
}
public func existingFeed(with feedID: String) -> Feed? {
return feedIDDictionary[feedID]
}
public func canAddItem(_ item: AnyObject) -> Bool {
return delegate.canAddItem(item, toContainer: self)
}
public func isChild(_ obj: AnyObject) -> Bool {
return topLevelObjects.contains(where: { (oneObject) -> Bool in
return oneObject === obj
})
}
public func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool {
for oneObject in topLevelObjects {
if let oneContainer = oneObject as? Container {
if visitBlock(oneObject) {
return true
}
if recurse && oneContainer.visitObjects(recurse, visitBlock) {
return true
}
}
else {
if visitBlock(oneObject) {
return true
}
}
}
return false
}
}
extension Account: PlistProvider {
public func plist() -> AnyObject? {
return nil // TODO
}
}

View File

@ -25,11 +25,12 @@ public final class Article: Hashable {
var bannerImageURL: String? var bannerImageURL: String?
var datePublished: Date? var datePublished: Date?
var dateModified: Date? var dateModified: Date?
var authors: [Authors]? var authors: [Author]?
var tags: [String]? var tags: [String]?
var attachments: [Attachment]? var attachments: [Attachment]?
var status: ArticleStatus? var status: ArticleStatus?
public let hashValue: Int
public var accountInfo: [String: Any]? //If account needs to store more data public var accountInfo: [String: Any]? //If account needs to store more data
var feed: Feed? { var feed: Feed? {
@ -38,7 +39,7 @@ public final class Article: Hashable {
} }
} }
init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Authors]?, tags: [String]?, attachments: [Attachment]?) { init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Author]?, tags: [String]?, attachments: [Attachment]?) {
self.account = account self.account = account
self.feedID = feedID self.feedID = feedID
@ -53,11 +54,11 @@ public final class Article: Hashable {
self.bannerImageURL = bannerImageURL self.bannerImageURL = bannerImageURL
self.datePublished = datePublished self.datePublished = datePublished
self.dateModified = dateModified self.dateModified = dateModified
self.dateArrived = dateArrived
self.authors = authors self.authors = authors
self.tags = tags self.tags = tags
self.attachments = attachments self.attachments = attachments
self.articleID = "\(feedID) \(uniqueID)"
self.hashValue = account.hashValue + feedID.hashValue + uniqueID.hashValue self.hashValue = account.hashValue + feedID.hashValue + uniqueID.hashValue
} }
@ -71,7 +72,7 @@ public extension Article {
public var logicalDatePublished: Date? { public var logicalDatePublished: Date? {
get { get {
return (datePublished ?? dateModified) && status?.dateArrived return (datePublished ?? dateModified) ?? status?.dateArrived
} }
} }
} }

View File

@ -0,0 +1,72 @@
//
// ArticleStatus.swift
// DataModel
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public enum ArticleStatusKey: String {
case read = "read"
case starred = "starred"
case userDeleted = "userDeleted"
}
public final class ArticleStatus {
public var read = false
public var starred = false
public var userDeleted = false
public var dateArrived: Date
var accountInfo: AccountInfo?
init(read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date, accountInfo: AccountInfo?) {
self.read = read
self.starred = starred
self.userDeleted = userDeleted
self.dateArrived = dateArrived
self.accountInfo = accountInfo
}
func boolStatusForKey(_ key: String) -> Bool {
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
switch articleStatusKey {
case .read:
return read
case .starred:
return starred
case .userDeleted:
return userDeleted
}
}
else if let flag = accountInfo?[key] as? Bool {
return flag
}
return false
}
func setBoolStatusForKey(_ status: Bool, key: String) {
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
switch articleStatusKey {
case .read:
read = status
case .starred:
starred = status
case .userDeleted:
userDeleted = status
}
}
else {
if accountInfo == nil {
accountInfo = AccountInfo()
}
accountInfo![key] = status
}
}
}

View File

@ -25,8 +25,8 @@ public struct Attachment: Equatable {
self.durationInSeconds = durationInSeconds self.durationInSeconds = durationInSeconds
} }
public class func ==(lhs: Attachment, rhs: Attachment) -> Bool { public static func ==(lhs: Attachment, rhs: Attachment) -> Bool {
return lhs.url == rhs.url && lhs.mimeType == rhs.mimeType && lhs.title == rhs.title && lhs.sizeInBytes == rhs.sizeInBytes && lhs.durationInSeconds == rhs.durationInSeconds return lhs.sizeInBytes == rhs.sizeInBytes && lhs.url == rhs.url && lhs.mimeType == rhs.mimeType && lhs.title == rhs.title && lhs.durationInSeconds == rhs.durationInSeconds
} }
} }

View File

@ -14,7 +14,8 @@ public struct Author: Hashable {
public let url: String? public let url: String?
public let avatarURL: String? public let avatarURL: String?
public let emailAddress: String? public let emailAddress: String?
public let hashValue: Int
public init?(name: String?, url: String?, avatarURL: String?, emailAddress: String?) { public init?(name: String?, url: String?, avatarURL: String?, emailAddress: String?) {
if name == nil && url == nil && emailAddress == nil { if name == nil && url == nil && emailAddress == nil {
@ -25,14 +26,14 @@ public struct Author: Hashable {
self.avatarURL = avatarURL self.avatarURL = avatarURL
self.emailAddress = emailAddress self.emailAddress = emailAddress
let s = name ?? "" var s = name ?? ""
s += url ?? "" s += url ?? ""
s += avatarURL ?? "" s += avatarURL ?? ""
s += emailAddres ?? "" s += emailAddress ?? ""
self.hashValue = s.hashValue self.hashValue = s.hashValue
} }
public class func ==(lhs: Author, rhs: Author) { public static func ==(lhs: Author, rhs: Author) -> Bool {
return lhs.hashValue == rhs.hashValue && lhs.name == rhs.name && lhs.url == rhs.url && lhs.avatarURL == rhs.avatarURL && lhs.emailAddress == rhs.emailAddress return lhs.hashValue == rhs.hashValue && lhs.name == rhs.name && lhs.url == rhs.url && lhs.avatarURL == rhs.avatarURL && lhs.emailAddress == rhs.emailAddress
} }

View File

@ -0,0 +1,573 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
843079FA1F0AB57F00B4B7F7 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEEA31F0AB512004AB7CD /* RSCore.framework */; };
844BEE651F0AB3C9004AB7CD /* Data.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE5B1F0AB3C8004AB7CD /* Data.framework */; };
844BEE6A1F0AB3C9004AB7CD /* DataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE691F0AB3C9004AB7CD /* DataTests.swift */; };
844BEE791F0AB4B8004AB7CD /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE781F0AB4B8004AB7CD /* Account.swift */; };
844BEE7B1F0AB4BE004AB7CD /* Folder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE7A1F0AB4BE004AB7CD /* Folder.swift */; };
844BEE7D1F0AB4C4004AB7CD /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE7C1F0AB4C4004AB7CD /* Feed.swift */; };
844BEE7F1F0AB4CA004AB7CD /* Article.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE7E1F0AB4CA004AB7CD /* Article.swift */; };
844BEE811F0AB4D0004AB7CD /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE801F0AB4D0004AB7CD /* Author.swift */; };
844BEE831F0AB4D6004AB7CD /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE821F0AB4D6004AB7CD /* Attachment.swift */; };
844BEE851F0AB4DB004AB7CD /* ArticleStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE841F0AB4DB004AB7CD /* ArticleStatus.swift */; };
844BEE871F0AB4E3004AB7CD /* BatchUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE861F0AB4E3004AB7CD /* BatchUpdates.swift */; };
844BEE891F0AB4E7004AB7CD /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE881F0AB4E7004AB7CD /* Notifications.swift */; };
844BEE8F1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE8B1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift */; };
844BEE901F0AB4EF004AB7CD /* Feed+OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE8C1F0AB4EF004AB7CD /* Feed+OPMLRepresentable.swift */; };
844BEE911F0AB4EF004AB7CD /* Folder+OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE8D1F0AB4EF004AB7CD /* Folder+OPMLRepresentable.swift */; };
844BEE921F0AB4EF004AB7CD /* OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE8E1F0AB4EF004AB7CD /* OPMLRepresentable.swift */; };
844BEE981F0AB4F8004AB7CD /* AccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE941F0AB4F8004AB7CD /* AccountDelegate.swift */; };
844BEE991F0AB4F8004AB7CD /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE951F0AB4F8004AB7CD /* Container.swift */; };
844BEE9A1F0AB4F8004AB7CD /* DisplayNameProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE961F0AB4F8004AB7CD /* DisplayNameProvider.swift */; };
844BEE9B1F0AB4F8004AB7CD /* UnreadCountProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE971F0AB4F8004AB7CD /* UnreadCountProvider.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
844BEE661F0AB3C9004AB7CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 844BEE521F0AB3C8004AB7CD /* Project object */;
proxyType = 1;
remoteGlobalIDString = 844BEE5A1F0AB3C8004AB7CD;
remoteInfo = Data;
};
844BEEA21F0AB512004AB7CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 84CFF4F41AC3C69700CEA6C8;
remoteInfo = RSCore;
};
844BEEA41F0AB512004AB7CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 84CFF4FF1AC3C69700CEA6C8;
remoteInfo = RSCoreTests;
};
844BEEA61F0AB512004AB7CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 842DD7BC1E14993900E061EB;
remoteInfo = RSCoreiOS;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
844BEE5B1F0AB3C8004AB7CD /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE641F0AB3C9004AB7CD /* DataTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE691F0AB3C9004AB7CD /* DataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTests.swift; sourceTree = "<group>"; };
844BEE6B1F0AB3C9004AB7CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
844BEE761F0AB444004AB7CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
844BEE781F0AB4B8004AB7CD /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
844BEE7A1F0AB4BE004AB7CD /* Folder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Folder.swift; sourceTree = "<group>"; };
844BEE7C1F0AB4C4004AB7CD /* Feed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
844BEE7E1F0AB4CA004AB7CD /* Article.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Article.swift; sourceTree = "<group>"; };
844BEE801F0AB4D0004AB7CD /* Author.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = "<group>"; };
844BEE821F0AB4D6004AB7CD /* Attachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
844BEE841F0AB4DB004AB7CD /* ArticleStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArticleStatus.swift; sourceTree = "<group>"; };
844BEE861F0AB4E3004AB7CD /* BatchUpdates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatchUpdates.swift; sourceTree = "<group>"; };
844BEE881F0AB4E7004AB7CD /* Notifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
844BEE8B1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Account+OPMLRepresentable.swift"; sourceTree = "<group>"; };
844BEE8C1F0AB4EF004AB7CD /* Feed+OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Feed+OPMLRepresentable.swift"; sourceTree = "<group>"; };
844BEE8D1F0AB4EF004AB7CD /* Folder+OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Folder+OPMLRepresentable.swift"; sourceTree = "<group>"; };
844BEE8E1F0AB4EF004AB7CD /* OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OPMLRepresentable.swift; sourceTree = "<group>"; };
844BEE941F0AB4F8004AB7CD /* AccountDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountDelegate.swift; sourceTree = "<group>"; };
844BEE951F0AB4F8004AB7CD /* Container.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
844BEE961F0AB4F8004AB7CD /* DisplayNameProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayNameProvider.swift; sourceTree = "<group>"; };
844BEE971F0AB4F8004AB7CD /* UnreadCountProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnreadCountProvider.swift; sourceTree = "<group>"; };
844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSCore.xcodeproj; path = ../RSCore/RSCore.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
844BEE571F0AB3C8004AB7CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
843079FA1F0AB57F00B4B7F7 /* RSCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE611F0AB3C9004AB7CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE651F0AB3C9004AB7CD /* Data.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
844BEE511F0AB3C8004AB7CD = {
isa = PBXGroup;
children = (
844BEE781F0AB4B8004AB7CD /* Account.swift */,
844BEE7A1F0AB4BE004AB7CD /* Folder.swift */,
844BEE7C1F0AB4C4004AB7CD /* Feed.swift */,
844BEE7E1F0AB4CA004AB7CD /* Article.swift */,
844BEE801F0AB4D0004AB7CD /* Author.swift */,
844BEE821F0AB4D6004AB7CD /* Attachment.swift */,
844BEE841F0AB4DB004AB7CD /* ArticleStatus.swift */,
844BEE861F0AB4E3004AB7CD /* BatchUpdates.swift */,
844BEE881F0AB4E7004AB7CD /* Notifications.swift */,
844BEE8A1F0AB4EF004AB7CD /* OPML */,
844BEE931F0AB4F8004AB7CD /* Protocols */,
844BEE761F0AB444004AB7CD /* Info.plist */,
844BEE681F0AB3C9004AB7CD /* DataTests */,
844BEE5C1F0AB3C8004AB7CD /* Products */,
844BEEA81F0AB520004AB7CD /* Frameworks */,
);
sourceTree = "<group>";
};
844BEE5C1F0AB3C8004AB7CD /* Products */ = {
isa = PBXGroup;
children = (
844BEE5B1F0AB3C8004AB7CD /* Data.framework */,
844BEE641F0AB3C9004AB7CD /* DataTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
844BEE681F0AB3C9004AB7CD /* DataTests */ = {
isa = PBXGroup;
children = (
844BEE691F0AB3C9004AB7CD /* DataTests.swift */,
844BEE6B1F0AB3C9004AB7CD /* Info.plist */,
);
path = DataTests;
sourceTree = "<group>";
};
844BEE8A1F0AB4EF004AB7CD /* OPML */ = {
isa = PBXGroup;
children = (
844BEE8B1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift */,
844BEE8C1F0AB4EF004AB7CD /* Feed+OPMLRepresentable.swift */,
844BEE8D1F0AB4EF004AB7CD /* Folder+OPMLRepresentable.swift */,
844BEE8E1F0AB4EF004AB7CD /* OPMLRepresentable.swift */,
);
path = OPML;
sourceTree = "<group>";
};
844BEE931F0AB4F8004AB7CD /* Protocols */ = {
isa = PBXGroup;
children = (
844BEE941F0AB4F8004AB7CD /* AccountDelegate.swift */,
844BEE951F0AB4F8004AB7CD /* Container.swift */,
844BEE961F0AB4F8004AB7CD /* DisplayNameProvider.swift */,
844BEE971F0AB4F8004AB7CD /* UnreadCountProvider.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
844BEE9D1F0AB512004AB7CD /* Products */ = {
isa = PBXGroup;
children = (
844BEEA31F0AB512004AB7CD /* RSCore.framework */,
844BEEA51F0AB512004AB7CD /* RSCoreTests.xctest */,
844BEEA71F0AB512004AB7CD /* RSCore.framework */,
);
name = Products;
sourceTree = "<group>";
};
844BEEA81F0AB520004AB7CD /* Frameworks */ = {
isa = PBXGroup;
children = (
844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
844BEE581F0AB3C8004AB7CD /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
844BEE5A1F0AB3C8004AB7CD /* Data */ = {
isa = PBXNativeTarget;
buildConfigurationList = 844BEE6F1F0AB3C9004AB7CD /* Build configuration list for PBXNativeTarget "Data" */;
buildPhases = (
844BEE561F0AB3C8004AB7CD /* Sources */,
844BEE571F0AB3C8004AB7CD /* Frameworks */,
844BEE581F0AB3C8004AB7CD /* Headers */,
844BEE591F0AB3C8004AB7CD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Data;
productName = Data;
productReference = 844BEE5B1F0AB3C8004AB7CD /* Data.framework */;
productType = "com.apple.product-type.framework";
};
844BEE631F0AB3C9004AB7CD /* DataTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 844BEE721F0AB3C9004AB7CD /* Build configuration list for PBXNativeTarget "DataTests" */;
buildPhases = (
844BEE601F0AB3C9004AB7CD /* Sources */,
844BEE611F0AB3C9004AB7CD /* Frameworks */,
844BEE621F0AB3C9004AB7CD /* Resources */,
);
buildRules = (
);
dependencies = (
844BEE671F0AB3C9004AB7CD /* PBXTargetDependency */,
);
name = DataTests;
productName = DataTests;
productReference = 844BEE641F0AB3C9004AB7CD /* DataTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
844BEE521F0AB3C8004AB7CD /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = "Ranchero Software";
TargetAttributes = {
844BEE5A1F0AB3C8004AB7CD = {
CreatedOnToolsVersion = 8.3.2;
DevelopmentTeam = 9C84TZ7Q6Z;
LastSwiftMigration = 0830;
ProvisioningStyle = Automatic;
};
844BEE631F0AB3C9004AB7CD = {
CreatedOnToolsVersion = 8.3.2;
DevelopmentTeam = 9C84TZ7Q6Z;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 844BEE551F0AB3C8004AB7CD /* Build configuration list for PBXProject "Data" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 844BEE511F0AB3C8004AB7CD;
productRefGroup = 844BEE5C1F0AB3C8004AB7CD /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 844BEE9D1F0AB512004AB7CD /* Products */;
ProjectRef = 844BEE9C1F0AB512004AB7CD /* RSCore.xcodeproj */;
},
);
projectRoot = "";
targets = (
844BEE5A1F0AB3C8004AB7CD /* Data */,
844BEE631F0AB3C9004AB7CD /* DataTests */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
844BEEA31F0AB512004AB7CD /* RSCore.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = RSCore.framework;
remoteRef = 844BEEA21F0AB512004AB7CD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
844BEEA51F0AB512004AB7CD /* RSCoreTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = RSCoreTests.xctest;
remoteRef = 844BEEA41F0AB512004AB7CD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
844BEEA71F0AB512004AB7CD /* RSCore.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = RSCore.framework;
remoteRef = 844BEEA61F0AB512004AB7CD /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
844BEE591F0AB3C8004AB7CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE621F0AB3C9004AB7CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
844BEE561F0AB3C8004AB7CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE911F0AB4EF004AB7CD /* Folder+OPMLRepresentable.swift in Sources */,
844BEE901F0AB4EF004AB7CD /* Feed+OPMLRepresentable.swift in Sources */,
844BEE7F1F0AB4CA004AB7CD /* Article.swift in Sources */,
844BEE791F0AB4B8004AB7CD /* Account.swift in Sources */,
844BEE7D1F0AB4C4004AB7CD /* Feed.swift in Sources */,
844BEE891F0AB4E7004AB7CD /* Notifications.swift in Sources */,
844BEE9A1F0AB4F8004AB7CD /* DisplayNameProvider.swift in Sources */,
844BEE8F1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift in Sources */,
844BEE991F0AB4F8004AB7CD /* Container.swift in Sources */,
844BEE7B1F0AB4BE004AB7CD /* Folder.swift in Sources */,
844BEE981F0AB4F8004AB7CD /* AccountDelegate.swift in Sources */,
844BEE831F0AB4D6004AB7CD /* Attachment.swift in Sources */,
844BEE871F0AB4E3004AB7CD /* BatchUpdates.swift in Sources */,
844BEE811F0AB4D0004AB7CD /* Author.swift in Sources */,
844BEE921F0AB4EF004AB7CD /* OPMLRepresentable.swift in Sources */,
844BEE9B1F0AB4F8004AB7CD /* UnreadCountProvider.swift in Sources */,
844BEE851F0AB4DB004AB7CD /* ArticleStatus.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE601F0AB3C9004AB7CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE6A1F0AB3C9004AB7CD /* DataTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
844BEE671F0AB3C9004AB7CD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 844BEE5A1F0AB3C8004AB7CD /* Data */;
targetProxy = 844BEE661F0AB3C9004AB7CD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
844BEE6D1F0AB3C9004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
844BEE6E1F0AB3C9004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
844BEE701F0AB3C9004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Data;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
844BEE711F0AB3C9004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Data;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
844BEE731F0AB3C9004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
INFOPLIST_FILE = DataTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DataTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
844BEE741F0AB3C9004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
INFOPLIST_FILE = DataTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DataTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
844BEE551F0AB3C8004AB7CD /* Build configuration list for PBXProject "Data" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE6D1F0AB3C9004AB7CD /* Debug */,
844BEE6E1F0AB3C9004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
844BEE6F1F0AB3C9004AB7CD /* Build configuration list for PBXNativeTarget "Data" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE701F0AB3C9004AB7CD /* Debug */,
844BEE711F0AB3C9004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
844BEE721F0AB3C9004AB7CD /* Build configuration list for PBXNativeTarget "DataTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE731F0AB3C9004AB7CD /* Debug */,
844BEE741F0AB3C9004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 844BEE521F0AB3C8004AB7CD /* Project object */;
}

View File

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:DataModel.xcodeproj"> location = "self:Data.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>

View File

@ -0,0 +1,36 @@
//
// DataTests.swift
// DataTests
//
// Created by Brent Simmons on 7/3/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import XCTest
@testable import Data
class DataTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -14,31 +14,43 @@ public final class Feed: UnreadCountProvider, DisplayNameProvider, Hashable {
public let account: Account public let account: Account
public let url: String public let url: String
public let feedID: String public let feedID: String
public var homePageURL: String? public var homePageURL: String?
public var name: String? public var name: String?
public var editedName: String? public var editedName: String?
public var articles = Set<Article>()
public var accountInfo: [String: Any]? //If account needs to store more data
public let hashValue: Int
public var nameForDisplay: String { public var nameForDisplay: String {
get { get {
return (editedName ?? name) ?? NSLocalizedString("Untitled", comment: "Feed name") return (editedName ?? name) ?? NSLocalizedString("Untitled", comment: "Feed name")
} }
} }
public var articles = Set<Article>() public var unreadCount = 0 {
public var accountInfo: [String: Any]? //If account needs to store more data didSet {
if unreadCount != oldValue {
postUnreadCountDidChangeNotification()
}
}
}
public init(account: Account, url: String, feedID: String) { public init(account: Account, url: String, feedID: String) {
self.account = account self.account = account
self.url = url self.url = url
self.feedID = feedID self.feedID = feedID
self.hashValue = account.hashValue + url.hashValue + feedID.hashValue self.hashValue = account.hashValue ^ url.hashValue ^ feedID.hashValue
} }
public fetchArticles() -> Set<Article> { public func updateUnreadCount() {
articles = account.fetchArticles(self) unreadCount = articles.reduce(0) { (result, oneArticle) -> Int in
return articles if let read = oneArticle.status?.read, !read {
return result + 1
}
return result
}
} }
public class func ==(lhs: Feed, rhs: Feed) -> Bool { public class func ==(lhs: Feed, rhs: Feed) -> Bool {
@ -47,20 +59,3 @@ public final class Feed: UnreadCountProvider, DisplayNameProvider, Hashable {
} }
} }
public extension Feed: OPMLRepresentable {
func OPMLString(indentLevel: Int) -> String {
let escapedName = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
var escapedHomePageURL = ""
if let homePageURL = homePageURL {
escapedHomePageURL = homePageURL.rs_stringByEscapingSpecialXMLCharacters()
}
let escapedFeedURL = url.rs_stringByEscapingSpecialXMLCharacters()
var s = "<outline text=\"\(escapedName)\" title=\"\(escapedName)\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"\(escapedHomePageURL)\" xmlUrl=\"\(escapedFeedURL)\"/>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
return s
}
}

View File

@ -0,0 +1,100 @@
//
// Folder.swift
// DataModel
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public final class Folder: UnreadCountProvider {
public let account: Account
public var nameForDisplay: String
var childObjects = [AnyObject]()
init(account: Account, nameForDisplay: String) {
self.account = account
self.nameForDisplay = nameForDisplay
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
}
// MARK: Notifications
dynamic public func unreadCountDidChange(_ note: Notification) {
guard let obj = note.object else {
return
}
let potentialChild = obj as AnyObject
if isChild(potentialChild) {
updateUnreadCount()
}
}
// MARK: UnreadCountProvider
public var unreadCount = 0 {
didSet {
if unreadCount != oldValue {
postUnreadCountDidChangeNotification()
}
}
}
public func updateUnreadCount() {
unreadCount = calculateUnreadCount(childObjects)
}
}
extension Folder: Container {
public func flattenedFeeds() -> Set<Feed> {
var feeds = Set<Feed>()
for oneChild in childObjects {
if let oneFeed = oneChild as? Feed {
feeds.insert(oneFeed)
}
else if let oneContainer = oneChild as? Container {
feeds.formUnion(oneContainer.flattenedFeeds())
}
}
return feeds
}
public func isChild(_ obj: AnyObject) -> Bool {
return childObjects.contains(where: { (oneObject) -> Bool in
return oneObject === obj
})
}
public func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool {
for oneObject in childObjects {
if let oneContainer = oneObject as? Container {
if visitBlock(oneObject) {
return true
}
if recurse && oneContainer.visitObjects(recurse, visitBlock) {
return true
}
}
else {
if visitBlock(oneObject) {
return true
}
}
}
return false
}
}

View File

@ -19,7 +19,7 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Ranchero Software, LLC. All rights reserved.</string> <string>Copyright © 2017 Ranchero Software. All rights reserved.</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string></string> <string></string>
</dict> </dict>

View File

@ -0,0 +1,23 @@
//
// Account+OPMLRepresentable.swift
// DataModel
//
// Created by Brent Simmons on 7/2/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
extension Account: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String {
var s = ""
for oneObject in topLevelObjects {
if let oneOPMLObject = oneObject as? OPMLRepresentable {
s += oneOPMLObject.OPMLString(indentLevel: indentLevel + 1)
}
}
return s
}
}

View File

@ -0,0 +1,28 @@
//
// Feed+OPMLRepresentable.swift
// DataModel
//
// Created by Brent Simmons on 7/2/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
extension Feed: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String {
let escapedName = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
var escapedHomePageURL = ""
if let homePageURL = homePageURL {
escapedHomePageURL = homePageURL.rs_stringByEscapingSpecialXMLCharacters()
}
let escapedFeedURL = url.rs_stringByEscapingSpecialXMLCharacters()
var s = "<outline text=\"\(escapedName)\" title=\"\(escapedName)\" description=\"\" type=\"rss\" version=\"RSS\" htmlUrl=\"\(escapedHomePageURL)\" xmlUrl=\"\(escapedFeedURL)\"/>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
return s
}
}

View File

@ -0,0 +1,41 @@
//
// Folder+OPMLRepresentable.swift
// DataModel
//
// Created by Brent Simmons on 7/2/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
extension Folder: OPMLRepresentable {
public func OPMLString(indentLevel: Int) -> String {
let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\">\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
var hasAtLeastOneChild = false
let _ = visitChildren { (oneChild) -> Bool in
if let oneOPMLObject = oneChild as? OPMLRepresentable {
s += oneOPMLObject.OPMLString(indentLevel: indentLevel + 1)
hasAtLeastOneChild = true
}
return false
}
if !hasAtLeastOneChild {
s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"/>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
return s
}
s = s + NSString.rs_string(withNumberOfTabs: indentLevel) + "</outline>\n"
return s
}
}

View File

@ -10,7 +10,7 @@ import Foundation
public protocol AccountDelegate { public protocol AccountDelegate {
func canAddItem(_ item: AnyObject, toContainer: Container) -> Bool
} }

View File

@ -0,0 +1,150 @@
//
// Container.swift
// Evergreen
//
// Created by Brent Simmons on 4/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
public typealias VisitBlock = (_ obj: AnyObject) -> Bool // Return true to stop
extension NSNotification.Name {
public static let ChildrenDidChange = Notification.Name("ChildrenDidChangeNotification")
}
public protocol Container: class {
//Recursive
func hasAtLeastOneFeed() -> Bool
func flattenedFeeds() -> Set<Feed>
func existingFeed(with feedID: String) -> Feed?
func existingFeed(withURL url: String) -> Feed?
func isChild(_ obj: AnyObject) -> Bool
// visitBlock should return true to stop visiting.
// visitObjects returns true if a visitBlock returned true.
func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool
//
//// func objectIsChild(_ obj: AnyObject) -> Bool
//// func objectIsDescendant(_ obj: AnyObject) -> Bool
////
//// func fetchArticles() -> [Article]
//
// // visitBlock should return true to stop visiting.
// // visitObjects returns true if a visitBlock returned true.
//// func visitObjects(_ recurse: Bool, visitBlock: VisitBlock) -> Bool
//// func visitChildren(visitBlock: VisitBlock) -> Bool // Above with recurse = false
////
//// func findObject(_ recurse: Bool, visitBlock: VisitBlock) -> AnyObject?
//
// func canAddItem(_ item: AnyObject) -> Bool
// func addItem(_ item: AnyObject) -> Bool // Return true even if item already exists.
// func addItems(_ items: [AnyObject]) -> Bool // Return true even if some items already exist.
//
// func canAddFolderWithName(_ folderName: String) -> Bool // Special case: folder with name exists. Return true in that case.
// func ensureFolderWithName(_ folderName: String) -> Folder? // Return folder even if item already exists.
//
// // Does not recurse.
// func existingFolderWithName(_ name: String) -> Folder?
//
// // Doesn't add feed. Just creates instance.
// func createFeedWithName(_ name: String?, editedName: String?, urlString: String) -> Feed?
//
// func deleteItems(_ items: [AnyObject])
}
public extension Container {
func hasAtLeastOneFeed() -> Bool {
let foundObject = findObject(true, visitBlock: { (oneDescendant) -> Bool in
return oneDescendant is Feed
})
return foundObject != nil
}
func existingFeed(with feedID: String) -> Feed? {
let foundObject = findObject(true) { (oneDescendant) -> Bool in
if let oneFeed = oneDescendant as? Feed, oneFeed.feedID == feedID {
return true
}
return false
}
return foundObject as! Feed?
}
func existingFeed(withURL url: String) -> Feed? {
let foundObject = findObject(true) { (oneDescendant) -> Bool in
if let oneFeed = oneDescendant as? Feed, oneFeed.url == url {
return true
}
return false
}
return foundObject as! Feed?
}
func visitChildren(visitBlock: VisitBlock) -> Bool {
return visitObjects(false, visitBlock)
}
func findObject(_ recurse: Bool, visitBlock: @escaping VisitBlock) -> AnyObject? {
var foundObject: AnyObject?
let _ = visitObjects(recurse) { (oneObject) in
if let _ = foundObject {
return true
}
if visitBlock(oneObject) {
foundObject = oneObject
return true
}
return false
}
return foundObject
}
func objectIsChild(_ obj: AnyObject) -> Bool {
return visitObjects(false) { (oneObject) in
return obj === oneObject
}
}
func objectIsDescendant(_ obj: AnyObject) -> Bool {
return visitObjects(true) { (oneObject) in
return obj === oneObject
}
}
func existingFolderWithName(_ name: String) -> Folder? {
let foundObject = findObject(false) { (oneObject) in
if let oneFolder = oneObject as? Folder, oneFolder.nameForDisplay == name {
return true
}
return false
}
return foundObject as! Folder?
}
public func postChildrenDidChangeNotification() {
NotificationCenter.default.post(name: .ChildrenDidChange, object: self)
}
}

View File

@ -17,12 +17,11 @@ public protocol UnreadCountProvider {
public func calculateUnreadCount<T: Collection>(_ children: T) -> Int { public func calculateUnreadCount<T: Collection>(_ children: T) -> Int {
var updatedUnreadCount = 0 let updatedUnreadCount = children.reduce(0) { (result, oneChild) -> Int in
children.forEach { (oneChild) in
if let oneUnreadCountProvider = oneChild as? UnreadCountProvider { if let oneUnreadCountProvider = oneChild as? UnreadCountProvider {
updatedUnreadCount += oneUnreadCountProvider.unreadCount return result + oneUnreadCountProvider.unreadCount
} }
return result
} }
return updatedUnreadCount return updatedUnreadCount

View File

@ -1,35 +0,0 @@
//
// Account.swift
// DataModel
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public enum AccountType: Int {
case onMyMac = 1
case feedly = 16
case feedbin
case feedWrangler
case newsBlur
}
public final class Account: Container, PlistProvider {
public let identifier: String
public let type: AccountType
public var nameForDisplay: String
public weak var delegate: AccountDelegate
init(settingsFile: String, type: AccountType, dataFolder: String, identifier: String, delegate: AccountDelegate) {
self.identifier = identifier
self.type = type
self.settingsFile = settingsFile
self.dataFolder = dataFolder
self.delegate = delegate
}
}

View File

@ -1,44 +0,0 @@
//
// AccountProtocol.swift
// Evergreen
//
// Created by Brent Simmons on 4/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public protocol Account: class, Folder {
var identifier: String {get}
var type: String {get}
var refreshInProgress: Bool {get}
init(settingsFile: String, dataFolder: String, identifier: String)
func refreshAll()
func markArticles(_ articles: NSSet, statusKey: ArticleStatusKey, flag: Bool)
func hasFeedWithURLString(_: String) -> Bool
func importOPML(_: Any)
func fetchArticles(for: [AnyObject]) -> [Article]
}
public extension Account {
func hasFeedWithURLString(_ urlString: String) -> Bool {
if let _ = existingFeedWithURL(urlString) {
return true
}
return false
}
public func postArticleStatusesDidChangeNotification(_ articles: NSSet) {
NotificationCenter.default.post(name: .ArticleStatusesDidChange, object: self, userInfo: [articlesKey: articles])
}
}

View File

@ -1,43 +0,0 @@
//
// ArticleStatusProtocol.swift
// Evergreen
//
// Created by Brent Simmons on 4/23/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public enum ArticleStatusKey: String {
case read = "read"
case starred = "starred"
case userDeleted = "userDeleted"
}
public protocol ArticleStatus {
var read: Bool {get set}
var starred: Bool {get set}
var userDeleted: Bool {get set}
var dateArrived: Date {get}
func boolStatusForKey(_ articleStatusKey: ArticleStatusKey) -> Bool
func setBoolStatusForKey(_ status: Bool, articleStatusKey: ArticleStatusKey)
}
public extension ArticleStatus {
func boolStatusForKey(_ articleStatusKey: ArticleStatusKey) -> Bool {
switch articleStatusKey {
case .read:
return read
case .starred:
return starred
case .userDeleted:
return userDeleted
}
}
}

View File

@ -1,168 +0,0 @@
//
// FolderProtocol.swift
// Evergreen
//
// Created by Brent Simmons on 4/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSCore
public typealias FolderVisitBlock = (_ obj: AnyObject) -> Bool
public let FolderChildrenDidChangeNotification = "FolderChildNodesDidChangeNotification"
public func FolderPostChildrenDidChangeNotification(_ folder: Folder) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: FolderChildrenDidChangeNotification), object: folder)
}
public protocol Container: class {
var account: Account? {get}
var hasAtLeastOneFeed: Bool {get} //Recursive
var flattenedFeeds: NSSet {get}
func objectIsChild(_ obj: AnyObject) -> Bool
func objectIsDescendant(_ obj: AnyObject) -> Bool
func fetchArticles() -> [Article]
// visitBlock should return true to stop visiting.
// visitObjects returns true if a visitBlock returned true.
func visitObjects(_ recurse: Bool, visitBlock: FolderVisitBlock) -> Bool
func visitChildren(visitBlock: FolderVisitBlock) -> Bool // Above with recurse = false
func findObject(_ recurse: Bool, visitBlock: FolderVisitBlock) -> AnyObject?
func canAddItem(_ item: AnyObject) -> Bool
func addItem(_ item: AnyObject) -> Bool // Return true even if item already exists.
func addItems(_ items: [AnyObject]) -> Bool // Return true even if some items already exist.
func canAddFolderWithName(_ folderName: String) -> Bool // Special case: folder with name exists. Return true in that case.
func ensureFolderWithName(_ folderName: String) -> Folder? // Return folder even if item already exists.
// Recurses
func existingFeedWithID(_ feedID: String) -> Feed?
func existingFeedWithURL(_ urlString: String) -> Feed?
// Does not recurse.
func existingFolderWithName(_ name: String) -> Folder?
// Doesn't add feed. Just creates instance.
func createFeedWithName(_ name: String?, editedName: String?, urlString: String) -> Feed?
func deleteItems(_ items: [AnyObject])
// Exporting OPML.
func opmlString(indentLevel: Int) -> String
}
public extension Folder {
var hasAtLeastOneFeed: Bool {
get {
return visitObjects(true) { (oneObject) in
return oneObject is Feed
}
}
}
func visitChildren(visitBlock: FolderVisitBlock) -> Bool {
return visitObjects(false, visitBlock: visitBlock)
}
func findObject(_ recurse: Bool, visitBlock: FolderVisitBlock) -> AnyObject? {
var foundObject: AnyObject?
let _ = visitObjects(recurse) { (oneObject) in
if let _ = foundObject {
return true
}
if visitBlock(oneObject) {
foundObject = oneObject
return true
}
return false
}
return foundObject
}
func objectIsChild(_ obj: AnyObject) -> Bool {
return visitObjects(false) { (oneObject) in
return obj === oneObject
}
}
func objectIsDescendant(_ obj: AnyObject) -> Bool {
return visitObjects(true) { (oneObject) in
return obj === oneObject
}
}
func existingFolderWithName(_ name: String) -> Folder? {
let foundObject = findObject(false) { (oneObject) in
if let oneFolder = oneObject as? Folder, oneFolder.nameForDisplay == name {
return true
}
return false
}
return foundObject as! Folder?
}
func addItems(_ items: [AnyObject]) -> Bool {
var atLeastOneItemAdded = false
items.forEach { (oneItem) in
if addItem(oneItem) {
atLeastOneItemAdded = true
}
}
return atLeastOneItemAdded
}
func opmlString(indentLevel: Int) -> String {
let escapedTitle = nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
var s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\">\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
var hasAtLeastOneChild = false
let _ = visitChildren { (oneChild) -> Bool in
hasAtLeastOneChild = true
if let oneFolder = oneChild as? Folder {
s = s + oneFolder.opmlString(indentLevel: indentLevel + 1)
}
else if let oneFeed = oneChild as? Feed {
s = s + oneFeed.opmlString(indentLevel: indentLevel + 1)
}
return false
}
if !hasAtLeastOneChild {
s = "<outline text=\"\(escapedTitle)\" title=\"\(escapedTitle)\"/>\n"
s = s.rs_string(byPrependingNumberOfTabs: indentLevel)
return s
}
s = s + NSString.rs_string(withNumberOfTabs: indentLevel) + "</outline>\n"
return s
}
}

View File

@ -1,366 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
8439773E1DA07F2400F0FCBD /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8439773D1DA07F2400F0FCBD /* RSCore.framework */; };
8471A2CC1ED4CEEE008F099E /* AccountProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2C81ED4CEEE008F099E /* AccountProtocol.swift */; };
8471A2CE1ED4CEEE008F099E /* ArticleStatusProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2CA1ED4CEEE008F099E /* ArticleStatusProtocol.swift */; };
8471A2CF1ED4CEEE008F099E /* BatchUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2CB1ED4CEEE008F099E /* BatchUpdates.swift */; };
8471A2D51ED4CEFA008F099E /* DisplayNameProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2D01ED4CEFA008F099E /* DisplayNameProviderProtocol.swift */; };
8471A2D71ED4CEFA008F099E /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2D21ED4CEFA008F099E /* Container.swift */; };
8471A2D81ED4CEFA008F099E /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2D31ED4CEFA008F099E /* Notifications.swift */; };
8471A2D91ED4CEFA008F099E /* UnreadCountProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8471A2D41ED4CEFA008F099E /* UnreadCountProviderProtocol.swift */; };
84F466A61F08389400225386 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466A51F08389400225386 /* Account.swift */; };
84F466A81F083A2A00225386 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466A71F083A2A00225386 /* Feed.swift */; };
84F466AA1F083B7A00225386 /* OPMLRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466A91F083B7A00225386 /* OPMLRepresentable.swift */; };
84F466AC1F083F2600225386 /* Article.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466AB1F083F2600225386 /* Article.swift */; };
84F466AE1F08435800225386 /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466AD1F08435800225386 /* Author.swift */; };
84F466B01F0862AF00225386 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466AF1F0862AF00225386 /* Attachment.swift */; };
84F466B21F0863D700225386 /* AccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466B11F0863D700225386 /* AccountDelegate.swift */; };
84F466B41F08725700225386 /* Folder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F466B31F08725700225386 /* Folder.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
8439773D1DA07F2400F0FCBD /* RSCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RSCore.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Rainier-cidsoqwawkdqqphkdtrqrojskege/Build/Products/Debug/RSCore.framework"; sourceTree = "<group>"; };
8471A2C81ED4CEEE008F099E /* AccountProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountProtocol.swift; sourceTree = "<group>"; };
8471A2CA1ED4CEEE008F099E /* ArticleStatusProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArticleStatusProtocol.swift; sourceTree = "<group>"; };
8471A2CB1ED4CEEE008F099E /* BatchUpdates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatchUpdates.swift; sourceTree = "<group>"; };
8471A2D01ED4CEFA008F099E /* DisplayNameProviderProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayNameProviderProtocol.swift; sourceTree = "<group>"; };
8471A2D21ED4CEFA008F099E /* Container.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
8471A2D31ED4CEFA008F099E /* Notifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
8471A2D41ED4CEFA008F099E /* UnreadCountProviderProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnreadCountProviderProtocol.swift; sourceTree = "<group>"; };
8471A2DA1ED4CF01008F099E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84C7AE921D68C558009FB883 /* DataModel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DataModel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
84F466A51F08389400225386 /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
84F466A71F083A2A00225386 /* Feed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
84F466A91F083B7A00225386 /* OPMLRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OPMLRepresentable.swift; sourceTree = "<group>"; };
84F466AB1F083F2600225386 /* Article.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Article.swift; sourceTree = "<group>"; };
84F466AD1F08435800225386 /* Author.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = "<group>"; };
84F466AF1F0862AF00225386 /* Attachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
84F466B11F0863D700225386 /* AccountDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountDelegate.swift; sourceTree = "<group>"; };
84F466B31F08725700225386 /* Folder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Folder.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
84C7AE8E1D68C558009FB883 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8439773E1DA07F2400F0FCBD /* RSCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
8439773C1DA07F2400F0FCBD /* Frameworks */ = {
isa = PBXGroup;
children = (
8439773D1DA07F2400F0FCBD /* RSCore.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
84C7AE881D68C558009FB883 = {
isa = PBXGroup;
children = (
84F466A51F08389400225386 /* Account.swift */,
84F466B11F0863D700225386 /* AccountDelegate.swift */,
84F466B31F08725700225386 /* Folder.swift */,
84F466A71F083A2A00225386 /* Feed.swift */,
84F466AB1F083F2600225386 /* Article.swift */,
84F466AD1F08435800225386 /* Author.swift */,
84F466AF1F0862AF00225386 /* Attachment.swift */,
8471A2C81ED4CEEE008F099E /* AccountProtocol.swift */,
8471A2CA1ED4CEEE008F099E /* ArticleStatusProtocol.swift */,
8471A2CB1ED4CEEE008F099E /* BatchUpdates.swift */,
8471A2D01ED4CEFA008F099E /* DisplayNameProviderProtocol.swift */,
84F466A91F083B7A00225386 /* OPMLRepresentable.swift */,
8471A2D21ED4CEFA008F099E /* Container.swift */,
8471A2D31ED4CEFA008F099E /* Notifications.swift */,
8471A2D41ED4CEFA008F099E /* UnreadCountProviderProtocol.swift */,
8471A2DA1ED4CF01008F099E /* Info.plist */,
84C7AE931D68C558009FB883 /* Products */,
8439773C1DA07F2400F0FCBD /* Frameworks */,
);
sourceTree = "<group>";
};
84C7AE931D68C558009FB883 /* Products */ = {
isa = PBXGroup;
children = (
84C7AE921D68C558009FB883 /* DataModel.framework */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
84C7AE8F1D68C558009FB883 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
84C7AE911D68C558009FB883 /* DataModel */ = {
isa = PBXNativeTarget;
buildConfigurationList = 84C7AE9A1D68C558009FB883 /* Build configuration list for PBXNativeTarget "DataModel" */;
buildPhases = (
84C7AE8D1D68C558009FB883 /* Sources */,
84C7AE8E1D68C558009FB883 /* Frameworks */,
84C7AE8F1D68C558009FB883 /* Headers */,
84C7AE901D68C558009FB883 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = DataModel;
productName = DataModel;
productReference = 84C7AE921D68C558009FB883 /* DataModel.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
84C7AE891D68C558009FB883 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = "Ranchero Software, LLC";
TargetAttributes = {
84C7AE911D68C558009FB883 = {
CreatedOnToolsVersion = 8.0;
LastSwiftMigration = 0800;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 84C7AE8C1D68C558009FB883 /* Build configuration list for PBXProject "DataModel" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 84C7AE881D68C558009FB883;
productRefGroup = 84C7AE931D68C558009FB883 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
84C7AE911D68C558009FB883 /* DataModel */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
84C7AE901D68C558009FB883 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
84C7AE8D1D68C558009FB883 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84F466AC1F083F2600225386 /* Article.swift in Sources */,
8471A2CC1ED4CEEE008F099E /* AccountProtocol.swift in Sources */,
84F466A81F083A2A00225386 /* Feed.swift in Sources */,
84F466A61F08389400225386 /* Account.swift in Sources */,
8471A2CF1ED4CEEE008F099E /* BatchUpdates.swift in Sources */,
8471A2CE1ED4CEEE008F099E /* ArticleStatusProtocol.swift in Sources */,
84F466B01F0862AF00225386 /* Attachment.swift in Sources */,
8471A2D91ED4CEFA008F099E /* UnreadCountProviderProtocol.swift in Sources */,
84F466B21F0863D700225386 /* AccountDelegate.swift in Sources */,
8471A2D51ED4CEFA008F099E /* DisplayNameProviderProtocol.swift in Sources */,
84F466AE1F08435800225386 /* Author.swift in Sources */,
84F466B41F08725700225386 /* Folder.swift in Sources */,
8471A2D81ED4CEFA008F099E /* Notifications.swift in Sources */,
84F466AA1F083B7A00225386 /* OPMLRepresentable.swift in Sources */,
8471A2D71ED4CEFA008F099E /* Container.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
84C7AE981D68C558009FB883 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
84C7AE991D68C558009FB883 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
84C7AE9B1D68C558009FB883 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DataModel;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
84C7AE9C1D68C558009FB883 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DataModel;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
84C7AE8C1D68C558009FB883 /* Build configuration list for PBXProject "DataModel" */ = {
isa = XCConfigurationList;
buildConfigurations = (
84C7AE981D68C558009FB883 /* Debug */,
84C7AE991D68C558009FB883 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
84C7AE9A1D68C558009FB883 /* Build configuration list for PBXNativeTarget "DataModel" */ = {
isa = XCConfigurationList;
buildConfigurations = (
84C7AE9B1D68C558009FB883 /* Debug */,
84C7AE9C1D68C558009FB883 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 84C7AE891D68C558009FB883 /* Project object */;
}

View File

@ -1,14 +0,0 @@
//
// Folder.swift
// DataModel
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public class Folder: Container {
}

View File

@ -0,0 +1,420 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
844BEE411F0AB3AB004AB7CD /* Database.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE371F0AB3AA004AB7CD /* Database.framework */; };
844BEE461F0AB3AB004AB7CD /* DatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */; };
844BEE481F0AB3AB004AB7CD /* Database.h in Headers */ = {isa = PBXBuildFile; fileRef = 844BEE3A1F0AB3AA004AB7CD /* Database.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
844BEE421F0AB3AB004AB7CD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 844BEE2E1F0AB3AA004AB7CD /* Project object */;
proxyType = 1;
remoteGlobalIDString = 844BEE361F0AB3AA004AB7CD;
remoteInfo = Database;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
844BEE371F0AB3AA004AB7CD /* Database.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Database.framework; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE3A1F0AB3AA004AB7CD /* Database.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = "<group>"; };
844BEE3B1F0AB3AA004AB7CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
844BEE401F0AB3AB004AB7CD /* DatabaseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DatabaseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseTests.swift; sourceTree = "<group>"; };
844BEE471F0AB3AB004AB7CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
844BEE331F0AB3AA004AB7CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE3D1F0AB3AB004AB7CD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE411F0AB3AB004AB7CD /* Database.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
844BEE2D1F0AB3AA004AB7CD = {
isa = PBXGroup;
children = (
844BEE391F0AB3AA004AB7CD /* Database */,
844BEE441F0AB3AB004AB7CD /* DatabaseTests */,
844BEE381F0AB3AA004AB7CD /* Products */,
);
sourceTree = "<group>";
};
844BEE381F0AB3AA004AB7CD /* Products */ = {
isa = PBXGroup;
children = (
844BEE371F0AB3AA004AB7CD /* Database.framework */,
844BEE401F0AB3AB004AB7CD /* DatabaseTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
844BEE391F0AB3AA004AB7CD /* Database */ = {
isa = PBXGroup;
children = (
844BEE3A1F0AB3AA004AB7CD /* Database.h */,
844BEE3B1F0AB3AA004AB7CD /* Info.plist */,
);
path = Database;
sourceTree = "<group>";
};
844BEE441F0AB3AB004AB7CD /* DatabaseTests */ = {
isa = PBXGroup;
children = (
844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */,
844BEE471F0AB3AB004AB7CD /* Info.plist */,
);
path = DatabaseTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
844BEE341F0AB3AA004AB7CD /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE481F0AB3AB004AB7CD /* Database.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
844BEE361F0AB3AA004AB7CD /* Database */ = {
isa = PBXNativeTarget;
buildConfigurationList = 844BEE4B1F0AB3AB004AB7CD /* Build configuration list for PBXNativeTarget "Database" */;
buildPhases = (
844BEE321F0AB3AA004AB7CD /* Sources */,
844BEE331F0AB3AA004AB7CD /* Frameworks */,
844BEE341F0AB3AA004AB7CD /* Headers */,
844BEE351F0AB3AA004AB7CD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Database;
productName = Database;
productReference = 844BEE371F0AB3AA004AB7CD /* Database.framework */;
productType = "com.apple.product-type.framework";
};
844BEE3F1F0AB3AB004AB7CD /* DatabaseTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 844BEE4E1F0AB3AB004AB7CD /* Build configuration list for PBXNativeTarget "DatabaseTests" */;
buildPhases = (
844BEE3C1F0AB3AB004AB7CD /* Sources */,
844BEE3D1F0AB3AB004AB7CD /* Frameworks */,
844BEE3E1F0AB3AB004AB7CD /* Resources */,
);
buildRules = (
);
dependencies = (
844BEE431F0AB3AB004AB7CD /* PBXTargetDependency */,
);
name = DatabaseTests;
productName = DatabaseTests;
productReference = 844BEE401F0AB3AB004AB7CD /* DatabaseTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
844BEE2E1F0AB3AA004AB7CD /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = "Ranchero Software";
TargetAttributes = {
844BEE361F0AB3AA004AB7CD = {
CreatedOnToolsVersion = 8.3.2;
DevelopmentTeam = 9C84TZ7Q6Z;
ProvisioningStyle = Automatic;
};
844BEE3F1F0AB3AB004AB7CD = {
CreatedOnToolsVersion = 8.3.2;
DevelopmentTeam = 9C84TZ7Q6Z;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 844BEE311F0AB3AA004AB7CD /* Build configuration list for PBXProject "Database" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 844BEE2D1F0AB3AA004AB7CD;
productRefGroup = 844BEE381F0AB3AA004AB7CD /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
844BEE361F0AB3AA004AB7CD /* Database */,
844BEE3F1F0AB3AB004AB7CD /* DatabaseTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
844BEE351F0AB3AA004AB7CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE3E1F0AB3AB004AB7CD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
844BEE321F0AB3AA004AB7CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
844BEE3C1F0AB3AB004AB7CD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
844BEE461F0AB3AB004AB7CD /* DatabaseTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
844BEE431F0AB3AB004AB7CD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 844BEE361F0AB3AA004AB7CD /* Database */;
targetProxy = 844BEE421F0AB3AB004AB7CD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
844BEE491F0AB3AB004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
844BEE4A1F0AB3AB004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
844BEE4C1F0AB3AB004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Database/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Database;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
844BEE4D1F0AB3AB004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = Database/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.Database;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
844BEE4F1F0AB3AB004AB7CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
INFOPLIST_FILE = DatabaseTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DatabaseTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
844BEE501F0AB3AB004AB7CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 9C84TZ7Q6Z;
INFOPLIST_FILE = DatabaseTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.DatabaseTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
844BEE311F0AB3AA004AB7CD /* Build configuration list for PBXProject "Database" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE491F0AB3AB004AB7CD /* Debug */,
844BEE4A1F0AB3AB004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
844BEE4B1F0AB3AB004AB7CD /* Build configuration list for PBXNativeTarget "Database" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE4C1F0AB3AB004AB7CD /* Debug */,
844BEE4D1F0AB3AB004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
};
844BEE4E1F0AB3AB004AB7CD /* Build configuration list for PBXNativeTarget "DatabaseTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
844BEE4F1F0AB3AB004AB7CD /* Debug */,
844BEE501F0AB3AB004AB7CD /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 844BEE2E1F0AB3AA004AB7CD /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Database.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,19 @@
//
// Database.h
// Database
//
// Created by Brent Simmons on 7/3/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
#import <Cocoa/Cocoa.h>
//! Project version number for Database.
FOUNDATION_EXPORT double DatabaseVersionNumber;
//! Project version string for Database.
FOUNDATION_EXPORT const unsigned char DatabaseVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Database/PublicHeader.h>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Ranchero Software. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,36 @@
//
// DatabaseTests.swift
// DatabaseTests
//
// Created by Brent Simmons on 7/3/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import XCTest
@testable import Database
class DatabaseTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -15,5 +15,5 @@ import Foundation
public protocol PlistProvider: class { public protocol PlistProvider: class {
var plist: AnyObject? {get} func plist() -> AnyObject?
} }