Update code formatting in some files in Account.framework.

This commit is contained in:
Brent Simmons 2019-07-08 22:58:19 -07:00
parent 1a03bcf03c
commit 21faa0ddc0
23 changed files with 52 additions and 139 deletions

View File

@ -1,6 +1,6 @@
//
// AccountError.swift
// Account
// NetNewsWire
//
// Created by Maurice Parker on 5/26/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
@ -65,5 +65,4 @@ public enum AccountError: LocalizedError {
let localizedText = NSLocalizedString("An error occurred while processing the \"%@\" account: %@", comment: "Unknown error")
return NSString.localizedStringWithFormat(localizedText as NSString, account.nameForDisplay, error.localizedDescription) as String
}
}

View File

@ -13,12 +13,9 @@ import Articles
// Main thread only.
public extension Notification.Name {
static let AccountsDidChange = Notification.Name(rawValue: "AccountsDidChange")
static let AccountsDidChange = Notification.Name("AccountsDidChange")
}
private let defaultAccountFolderName = "OnMyMac"
private let defaultAccountIdentifier = "OnMyMac"
public final class AccountManager: UnreadCountProvider {
public static let shared = AccountManager()
@ -27,6 +24,9 @@ public final class AccountManager: UnreadCountProvider {
private let accountsFolder = RSDataSubfolder(nil, "Accounts")!
private var accountsDictionary = [String: Account]()
private let defaultAccountFolderName = "OnMyMac"
private let defaultAccountIdentifier = "OnMyMac"
public var isUnreadCountsInitialized: Bool {
for account in activeAccounts {
if !account.isUnreadCountsInitialized {
@ -76,9 +76,7 @@ public final class AccountManager: UnreadCountProvider {
}
public init() {
// The local "On My Mac" account must always exist, even if it's empty.
let localAccountFolder = (accountsFolder as NSString).appendingPathComponent("OnMyMac")
do {
try FileManager.default.createDirectory(atPath: localAccountFolder, withIntermediateDirectories: true, attributes: nil)
@ -101,10 +99,9 @@ public final class AccountManager: UnreadCountProvider {
}
}
// MARK: API
// MARK: - API
public func createAccount(type: AccountType) -> Account {
let accountID = UUID().uuidString
let accountFolder = (accountsFolder as NSString).appendingPathComponent("\(type.rawValue)_\(accountID)")
@ -124,7 +121,6 @@ public final class AccountManager: UnreadCountProvider {
}
public func deleteAccount(_ account: Account) {
guard !account.refreshInProgress else {
return
}
@ -142,16 +138,13 @@ public final class AccountManager: UnreadCountProvider {
updateUnreadCount()
NotificationCenter.default.post(name: .AccountsDidChange, object: self)
}
public func existingAccount(with accountID: String) -> Account? {
return accountsDictionary[accountID]
}
public func refreshAll(errorHandler: @escaping (Error) -> Void) {
activeAccounts.forEach { account in
account.refreshAll() { result in
switch result {
@ -162,7 +155,6 @@ public final class AccountManager: UnreadCountProvider {
}
}
}
}
public func syncArticleStatusAll(completion: (() -> Void)? = nil) {
@ -181,7 +173,6 @@ public final class AccountManager: UnreadCountProvider {
}
public func anyAccountHasAtLeastOneFeed() -> Bool {
for account in activeAccounts {
if account.hasAtLeastOneFeed() {
return true
@ -192,7 +183,6 @@ public final class AccountManager: UnreadCountProvider {
}
public func anyAccountHasFeedWithURL(_ urlString: String) -> Bool {
for account in activeAccounts {
if let _ = account.existingFeed(withURL: urlString) {
return true
@ -200,11 +190,6 @@ public final class AccountManager: UnreadCountProvider {
}
return false
}
func updateUnreadCount() {
unreadCount = calculateUnreadCount(activeAccounts)
}
// MARK: - Fetching Articles
@ -238,10 +223,9 @@ public final class AccountManager: UnreadCountProvider {
}
}
// MARK: Notifications
// MARK: - Notifications
@objc dynamic func unreadCountDidChange(_ notification: Notification) {
guard let _ = notification.object as? Account else {
return
}
@ -251,15 +235,21 @@ public final class AccountManager: UnreadCountProvider {
@objc func accountStateDidChange(_ notification: Notification) {
updateUnreadCount()
}
// MARK: Private
}
private func loadAccount(_ accountSpecifier: AccountSpecifier) -> Account? {
// MARK: - Private
private extension AccountManager {
func updateUnreadCount() {
unreadCount = calculateUnreadCount(activeAccounts)
}
func loadAccount(_ accountSpecifier: AccountSpecifier) -> Account? {
return Account(dataFolder: accountSpecifier.folderPath, type: accountSpecifier.type, accountID: accountSpecifier.identifier)
}
private func loadAccount(_ filename: String) -> Account? {
func loadAccount(_ filename: String) -> Account? {
let folderPath = (accountsFolder as NSString).appendingPathComponent(filename)
if let accountSpecifier = AccountSpecifier(folderPath: folderPath) {
return loadAccount(accountSpecifier)
@ -267,8 +257,7 @@ public final class AccountManager: UnreadCountProvider {
return nil
}
private func readAccountsFromDisk() {
func readAccountsFromDisk() {
var filenames: [String]?
do {
@ -280,7 +269,6 @@ public final class AccountManager: UnreadCountProvider {
}
filenames?.forEach { (oneFilename) in
guard oneFilename != defaultAccountFolderName else {
return
}
@ -290,12 +278,10 @@ public final class AccountManager: UnreadCountProvider {
}
}
private func sortByName(_ accounts: [Account]) -> [Account] {
func sortByName(_ accounts: [Account]) -> [Account] {
// LocalAccount is first.
return accounts.sorted { (account1, account2) -> Bool in
if account1 === defaultAccount {
return true
}
@ -307,13 +293,6 @@ public final class AccountManager: UnreadCountProvider {
}
}
private let accountDataFileName = "AccountData.plist"
private func accountFilePathWithFolder(_ folderPath: String) -> String {
return NSString(string: folderPath).appendingPathComponent(accountDataFileName)
}
private struct AccountSpecifier {
let type: AccountType
@ -322,8 +301,8 @@ private struct AccountSpecifier {
let folderName: String
let dataFilePath: String
init?(folderPath: String) {
init?(folderPath: String) {
if !FileManager.default.rs_fileIsFolder(folderPath) {
return nil
}
@ -335,18 +314,21 @@ private struct AccountSpecifier {
let nameComponents = name.components(separatedBy: "_")
guard nameComponents.count == 2, let rawType = Int(nameComponents[0]), let acctType = AccountType(rawValue: rawType) else {
guard nameComponents.count == 2, let rawType = Int(nameComponents[0]), let accountType = AccountType(rawValue: rawType) else {
return nil
}
self.folderPath = folderPath
self.folderName = name
self.type = acctType
self.type = accountType
self.identifier = nameComponents[1]
self.dataFilePath = accountFilePathWithFolder(self.folderPath)
self.dataFilePath = AccountSpecifier.accountFilePathWithFolder(self.folderPath)
}
private static let accountDataFileName = "AccountData.plist"
private static func accountFilePathWithFolder(_ folderPath: String) -> String {
return NSString(string: folderPath).appendingPathComponent(accountDataFileName)
}
}

View File

@ -68,5 +68,4 @@ final class AccountMetadata: Codable {
func valueDidChange(_ key: CodingKeys) {
delegate?.valueDidChange(self, key: key)
}
}

View File

@ -1,6 +1,6 @@
//
// ArticleFetcher.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 2/4/18.
// Copyright © 2018 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// CombinedRefreshProgress.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 10/7/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
@ -20,7 +20,6 @@ public struct CombinedRefreshProgress {
public let isComplete: Bool
init(numberOfTasks: Int, numberRemaining: Int, numberCompleted: Int) {
self.numberOfTasks = max(numberOfTasks, 0)
self.numberRemaining = max(numberRemaining, 0)
self.numberCompleted = max(numberCompleted, 0)
@ -28,7 +27,6 @@ public struct CombinedRefreshProgress {
}
public init(downloadProgressArray: [DownloadProgress]) {
var numberOfTasks = 0
var numberRemaining = 0
var numberCompleted = 0

View File

@ -76,7 +76,6 @@ public extension Container {
}
func flattenedFeeds() -> Set<Feed> {
var feeds = Set<Feed>()
feeds.formUnion(topLevelFeeds)
if let folders = folders {

View File

@ -1,6 +1,6 @@
//
// ContainerPath.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 11/4/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
@ -22,7 +22,6 @@ public struct ContainerPath {
// folders should be from top-level down, as in ["Cats", "Tabbies"]
public init(account: Account, folders: [Folder]) {
self.account = account
self.names = folders.map { $0.nameForDisplay }
self.isTopLevel = folders.isEmpty
@ -31,7 +30,6 @@ public struct ContainerPath {
}
public func resolveContainer() -> Container? {
// The only time it should fail is if the account no longer exists.
// Otherwise the worst-case scenario is that it will create Folders if needed.

View File

@ -1,6 +1,6 @@
//
// DataExtensions.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 10/7/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// Feed.swift
// DataModel
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// FeedFinder.swift
// FeedFinder
// NetNewsWire
//
// Created by Brent Simmons on 8/2/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
@ -14,9 +14,7 @@ import RSCore
class FeedFinder {
static func find(url: URL, completion: @escaping (Result<Set<FeedSpecifier>, Error>) -> Void) {
downloadUsingCache(url) { (data, response, error) in
if response?.forcedStatusCode == 404 {
completion(.failure(AccountError.createErrorNotFound))
return
@ -49,17 +47,13 @@ class FeedFinder {
}
FeedFinder.findFeedsInHTMLPage(htmlData: data, urlString: url.absoluteString, completion: completion)
}
}
}
private extension FeedFinder {
static func addFeedSpecifier(_ feedSpecifier: FeedSpecifier, feedSpecifiers: inout [String: FeedSpecifier]) {
// If theres an existing feed specifier, merge the two so that we have the best data. If one has a title and one doesnt, use that non-nil title. Use the better source.
if let existingFeedSpecifier = feedSpecifiers[feedSpecifier.urlString] {
@ -72,7 +66,6 @@ private extension FeedFinder {
}
static func findFeedsInHTMLPage(htmlData: Data, urlString: String, completion: @escaping (Result<Set<FeedSpecifier>, Error>) -> Void) {
// Feeds in the <head> section we automatically assume are feeds.
// If there are none from the <head> section,
// then possible feeds in <body> section are downloaded individually
@ -99,16 +92,17 @@ private extension FeedFinder {
if didFindFeedInHTMLHead {
completion(.success(Set(feedSpecifiers.values)))
return
} else if feedSpecifiersToDownload.isEmpty {
}
else if feedSpecifiersToDownload.isEmpty {
completion(.failure(AccountError.createErrorNotFound))
return
} else {
}
else {
downloadFeedSpecifiers(feedSpecifiersToDownload, feedSpecifiers: feedSpecifiers, completion: completion)
}
}
static func possibleFeedsInHTMLPage(htmlData: Data, urlString: String) -> Set<FeedSpecifier> {
let parserData = ParserData(url: urlString, data: htmlData)
var feedSpecifiers = HTMLFeedFinder(parserData: parserData).feedSpecifiers
@ -139,7 +133,6 @@ private extension FeedFinder {
let group = DispatchGroup()
for downloadFeedSpecifier in downloadFeedSpecifiers {
guard let url = URL(string: downloadFeedSpecifier.urlString) else {
continue
}
@ -159,12 +152,10 @@ private extension FeedFinder {
group.notify(queue: DispatchQueue.main) {
completion(.success(Set(resultFeedSpecifiers.values)))
}
}
static func isFeed(_ data: Data, _ urlString: String) -> Bool {
let parserData = ParserData(url: urlString, data: data)
return FeedParser.canParse(parserData)
}
}

View File

@ -1,6 +1,6 @@
//
// FeedSpecifier.swift
// FeedFinder
// NetNewsWire
//
// Created by Brent Simmons on 8/7/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
@ -11,11 +11,9 @@ import Foundation
struct FeedSpecifier: Hashable {
enum Source: Int {
case UserEntered = 0, HTMLHead, HTMLLink
func equalToOrBetterThan(_ otherSource: Source) -> Bool {
return self.rawValue <= otherSource.rawValue
}
}
@ -28,7 +26,6 @@ struct FeedSpecifier: Hashable {
}
func feedSpecifierByMerging(_ feedSpecifier: FeedSpecifier) -> FeedSpecifier {
// Take the best data (non-nil title, better source) to create a new feed specifier;
let mergedTitle = title ?? feedSpecifier.title
@ -38,7 +35,6 @@ struct FeedSpecifier: Hashable {
}
public static func bestFeed(in feedSpecifiers: Set<FeedSpecifier>) -> FeedSpecifier? {
if feedSpecifiers.isEmpty {
return nil
}
@ -64,7 +60,6 @@ struct FeedSpecifier: Hashable {
private extension FeedSpecifier {
func calculatedScore() -> Int {
var score = 0
if source == .UserEntered {

View File

@ -1,6 +1,6 @@
//
// HTMLFeedFinder.swift
// FeedFinder
// NetNewsWire
//
// Created by Brent Simmons on 8/7/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
@ -20,7 +20,6 @@ class HTMLFeedFinder {
private var feedSpecifiersDictionary = [String: FeedSpecifier]()
init(parserData: ParserData) {
let metadata = RSHTMLMetadataParser.htmlMetadata(with: parserData)
for oneFeedLink in metadata.feedLinks {
@ -46,7 +45,6 @@ class HTMLFeedFinder {
private extension HTMLFeedFinder {
func addFeedSpecifier(_ feedSpecifier: FeedSpecifier) {
// If theres an existing feed specifier, merge the two so that we have the best data. If one has a title and one doesnt, use that non-nil title. Use the better source.
if let existingFeedSpecifier = feedSpecifiersDictionary[feedSpecifier.urlString] {
@ -59,7 +57,6 @@ private extension HTMLFeedFinder {
}
func urlStringMightBeFeed(_ urlString: String) -> Bool {
let massagedURLString = urlString.replacingOccurrences(of: "buzzfeed", with: "_")
for oneMatch in feedURLWordsToMatch {
@ -73,7 +70,6 @@ private extension HTMLFeedFinder {
}
func linkMightBeFeed(_ link: RSHTMLLink) -> Bool {
if let linkURLString = link.urlString, urlStringMightBeFeed(linkURLString) {
return true
}

View File

@ -1,6 +1,6 @@
//
// FeedMetadata.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 3/12/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
@ -128,5 +128,4 @@ final class FeedMetadata: Codable {
func valueDidChange(_ key: CodingKeys) {
delegate?.valueDidChange(self, key: key)
}
}

View File

@ -1,6 +1,6 @@
//
// Folder.swift
// DataModel
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
@ -52,7 +52,6 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun
// MARK: - Init
init(account: Account, name: String?) {
self.account = account
self.name = name
@ -67,7 +66,6 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun
// MARK: - Notifications
@objc func unreadCountDidChange(_ note: Notification) {
if let object = note.object {
if objectIsChild(object as AnyObject) {
updateUnreadCount()
@ -76,7 +74,6 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun
}
@objc func childrenDidChange(_ note: Notification) {
updateUnreadCount()
}
@ -114,7 +111,6 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun
// MARK: - Equatable
static public func ==(lhs: Folder, rhs: Folder) -> Bool {
return lhs === rhs
}
}
@ -141,7 +137,6 @@ private extension Folder {
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)

View File

@ -15,7 +15,6 @@ struct InitialFeedDownloader {
static func download(_ url: URL,_ completionHandler: @escaping (_ parsedFeed: ParsedFeed?) -> Void) {
downloadUsingCache(url) { (data, response, error) in
guard let data = data else {
completionHandler(nil)
return

View File

@ -1,6 +1,6 @@
//
// LocalAccountDelegate.swift
// Account
// NetNewsWire
//
// Created by Brent Simmons on 9/16/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
@ -47,7 +47,6 @@ final class LocalAccountDelegate: AccountDelegate {
}
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
var fileData: Data?
do {
@ -87,7 +86,6 @@ final class LocalAccountDelegate: AccountDelegate {
}
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, completion: @escaping (Result<Feed, Error>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(LocalAccountDelegateError.invalidParameter))
return
@ -98,8 +96,6 @@ final class LocalAccountDelegate: AccountDelegate {
switch result {
case .success(let feedSpecifiers):
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers),
let url = URL(string: bestFeedSpecifier.urlString) else {
self.refreshProgress.completeTask()
@ -116,7 +112,6 @@ final class LocalAccountDelegate: AccountDelegate {
let feed = account.createFeed(with: nil, url: url.absoluteString, feedID: url.absoluteString, homePageURL: nil)
InitialFeedDownloader.download(url) { parsedFeed in
self.refreshProgress.completeTask()
if let parsedFeed = parsedFeed {
@ -198,5 +193,4 @@ final class LocalAccountDelegate: AccountDelegate {
static func validateCredentials(transport: Transport, credentials: Credentials, completion: (Result<Bool, Error>) -> Void) {
return completion(.success(false))
}
}

View File

@ -1,6 +1,6 @@
//
// LocalAccountRefresher.swift
// LocalAccount
// NetNewsWire
//
// Created by Brent Simmons on 9/6/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
@ -23,7 +23,6 @@ final class LocalAccountRefresher {
}
public func refreshFeeds(_ feeds: Set<Feed>) {
downloadSession.downloadObjects(feeds as NSSet)
}
}
@ -33,11 +32,9 @@ final class LocalAccountRefresher {
extension LocalAccountRefresher: DownloadSessionDelegate {
func downloadSession(_ downloadSession: DownloadSession, requestForRepresentedObject representedObject: AnyObject) -> URLRequest? {
guard let feed = representedObject as? Feed else {
return nil
}
guard let url = URL(string: feed.url) else {
return nil
}
@ -51,7 +48,6 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
}
func downloadSession(_ downloadSession: DownloadSession, downloadDidCompleteForRepresentedObject representedObject: AnyObject, response: URLResponse?, data: Data, error: NSError?) {
guard let feed = representedObject as? Feed, !data.isEmpty else {
return
}
@ -63,18 +59,15 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
let dataHash = (data as NSData).rs_md5HashString()
if dataHash == feed.contentHash {
// print("Hashed content of \(feed.url) has not changed.")
return
}
let parserData = ParserData(url: feed.url, data: data)
FeedParser.parse(parserData) { (parsedFeed, error) in
guard let account = feed.account, let parsedFeed = parsedFeed, error == nil else {
return
}
account.update(feed, with: parsedFeed) {
if let httpResponse = response as? HTTPURLResponse {
feed.conditionalGetInfo = HTTPConditionalGetInfo(urlResponse: httpResponse)
}
@ -85,7 +78,6 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
}
func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData data: Data, representedObject: AnyObject) -> Bool {
guard let feed = representedObject as? Feed else {
return false
}
@ -106,21 +98,9 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
}
func downloadSession(_ downloadSession: DownloadSession, didReceiveUnexpectedResponse response: URLResponse, representedObject: AnyObject) {
// guard let feed = representedObject as? Feed else {
// return
// }
//
// print("Unexpected response \(response) for \(feed.url).")
}
func downloadSession(_ downloadSession: DownloadSession, didReceiveNotModifiedResponse: URLResponse, representedObject: AnyObject) {
// guard let feed = representedObject as? Feed else {
// return
// }
//
// print("Not modified response for \(feed.url).")
}
}
@ -129,7 +109,6 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
private extension Data {
func isDefinitelyNotFeed() -> Bool {
// We only detect a few image types for now. This should get fleshed-out at some later date.
return (self as NSData).rs_dataIsImage()
}

View File

@ -25,12 +25,10 @@ public protocol UnreadCountProvider {
public extension UnreadCountProvider {
func postUnreadCountDidChangeNotification() {
NotificationCenter.default.post(name: .UnreadCountDidChange, object: self, userInfo: nil)
}
func calculateUnreadCount<T: Collection>(_ children: T) -> Int {
let updatedUnreadCount = children.reduce(0) { (result, oneChild) -> Int in
if let oneUnreadCountProvider = oneChild as? UnreadCountProvider {
return result + oneUnreadCountProvider.unreadCount

View File

@ -1,6 +1,6 @@
//
// Article.swift
// Data
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// ArticleStatus.swift
// DataModel
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
@ -30,7 +30,6 @@ public final class ArticleStatus: Hashable {
public var userDeleted = false
public init(articleID: String, read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date) {
self.articleID = articleID
self.read = read
self.starred = starred
@ -39,12 +38,10 @@ public final class ArticleStatus: Hashable {
}
public convenience init(articleID: String, read: Bool, dateArrived: Date) {
self.init(articleID: articleID, read: read, starred: false, userDeleted: false, dateArrived: dateArrived)
}
public func boolStatus(forKey key: ArticleStatus.Key) -> Bool {
switch key {
case .read:
return read
@ -56,7 +53,6 @@ public final class ArticleStatus: Hashable {
}
public func setBoolStatus(_ status: Bool, forKey key: ArticleStatus.Key) {
switch key {
case .read:
read = status
@ -76,7 +72,6 @@ public final class ArticleStatus: Hashable {
// MARK: - Equatable
public static func ==(lhs: ArticleStatus, rhs: ArticleStatus) -> Bool {
return lhs.articleID == rhs.articleID && lhs.dateArrived == rhs.dateArrived && lhs.read == rhs.read && lhs.starred == rhs.starred && lhs.userDeleted == rhs.userDeleted
}
}
@ -84,15 +79,13 @@ public final class ArticleStatus: Hashable {
public extension Set where Element == ArticleStatus {
func articleIDs() -> Set<String> {
return Set<String>(map { $0.articleID })
}
}
public extension Array where Element == ArticleStatus {
func articleIDs() -> [String] {
func articleIDs() -> [String] {
return map { $0.articleID }
}
}

View File

@ -1,6 +1,6 @@
//
// Attachment.swift
// DataModel
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// Author.swift
// DataModel
// NetNewsWire
//
// Created by Brent Simmons on 7/1/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.

View File

@ -1,6 +1,6 @@
//
// DatabaseID.swift
// Data
// NetNewsWire
//
// Created by Brent Simmons on 7/15/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
@ -17,7 +17,6 @@ private var databaseIDCache = [String: String]()
private var databaseIDCacheLock = os_unfair_lock_s()
public func databaseIDWithString(_ s: String) -> String {
os_unfair_lock_lock(&databaseIDCacheLock)
defer {
os_unfair_lock_unlock(&databaseIDCacheLock)