Привет. В приложение из ленты 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: " ", with: "").replacingOccurrences(of: """, with: "\"").replacingOccurrences(of: "«", with: "\"").replacingOccurrences(of: "»", with: "\"").replacingOccurrences(of: ">", 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
}
}
С тайтлом никак не могу сообразить, как правильно сделать. Сейчас, конечно, совсем не правильно.