Remove use of forEach.

This commit is contained in:
Brent Simmons 2024-11-18 15:11:18 -08:00
parent c1c4c8b1b6
commit ba0a2d3521
25 changed files with 156 additions and 98 deletions

View File

@ -491,9 +491,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
} else {
if let title = item.titleFromAttributes, let folder = ensureFolder(with: title) {
folder.externalID = item.attributes?["nnw_externalID"] as? String
item.items?.forEach { itemChild in
if let feedSpecifier = itemChild.feedSpecifier {
folder.addFeed(newFeed(with: feedSpecifier))
if let items = item.items {
for itemChild in items {
if let feedSpecifier = itemChild.feedSpecifier {
folder.addFeed(newFeed(with: feedSpecifier))
}
}
}
}
@ -521,9 +523,11 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
if topLevelFeeds.contains(feed) {
containers.append(self)
}
folders?.forEach { folder in
if folder.topLevelFeeds.contains(feed) {
containers.append(folder)
if let folders {
for folder in folders {
if folder.topLevelFeeds.contains(feed) {
containers.append(folder)
}
}
}
return containers
@ -925,7 +929,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
public func debugDropConditionalGetInfo() {
#if DEBUG
flattenedFeeds().forEach{ $0.dropConditionalGetInfo() }
for feed in flattenedFeeds() {
feed.dropConditionalGetInfo()
}
#endif
}
@ -1169,7 +1175,7 @@ private extension Account {
for article in articles where !article.status.read {
unreadCountStorage[article.feedID, default: 0] += 1
}
feeds.forEach { (feed) in
for feed in feeds {
let unreadCount = unreadCountStorage[feed.feedID, default: 0]
feed.unreadCount = unreadCount
}
@ -1220,7 +1226,7 @@ private extension Account {
var idDictionary = [String: Feed]()
var externalIDDictionary = [String: Feed]()
flattenedFeeds().forEach { (feed) in
for feed in flattenedFeeds() {
idDictionary[feed.feedID] = feed
if let externalID = feed.externalID {
externalIDDictionary[externalID] = feed

View File

@ -215,23 +215,31 @@ public final class AccountManager: UnreadCountProvider {
public func suspendNetworkAll() {
isSuspended = true
accounts.forEach { $0.suspendNetwork() }
for account in accounts {
account.suspendNetwork()
}
}
public func suspendDatabaseAll() {
accounts.forEach { $0.suspendDatabase() }
for account in accounts {
account.suspendDatabase()
}
}
public func resumeAll() {
isSuspended = false
accounts.forEach { $0.resumeDatabaseAndDelegate() }
accounts.forEach { $0.resume() }
for account in accounts {
account.resumeDatabaseAndDelegate()
}
for account in accounts {
account.resume()
}
}
public func receiveRemoteNotification(userInfo: [AnyHashable : Any], completion: (() -> Void)? = nil) {
let group = DispatchGroup()
activeAccounts.forEach { account in
for account in activeAccounts {
group.enter()
account.receiveRemoteNotification(userInfo: userInfo) {
group.leave()
@ -248,7 +256,7 @@ public final class AccountManager: UnreadCountProvider {
let group = DispatchGroup()
activeAccounts.forEach { account in
for account in activeAccounts {
group.enter()
account.refreshAll() { result in
group.leave()
@ -272,7 +280,7 @@ public final class AccountManager: UnreadCountProvider {
var syncErrors = [AccountSyncError]()
let group = DispatchGroup()
activeAccounts.forEach { account in
for account in activeAccounts {
group.enter()
account.refreshAll() { result in
group.leave()
@ -297,9 +305,9 @@ public final class AccountManager: UnreadCountProvider {
public func sendArticleStatusAll(completion: (() -> Void)? = nil) {
let group = DispatchGroup()
activeAccounts.forEach {
for account in activeAccounts {
group.enter()
$0.sendArticleStatus() { _ in
account.sendArticleStatus() { _ in
group.leave()
}
}
@ -312,9 +320,9 @@ public final class AccountManager: UnreadCountProvider {
public func syncArticleStatusAll(completion: (() -> Void)? = nil) {
let group = DispatchGroup()
activeAccounts.forEach {
for account in activeAccounts {
group.enter()
$0.syncArticleStatus() { _ in
account.syncArticleStatus() { _ in
group.leave()
}
}
@ -325,7 +333,9 @@ public final class AccountManager: UnreadCountProvider {
}
public func saveAll() {
accounts.forEach { $0.save() }
for account in accounts {
account.save()
}
}
public func anyAccountHasAtLeastOneFeed() -> Bool {
@ -481,13 +491,15 @@ private extension AccountManager {
filenames = filenames?.sorted()
filenames?.forEach { (oneFilename) in
guard oneFilename != defaultAccountFolderName else {
return
}
if let oneAccount = loadAccount(oneFilename) {
if !duplicateServiceAccount(oneAccount) {
accountsDictionary[oneAccount.accountID] = oneAccount
if let filenames {
for oneFilename in filenames {
guard oneFilename != defaultAccountFolderName else {
continue
}
if let oneAccount = loadAccount(oneFilename) {
if !duplicateServiceAccount(oneAccount) {
accountsDictionary[oneAccount.accountID] = oneAccount
}
}
}
}

View File

@ -77,9 +77,11 @@ final class CloudKitAccountZone: CloudKitZone {
if let title = item.titleFromAttributes {
let containerRecord = newContainerCKRecord(name: title)
records.append(containerRecord)
item.items?.forEach { itemChild in
if let feedSpecifier = itemChild.feedSpecifier {
processFeed(feedSpecifier: feedSpecifier, containerExternalID: containerRecord.externalID)
if let items = item.items {
for itemChild in items {
if let feedSpecifier = itemChild.feedSpecifier {
processFeed(feedSpecifier: feedSpecifier, containerExternalID: containerRecord.externalID)
}
}
}
}

View File

@ -84,9 +84,9 @@ class CloudKitAcountZoneDelegate: CloudKitZoneDelegate {
func removeFeed(_ externalID: String) {
if let feed = account?.existingFeed(withExternalID: externalID), let containers = account?.existingContainers(withFeed: feed) {
containers.forEach {
for container in containers {
feed.dropConditionalGetInfo()
$0.removeFeed(feed)
container.removeFeed(feed)
}
}
}

View File

@ -38,7 +38,9 @@ final class FeedMetadataFile {
let decoder = PropertyListDecoder()
account.feedMetadata = (try? decoder.decode(Account.FeedMetadataDictionary.self, from: fileData)) ?? Account.FeedMetadataDictionary()
}
account.feedMetadata.values.forEach { $0.delegate = account }
for value in account.feedMetadata.values {
value.delegate = account
}
}
func save() {

View File

@ -761,7 +761,7 @@ private extension FeedbinAccountDelegate {
// Feedbin has a tag that we don't have a folder for. We might not get a new
// taggings response for it if it is a folder rename. Force expire the tagging
// so that we will for sure get the new tagging information.
tags.forEach { tag in
for tag in tags {
if !folderNames.contains(tag.name) {
accountMetadata?.conditionalGetInfo[FeedbinAPICaller.ConditionalGetKeys.taggings] = nil
}
@ -779,7 +779,7 @@ private extension FeedbinAccountDelegate {
// Delete any folders not at Feedbin
if let folders = account.folders {
folders.forEach { folder in
for folder in folders {
if !tagNames.contains(folder.name ?? "") {
for feed in folder.topLevelFeeds {
account.addFeed(feed)
@ -799,7 +799,7 @@ private extension FeedbinAccountDelegate {
}()
// Make any folders Feedbin has, but we don't
tagNames.forEach { tagName in
for tagName in tagNames {
if !folderNames.contains(tagName) {
_ = account.ensureFolder(with: tagName)
}
@ -835,7 +835,7 @@ private extension FeedbinAccountDelegate {
// Add any feeds we don't have and update any we do
var subscriptionsToAdd = Set<FeedbinSubscription>()
subscriptions.forEach { subscription in
for subscription in subscriptions {
let subFeedId = String(subscription.feedID)
@ -854,7 +854,7 @@ private extension FeedbinAccountDelegate {
}
// Actually add subscriptions all in one go, so we dont trigger various rebuilding things that Account does.
subscriptionsToAdd.forEach { subscription in
for subscription in subscriptionsToAdd {
let feed = account.createFeed(with: subscription.name, url: subscription.url, feedID: String(subscription.feedID), homePageURL: subscription.homePageURL)
feed.externalID = String(subscription.subscriptionID)
account.addFeed(feed)

View File

@ -95,7 +95,7 @@ final class FeedlyCreateFeedsForCollectionFoldersOperation: FeedlyOperation {
}
os_log(.debug, log: log, "Processing %i feeds.", feedsAndFolders.count)
feedsAndFolders.forEach { (feed, folder) in
for (feed, folder) in feedsAndFolders {
if !folder.has(feed) {
folder.addFeed(feed)
}

View File

@ -46,7 +46,7 @@ extension NewsBlurAccountDelegate {
// Delete any folders not at NewsBlur
if let folders = account.folders {
folders.forEach { folder in
for folder in folders {
if !folderNames.contains(folder.name ?? "") {
for feed in folder.topLevelFeeds {
account.addFeed(feed)
@ -67,7 +67,7 @@ extension NewsBlurAccountDelegate {
// Make any folders NewsBlur has, but we don't
// Ignore account-level folder
folderNames.forEach { folderName in
for folderName in folderNames {
if !accountFolderNames.contains(folderName) && folderName != " " {
_ = account.ensureFolder(with: folderName)
}
@ -118,8 +118,8 @@ extension NewsBlurAccountDelegate {
}
// Actually add feeds all in one go, so we dont trigger various rebuilding things that Account does.
feedsToAdd.forEach { feed in
let feed = account.createFeed(with: feed.name, url: feed.feedURL, feedID: String(feed.feedID), homePageURL: feed.homePageURL)
for feedToAdd in feedsToAdd {
let feed = account.createFeed(with: feedToAdd.name, url: feedToAdd.feedURL, feedID: String(feedToAdd.feedID), homePageURL: feedToAdd.homePageURL)
feed.externalID = String(feed.feedID)
account.addFeed(feed)
}

View File

@ -22,13 +22,13 @@ final class OPMLNormalizer {
private func normalize(_ items: [OPMLItem], parentFolder: OPMLItem? = nil) {
var feedsToAdd = [OPMLItem]()
items.forEach { (item) in
for item in items {
if let _ = item.feedSpecifier {
if !feedsToAdd.contains(where: { $0.feedSpecifier?.feedURL == item.feedSpecifier?.feedURL }) {
feedsToAdd.append(item)
}
return
continue
}
guard let _ = item.titleFromAttributes else {
@ -36,7 +36,7 @@ final class OPMLNormalizer {
if let itemChildren = item.items {
normalize(itemChildren, parentFolder: parentFolder)
}
return
continue
}
feedsToAdd.append(item)
@ -60,7 +60,5 @@ final class OPMLNormalizer {
normalizedOPMLItems.append(feed)
}
}
}
}

View File

@ -718,7 +718,7 @@ private extension ReaderAPIAccountDelegate {
// Delete any folders not at Reader
if let folders = account.folders {
folders.forEach { folder in
for folder in folders {
if !readerFolderExternalIDs.contains(folder.externalID ?? "") {
for feed in folder.topLevelFeeds {
account.addFeed(feed)
@ -738,7 +738,7 @@ private extension ReaderAPIAccountDelegate {
}()
// Make any folders Reader has, but we don't
folderTags.forEach { tag in
for tag in folderTags {
if !folderExternalIDs.contains(tag.tagID) {
let folder = account.ensureFolder(with: tag.folderName ?? "None")
folder?.externalID = tag.tagID
@ -775,8 +775,8 @@ private extension ReaderAPIAccountDelegate {
}
// Add any feeds we don't have and update any we do
subscriptions.forEach { subscription in
for subscription in subscriptions {
if let feed = account.existingFeed(withFeedID: subscription.feedID) {
feed.name = subscription.name
feed.editedName = nil
@ -801,14 +801,14 @@ private extension ReaderAPIAccountDelegate {
let taggingsDict = subscriptions.reduce([String: [ReaderAPISubscription]]()) { (dict, subscription) in
var taggedFeeds = dict
subscription.categories.forEach({ (category) in
for category in subscription.categories {
if var taggedFeed = taggedFeeds[category.categoryId] {
taggedFeed.append(subscription)
taggedFeeds[category.categoryId] = taggedFeed
} else {
taggedFeeds[category.categoryId] = [subscription]
}
})
}
return taggedFeeds
}

View File

@ -132,7 +132,9 @@ final class SearchTable: DatabaseTable {
private extension SearchTable {
func performInitialIndexForArticles(_ articles: Set<ArticleSearchInfo>, _ database: FMDatabase) {
articles.forEach { performInitialIndex($0, database) }
for article in articles {
performInitialIndex(article, database)
}
}
func performInitialIndex(_ article: ArticleSearchInfo, _ database: FMDatabase) {
@ -177,7 +179,7 @@ private extension SearchTable {
let groupedSearchInfos = Dictionary(grouping: searchInfos, by: { $0.rowID })
let searchInfosDictionary = groupedSearchInfos.mapValues { $0.first! }
articles.forEach { (article) in
for article in articles {
updateIndexForArticle(article, searchInfosDictionary, database)
}
}

View File

@ -59,7 +59,9 @@ struct QueueCall: Equatable {
guard !isPaused else { return }
let callsToMake = calls // Make a copy in case calls are added to the queue while performing calls.
resetCalls()
callsToMake.forEach { $0.perform() }
for call in callsToMake {
call.perform()
}
}
@objc func timerDidFire(_ sender: Any?) {

View File

@ -68,7 +68,9 @@ public final class MainThreadOperationQueue {
/// Add multiple operations to the queue.
/// This has the same effect as calling addOperation one-by-one.
public func addOperations(_ operations: [MainThreadOperation]) {
operations.forEach{ add($0) }
for operation in operations {
add(operation)
}
}
/// Add a dependency. Do this *before* calling addOperation, since addOperation might run the operation right away.
@ -453,16 +455,22 @@ private extension MainThreadOperationDependencies {
}
func removeDependencies(_ parentOperationIDs: [Int]) {
parentOperationIDs.forEach { dependencies[$0] = nil }
for parentOperationID in parentOperationIDs {
dependencies[parentOperationID] = nil
}
}
func removeChildOperationIDs(_ operationIDs: [Int]) {
operationIDs.forEach{ removeChildOperationID($0) }
for operationID in operationIDs {
removeChildOperationID(operationID)
}
removeEmptyDependencies()
}
func removeChildOperationID(_ operationID: Int) {
dependencies.values.forEach{ $0.remove(operationID) }
for value in dependencies.values {
value.remove(operationID)
}
}
func removeEmptyDependencies() {

View File

@ -67,10 +67,12 @@ public extension UndoableCommandRunner {
// Otherwise things like Redo Mark Read are ambiguous.
// (Do they apply to the previous articles or to the current articles?)
guard let undoManager = undoManager else {
guard let undoManager else {
return
}
undoableCommands.forEach { undoManager.removeAllActions(withTarget: $0) }
for undoableCommand in undoableCommands {
undoManager.removeAllActions(withTarget: undoableCommand)
}
undoableCommands = [UndoableCommand]()
}
}

View File

@ -19,8 +19,12 @@ extension UIViewController {
}
public func replaceChildAndPinView(_ controller: UIViewController) {
view.subviews.forEach { $0.removeFromSuperview() }
children.forEach { $0.removeFromParent() }
for subview in view.subviews {
subview.removeFromSuperview()
}
for child in children {
child.removeFromParent()
}
addChildAndPinView(controller)
}

View File

@ -62,7 +62,7 @@ public extension DatabaseTable {
func insertRows(_ dictionaries: [DatabaseDictionary], insertType: RSDatabaseInsertType, in database: FMDatabase) {
dictionaries.forEach { (oneDictionary) in
for oneDictionary in dictionaries {
let _ = database.rs_insertRow(with: oneDictionary, insertType: insertType, tableName: self.name)
}
}

View File

@ -89,7 +89,7 @@ private extension TreeController {
func visitNode(_ node: Node, _ visitBlock: NodeVisitBlock) {
visitBlock(node)
node.childNodes.forEach{ (oneChildNode) in
for oneChildNode in node.childNodes {
visitNode(oneChildNode, visitBlock)
}
}
@ -124,7 +124,7 @@ private extension TreeController {
node.childNodes = childNodes
}
childNodes.forEach{ (oneChildNode) in
for oneChildNode in childNodes {
if rebuildChildNodes(node: oneChildNode) {
childNodesDidChange = true
}

View File

@ -64,9 +64,15 @@ public protocol DownloadSessionDelegate {
public func cancelAll() {
urlSession.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
dataTasks.forEach { $0.cancel() }
uploadTasks.forEach { $0.cancel() }
downloadTasks.forEach { $0.cancel() }
for dataTask in dataTasks {
dataTask.cancel()
}
for uploadTask in uploadTasks {
uploadTask.cancel()
}
for downloadTask in downloadTasks {
downloadTask.cancel()
}
}
}

View File

@ -28,11 +28,11 @@ public struct HTTPLinkPagingInfo {
let links = linkHeader.components(separatedBy: ",")
var dict: [String: String] = [:]
links.forEach({
let components = $0.components(separatedBy:"; ")
for link in links {
let components = link.components(separatedBy:"; ")
let page = components[0].trimmingCharacters(in: CharacterSet(charactersIn: " <>"))
dict[components[1]] = page
})
}
self.init(nextPage: dict["rel=\"next\""], lastPage: dict["rel=\"last\""])

View File

@ -88,7 +88,7 @@ private final class WebCache {
func cleanup(_ cleanupInterval: TimeInterval) {
let cutoffDate = Date(timeInterval: -cleanupInterval, since: Date())
cache.keys.forEach { (key) in
for key in cache.keys {
let cacheRecord = self[key]!
if shouldDelete(cacheRecord, cutoffDate) {
cache[key] = nil
@ -168,7 +168,7 @@ private final class DownloadWithCacheManager {
}
var callbackCount = 0
self.pendingCallbacks.forEach{ (callbackRecord) in
for callbackRecord in self.pendingCallbacks {
if url == callbackRecord.url {
callbackRecord.completion(data, response, error)
callbackCount += 1

View File

@ -134,9 +134,15 @@ extension URLSession: Transport {
public func cancelAll() {
getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
dataTasks.forEach { $0.cancel() }
uploadTasks.forEach { $0.cancel() }
downloadTasks.forEach { $0.cancel() }
for dataTask in dataTasks {
dataTask.cancel()
}
for uploadTask in uploadTasks {
uploadTask.cancel()
}
for downloadTask in downloadTasks {
downloadTask.cancel()
}
}
}

View File

@ -66,7 +66,7 @@ final class SmartFeed: PseudoFeed {
// Remove any accounts that are no longer active or have been deleted
let activeAccountIDs = activeAccounts.map { $0.accountID }
unreadCounts.keys.forEach { accountID in
for accountID in unreadCounts.keys {
if !activeAccountIDs.contains(accountID) {
unreadCounts.removeValue(forKey: accountID)
}
@ -75,7 +75,9 @@ final class SmartFeed: PseudoFeed {
if activeAccounts.isEmpty {
updateUnreadCount()
} else {
activeAccounts.forEach { self.fetchUnreadCount(for: $0) }
for account in activeAccounts {
self.fetchUnreadCount(for: account)
}
}
}

View File

@ -24,7 +24,9 @@ final class FetchRequestQueue {
func cancelAllRequests() {
precondition(Thread.isMainThread)
pendingRequests.forEach { $0.isCanceled = true }
for request in pendingRequests {
request.isCanceled = true
}
currentRequest?.isCanceled = true
pendingRequests = [FetchRequestOperation]()
}

View File

@ -82,12 +82,12 @@ private extension FeedTreeControllerDelegate {
var updatedChildNodes = [Node]()
children.forEach { (representedObject) in
for representedObject in children {
if let existingNode = containerNode.childNodeRepresentingObject(representedObject) {
if !updatedChildNodes.contains(existingNode) {
updatedChildNodes += [existingNode]
return
continue
}
}

View File

@ -452,12 +452,14 @@ class TimelineViewController: UITableViewController, UndoableCommandRunner {
guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
return
}
for indexPath in tableView.indexPathsForVisibleRows? {
guard let article = dataSource.itemIdentifier(for: indexPath) else {
continue
}
if article.feed == feed, let cell = tableView.cellForRow(at: indexPath) as? TimelineTableViewCell, let image = iconImageFor(article) {
cell.setIconImage(image)
if let indexPaths = tableView.indexPathsForVisibleRows {
for indexPath in indexPaths {
guard let article = dataSource.itemIdentifier(for: indexPath) else {
continue
}
if article.feed == feed, let cell = tableView.cellForRow(at: indexPath) as? TimelineTableViewCell, let image = iconImageFor(article) {
cell.setIconImage(image)
}
}
}
}
@ -466,13 +468,15 @@ class TimelineViewController: UITableViewController, UndoableCommandRunner {
guard coordinator.showIcons, let avatarURL = note.userInfo?[UserInfoKey.url] as? String else {
return
}
for indexPath in tableView.indexPathsForVisibleRows? {
guard let article = dataSource.itemIdentifier(for: indexPath), let authors = article.authors, !authors.isEmpty else {
continue
}
for author in authors {
if author.avatarURL == avatarURL, let cell = tableView.cellForRow(at: indexPath) as? TimelineTableViewCell, let image = iconImageFor(article) {
cell.setIconImage(image)
if let indexPaths = tableView.indexPathsForVisibleRows {
for indexPath in indexPaths {
guard let article = dataSource.itemIdentifier(for: indexPath), let authors = article.authors, !authors.isEmpty else {
continue
}
for author in authors {
if author.avatarURL == avatarURL, let cell = tableView.cellForRow(at: indexPath) as? TimelineTableViewCell, let image = iconImageFor(article) {
cell.setIconImage(image)
}
}
}
}