Не могу разобраться с поиском по заголовкам новостей из ленты RSS

searchbar
filter
swift
xcode

#1

Привет. В приложение из ленты RSS загружается лента новостей, структурируется на заголовок, контент, картинку (полный текст отображается в отдельном контроллере). Затем заголовки делятся на sections по дате (году). Все это в CollectionView. Нужно сделать фильтр для поиска по заголовкам новостей.

Код загрузки ленты:

@objc func loadNews() {
        loadingShow(text: NSLocalizedString("Updating...", comment: ""))
        newsRSS.removeAll()
        newsGroupsRSS.removeAll()
        collectionView.reloadData()
        
        let url: URL = URL(string: "https://XXXXXXXXXXX/news.html?format=feed&type=rss")!
        let request: URLRequest = URLRequest(url: url)
        let sessionConf = URLSessionConfiguration.default
        let sessionRSS = URLSession(configuration: sessionConf, delegate: nil, delegateQueue: nil)
        let task = sessionRSS.dataTask(with: request) { (data, response, error) in
            
            if (error == nil) {
                if (response as? HTTPURLResponse) != nil {
                    let xml = XML.parse(data!)
                    for hit in xml["rss","channel","item"] {
             
                        var images: [String] = []
                        
                        // ссылка
                        let link: String = hit["link"].text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

                        // заголовок
                        let title1: String = hit["title"].text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                        let title = title1.replacingOccurrences(of: "<[^>]+>", with: "", options: String.CompareOptions.regularExpression, range: nil).replacingOccurrences(of: ";", with: "")
                        
                        // текст новости
                        let desc: String = hit["description"].text!.replacingOccurrences(of: "<br>", with: "\n").replacingOccurrences(of: "</br>", with: "\n").replacingOccurrences(of: "<br />", with: "\n").replacingOccurrences(of: "</p>", with: "\n").replacingOccurrences(of: "&nbsp", with: "").replacingOccurrences(of: "&quot", with: "\"").replacingOccurrences(of: "&laquo", with: "\"").replacingOccurrences(of: "&raquo", with: "\"").replacingOccurrences(of: "&gt", with: "").trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                        // получим картинки из текста
                        let pattern = "([^\"]*)"
                        let arr = listMatches(pattern: pattern, inString: desc)
                        for item in arr where item.contains(".jpg") || item.contains(".jpeg") || item.contains(".png") || item.contains(".gif") {
                            images.append(item)
                        }
                        // сам текст без тегов
                        let content = desc.replacingOccurrences(of: "<[^>]+>", with: "", options: String.CompareOptions.regularExpression, range: nil).replacingOccurrences(of: ";", with: "").replacingOccurrences(of: "\r\n\r\n\r\n", with: "\r\n\r\n").trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                        
                        // поместим в массив всю новость
                        let dateString: String = hit["pubDate"].text!
                        if let date = dateString.toDate(format: "E, d MMM yyyy HH:mm:ss Z") {
                            newsRSS.append(itemRSS.init(title: title, content: content, link: link, date: date, images: images))
                        }
                    }
                    
                    
                    newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year]))
                    
                    DispatchQueue.main.async {
                        self.refresher?.endRefreshing()
                        self.collectionView.reloadData()
                        
                    }

                }
            }
            DispatchQueue.main.async {
                self.refresher?.endRefreshing()
            }

        }
        
        task.resume()
        loadingHide()
    }

class NewsCell: UICollectionViewCell {

@IBOutlet weak var content:  UIView!
@IBOutlet weak var lblTitle: UIVerticalAlignLabel!
@IBOutlet weak var lblDate:  UILabel!

func setShadow() {
    content.layer.shadowColor   = UIColor(hex: lexiconColor).withAlphaComponent(0.3).cgColor
    content.layer.shadowOffset  = .zero
    content.layer.shadowRadius  = 5
    content.layer.shadowOpacity = 0.3
    
}

func setContent(item: itemRSS) {
    lblTitle.text = item.title
    lblDate.text  = item.date.toString(format:"dd.MM.yyyy")
    if sizeScreen().modelIphone() == .iphone5 {
        lblTitle.font = UIFont.systemFont(ofSize: 12)
    }
}

}

struct GroupRSS {
let date: Date
let items: [itemRSS]

public static func createGroups(datedItems: [Date: [itemRSS]]) -> [GroupRSS] {
    var result = [GroupRSS]()
    for (date, items) in datedItems {
        let group = GroupRSS(date: date, items: items.sorted(by: { $0.date > $1.date }))
        result.append(group)
    }
    return result.sorted(by: { $0.date > $1.date })
}
}

class itemRSS : Dated, CustomStringConvertible {
var title:    String  = ""
var content:  String  = ""
var link:     String  = ""
var date:     Date
var images:  [String] = []
init(title: String, content: String, link: String, date: Date, images: [String]) {
    self.title   = title
    self.content = content
    self.link    = link
    self.date    = date
    self.images  = images
}

var description: String {
    return date.toString(format: "yyyy-MM-dd")
}
}

И сама фильтрация:

extension NewsViewController: UISearchControllerDelegate, UISearchResultsUpdating, UISearchBarDelegate {

    func updateSearchResults(for searchController: UISearchController) {
        let searchText: String = searchController.searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines)
        filterContent(searchText: searchText)
    }
    func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        filterContent(searchText: searchBar.text!.trimmingCharacters(in: .whitespacesAndNewlines))
    }
    func filterContent(searchText: String) {

        if searchText.isEmpty {
            newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year]))

        } else {
            let searchString: String = searchText.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).replacingOccurrences(of: "  ", with: " ").lowercased()
            let strings: [String] = searchString.components(separatedBy: " ")

            if strings.count == 1 {

                newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year])).filter {_ in
                title!.lowercased().contains(strings[0])
                }

            } else if strings.count == 2 {
                newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year])).filter {_ in
                title!.lowercased().contains(strings[0]) || title!.lowercased().contains(strings[1])
                }

            } else if strings.count == 3 {


                newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year])).filter {_ in
                   title!.lowercased().contains(strings[0]) || title!.lowercased().contains(strings[1]) ||
                    title!.lowercased().contains(strings[2])
                }
            } else if strings.count == 4 {
                newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year])).filter {_ in
                   title!.lowercased().contains(strings[0]) || title!.lowercased().contains(strings[1]) ||
                    title!.lowercased().contains(strings[2]) || title!.lowercased().contains(strings[3])
                }
            } else {
                newsGroupsRSS = GroupRSS.createGroups(datedItems: grouped(newsRSS, components: [.year])).filter
                    { _ in title!.lowercased().contains(strings[0]) }
            }


    }
        collectionView.reloadData()

    }
    
    func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {

        return true
    }

}

С тайтлом никак не могу сообразить, как правильно сделать. Сейчас, конечно, совсем не правильно.