SearchBar 如何通过 NSMutableArray 进行搜索?
Posted
技术标签:
【中文标题】SearchBar 如何通过 NSMutableArray 进行搜索?【英文标题】:How can a SearchBar search through a NSMutableArray? 【发布时间】:2017-12-11 19:35:47 【问题描述】:我有一个NSMutableArray
,我正在尝试创建一个搜索栏。我一直在寻找几个小时,但我找不到任何对我有帮助的东西,因为我将 NSMutableArray
与 Firebase 一起使用。我对斯威夫特有点陌生。我创建了一个表格视图和一个搜索栏。表格视图显示来自NSMutableArray
的数据。当用户在搜索栏上搜索时,我怎样才能做到这一点,然后整个帖子都会出现?
如果有一个帖子包含 2 个字符串和一个图像,一个字符串是“A City”,另一个字符串是帖子的标题,假设当用户只搜索帖子的标题时或者只有城市,然后显示整个帖子。如果结果可以在同一个viewcontroller
上,就像在同一个tableview
上一样。
到目前为止,我已经在我的viewDidLoad
:
func setUpSearchBar()
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
searchController.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
而我的数组是这样的:
var posts = NSMutableArray()
我真正写过的唯一内容是设置了搜索栏,但没有真正发挥作用,因为我没有找到任何可以帮助我的东西,而且我不知道如何进行搜索酒吧工作。到目前为止,我必须找到的所有教程都是非常普通的数组,例如:
var post = ["pear", "orange", "apple"]
但我找不到如何让搜索遍历我的帖子NSMutableArray
。
如果有人能帮助我解决这个问题,我会非常高兴。如果可能的话,我不想要直接的答案和一些解释,以便我可以学习并自己创建它。
这是下载数据并将其显示在TableView
中的代码
import UIKit
import FirebaseStorage
import FirebaseDatabase
import FirebaseAuth
import FirebaseCore
import Firebase
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
@IBOutlet weak var postsTableView: UITableView!
var posts = NSMutableArray()
override func viewDidLoad()
super.viewDidLoad()
setUpSearchBar()
loadData()
self.postsTableView.delegate = self
self.postsTableView.dataSource = self
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func loadData()
Database.database().reference().child("posts").queryOrdered(byChild: "timeorder").observeSingleEvent(of: .value) (snapshot) in
if let postsDictionary = snapshot.value as? [String: AnyObject]
for post in postsDictionary
self.posts.add(post.value)
self.postsTableView.reloadData()
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int
// #warning Incomplete implementation, return the number of sections
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// #warning Incomplete implementation, return the number of rows
return self.posts.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PostTableViewCell
// Configure the cell...
let post = self.posts[indexPath.row] as! [String: AnyObject]
cell.titleLabel.text = post["title"] as? String
cell.contentTextView.text = post["content"] as? String
cell.dateAndTimeLabel.text = post["time"] as? String
cell.usernameLabel.text = post["username"] as? String
cell.locationAdressLabel.text = post["adress"] as? String
if let imageName = post["image"] as? String
let imageRef = Storage.storage().reference().child("images/\(imageName)")
imageRef.getData(maxSize: 25 * 1024 * 1024) (data, error) -> Void in
if error == nil
//successfull
let downloadedImage = UIImage(data: data!)
cell.postsImageView.image = downloadedImage
else
// error
print("there was an error downloading image: \(String(describing: error?.localizedDescription))")
return cell
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 500.0
@IBAction func goToProfilePage(_ sender: Any)
let logoutSuccess = self.storyboard?.instantiateViewController(withIdentifier: "ProfileVC")
self.present(logoutSuccess!, animated: true, completion: nil)
@IBAction func navigateButton(_ sender: Any)
let navigate = self.storyboard?.instantiateViewController(withIdentifier: "NavigateVC")
self.present(navigate!, animated: true, completion: nil)
@IBAction func chooseCountry(_ sender: Any)
let navigate = self.storyboard?.instantiateViewController(withIdentifier: "CountryVC")
self.present(navigate!, animated: true, completion: nil)
func setUpSearchBar()
let searchController = UISearchController(searchResultsController: nil)
navigationItem.searchController = searchController
searchController.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
这是将post
上传到 Firebase 的代码
import UIKit
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth
import Firebase
class PostViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPickerViewDataSource, UIPickerViewDelegate
@IBOutlet weak var addImageButton: UIBarButtonItem!
@IBOutlet weak var pickCountryPicker: UIPickerView!
@IBOutlet weak var choosenCountryLabel: UILabel!
@IBOutlet weak var titleTextField: UITextField!
@IBOutlet weak var contentTextView: UITextView!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var locationAdressTextField: UITextField!
var imageFileName = ""
var timeStamps = ""
var secondTimeStamps = ""
override func viewDidLoad()
super.viewDidLoad()
let currentDateTime = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
timeStamps = "\(dateFormatter.string(from: currentDateTime))"
let secondDateFormatter = DateFormatter()
secondDateFormatter.dateFormat = "yyyy-MM-dd HH:00:00"
secondTimeStamps = "\(secondDateFormatter.string(from: currentDateTime))"
// Do any additional setup after loading the view.
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
@IBAction func postButton(_ sender: Any)
if (self.imageFileName != "")
if choosenCountryLabel.text == "Afghanistan"
// image has finshed the uploading, Saving Post!!!
if let uid = Auth.auth().currentUser?.uid
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: (snapshot) in
if let userDictionary = snapshot.value as? [String: AnyObject]
for user in userDictionary
if let username = user.value as? String
if let streetAdress = self.locationAdressTextField.text
if let title = self.titleTextField.text
if let content = self.contentTextView.text
let postObject: Dictionary<String, Any> = [
"uid" : uid,
"title" : title,
"content" : content,
"username" : username,
"time" : self.timeStamps,
"timeorder" : self.secondTimeStamps,
"image" : self.imageFileName,
"adress" : streetAdress
]
Database.database().reference().child("posts").childByAutoId().setValue(postObject)
Database.database().reference().child("Afghanistanposts").childByAutoId().setValue(postObject)
Database.database().reference().child(uid).childByAutoId().setValue(postObject)
let alertPosting = UIAlertController(title: "Successfull upload", message: "Your acty was successfully uploaded.", preferredStyle: .alert)
alertPosting.addAction(UIAlertAction(title: "OK", style: .default, handler: (action) in
let vc = self.storyboard?.instantiateViewController(withIdentifier: "AfghanistanVC")
self.present(vc!, animated: true, completion: nil)
))
self.present(alertPosting, animated: true, completion: nil)
print("Posted Succesfully to Firebase, Saving Post!!!")
)
else
let alertNotPosting = UIAlertController(title: "Seems like you got connection problems", message: "Your image has not been uploaded. Please Wait 10 seconds and try again.", preferredStyle: .alert)
alertNotPosting.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alertNotPosting, animated: true, completion: nil)
@IBAction func addImage(_ sender: Any)
if addImageButton.isEnabled == false
let alertNotPosting = UIAlertController(title: "Image already Picked", message: "sorry you already have an image picked", preferredStyle: .alert)
alertNotPosting.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alertNotPosting, animated: true, completion: nil)
else
let picker = UIImagePickerController()
picker.delegate = self
self.present(picker, animated: true, completion: nil)
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
self.imageView.image = pickedImage
uploadImage(image: pickedImage)
picker.dismiss(animated: true, completion: nil)
addImageButton.isEnabled = false
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
picker.dismiss(animated: true, completion: nil)
func uploadImage(image: UIImage)
let randomName = randomStringWithLength(length: 10)
let imageData = UIImageJPEGRepresentation(image, 1.0)
let uploadRef = Storage.storage().reference().child("images/\(randomName).jpg")
let uploadTask = uploadRef.putData(imageData!, metadata: nil) metadata, error in
if error == nil
//success
print("SuccessFully uploaded")
self.imageFileName = "\(randomName as String).jpg"
else
// not success = error
print("error with the Image: \(String(describing: error?.localizedDescription))")
func randomStringWithLength(length: Int) -> NSString
let characters: NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var randomString: NSMutableString = NSMutableString(capacity: length)
for i in 0..<length
var len = UInt32(characters.length)
var rand = arc4random_uniform(len)
randomString.appendFormat("%C", characters.character(at: Int(rand)))
return randomString
func numberOfComponents(in pickerView: UIPickerView) -> Int
return 1
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
return countries[row]
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
return countries.count
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
choosenCountryLabel.text = countries[row]
下面是选择器的一个完整国家/地区的数组,不需要显示。
【问题讨论】:
不要使用NSMutableArray
。它与 Swift 数组无关,您正在与强类型系统作斗争。只需使用var
,您就可以免费获得可变性
@vadian 那么我应该使用什么 NSArray?还是?
不,使用 Swift 数组,[String]
或 [Post]
等。除非编译器告诉您需要它们,否则根本不要使用 NS...
集合类型(例如在一些 CoreFoundation函数调用和 Objective-C 桥接 inout 参数)
相信我,你绝对不需要NSMutableArray
。再一次,var
关键字使任何 Swift 集合类型(Array
、Dictionary
)都是可变的。如果您需要引用类型,请使用类而不是结构
@Jiyar 如果您使用相关代码更新您的问题,显示您实际拥有什么以及您正在尝试做什么,这将非常有帮助。
【参考方案1】:
为什么不直接将 NSMutableArray
转换为 Swift 数组?为了安全起见,我建议使用 guard
声明,如下所示:
guard let swiftArrayPosts = posts as? [String] else return
然后你就可以使用像filter
这样的Swift高阶函数来查找你想要的帖子了:
let filteredPosts = swiftArrayPosts.filter $0 == "MyQuery"
然后将filteredPosts
分配给您用来显示它们的任何数据源。
【讨论】:
我真的很难理解这个,我应该输入这个吗?在setUpSearchBar
函数中或上面,或者我会创建一个新函数,每当user
命中Search
时都会这样做?
需要查看更多代码才能理解您在说什么。没有原生的setUpSearchBar
函数。但是是的,您希望在用户输入查询时使用。
更新问题添加了我的上传代码和我的下载代码
首先。您需要将 searchController 的搜索栏分配给表视图标题视图 tableView.tableHeaderView = searchController.searchBar
在您的 setUpSearchBarFunction
中执行此操作
搜索栏已经在“导航”栏中,只要用户滚动到表格视图的顶部就会显示以上是关于SearchBar 如何通过 NSMutableArray 进行搜索?的主要内容,如果未能解决你的问题,请参考以下文章
如何在带有部分的 TableView 上创建 SearchBar?
如何让 TableView 中的 SearchBar 看起来像设置应用程序中的那样