UISearch 在 JSON api UITableView 中不起作用

Posted

技术标签:

【中文标题】UISearch 在 JSON api UITableView 中不起作用【英文标题】:UISearch is not Working in JSON api UITable View 【发布时间】:2017-08-18 04:21:20 【问题描述】:

全部

我正在尝试开发一个应用程序。现在我需要使用 UISearch View 搜索视频列表。

这是我的代码。我可以看到搜索栏,但它不起作用。

导入 UIKit 导入 GoogleMobileAds

ViewController 类:UIViewController、UITableViewDelegate、UITableViewDataSource、GADInterstitialDelegate、UIAlertViewDelegate、UISearchBarDelegate

@IBOutlet weak var tblVideos: UITableView!

@IBOutlet weak var banner3: GADBannerView!


var interstitial: GADInterstitial!


@IBOutlet weak var viewWait: UIView!



var channelsDataArray: Array<Dictionary<String, Any>> = []

var apikey = ""

var selectedVideoIndex: Int!


override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    if connectedToNetwork() == true 

        tblVideos.delegate = self
        tblVideos.dataSource = self

        print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
        banner3.adUnitID = ""
        banner3.rootViewController = self
        banner3.load(GADRequest())

        getChannelDetails(false)
        loadInterstitial()
        searchBar()

    

    else 
        let controller = UIAlertController(title: "No Internet Detected", message: "This app requires an Internet connection", preferredStyle: .alert)
        let ok = UIAlertAction(title: "OK", style: .default, handler: nil)
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        controller.addAction(ok)
        controller.addAction(cancel)

        present(controller, animated: true, completion: nil)
    


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


func searchBar() 
    let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 50))
    searchBar.delegate = self
    searchBar.showsScopeBar = true
    searchBar.tintColor = UIColor.lightGray
    self.tblVideos.tableHeaderView = searchBar




func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 

    if searchText == "" 
        //do something
        getChannelDetails(false)
    
    else 

            channelsDataArray = channelsDataArray.filter(($0["title"] as! String).contains(searchText))

    




override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let playerViewController = segue.destination as? PlayerViewController 
        playerViewController.videoID = channelsDataArray[selectedVideoIndex]["videoId"] as! String
    





// MARK: UITableView method implementation

func numberOfSections(in tableView: UITableView) -> Int 
    return 1



func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    return channelsDataArray.count





func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    var cell: UITableViewCell!


    cell = tableView.dequeueReusableCell(withIdentifier: "idCellChannel", for: indexPath)

    let channelTitleLabel = cell.viewWithTag(10) as! UILabel

    let thumbnailImageView = cell.viewWithTag(12) as! UIImageView

    let channelDetails = channelsDataArray[indexPath.row]
    channelTitleLabel.text = channelDetails["title"] as? String

    thumbnailImageView.image = UIImage(data: try! Data(contentsOf: URL(string: (channelDetails["url"] as? String)!)!))


    return cell



func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    return 350.0



func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

    selectedVideoIndex = indexPath.row
    performSegue(withIdentifier: "idSeguePlayer", sender: self)
    if (interstitial!.isReady) 
        interstitial!.present(fromRootViewController: self)
    
    loadInterstitial()









// MARK: UITextFieldDelegate method implementation



// MARK: Custom method implementation

func performGetRequest(_ targetURL: URL!, completion: @escaping (_ data: Data?, _ HTTPStatusCode: Int, _ error: Error?) -> Void) 
    var request = URLRequest(url: targetURL)
    request.httpMethod = "GET"

    let sessionConfiguration = URLSessionConfiguration.default

    let session = URLSession(configuration: sessionConfiguration)

    let task = session.dataTask(with: request, completionHandler:  (data: Data?, response: URLResponse?, error: Error?) -> Void in
        DispatchQueue.main.async(execute:  () -> Void in
            completion(data, (response as! HTTPURLResponse).statusCode, error)
        )
     )

    task.resume()



func getChannelDetails(_ useChannelIDParam: Bool) 
    var urlString: String!
    if !useChannelIDParam 
        urlString = "https://www.googleapis.com/youtube/v3/search?part=id%2Csnippet&type=video&q=mufti+amir+hamza&maxResults=50&key=apikey"
    

    let targetURL = URL(string: urlString)

    performGetRequest(targetURL, completion:  (data, HTTPStatusCode, error) -> Void in
        if HTTPStatusCode == 200 && error == nil 

            do 

                if let resultsDict = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:Any] 
                    if let items = resultsDict["items"] as? [[String:Any]] 
                        for item in items 
                            var desiredValues = [String:Any]()

                            //get the videoId
                            if let id = item["id"] as? [String:Any], let videoId = id["videoId"] as? String
                                desiredValues["videoId"] = videoId
                            

                            //get title and thumbnail from snippet
                            if let snippet = item["snippet"] as? [String:Any] 
                                if let title = snippet["title"] 
                                    desiredValues["title"] = title
                                
                                if let thumbanail = snippet["thumbnails"] as? [String:Any], let highValues = thumbanail["high"] as? [String:Any], let url = highValues["url"] as? String 
                                    desiredValues["url"] = url
                                
                            
                            self.channelsDataArray.append(desiredValues)
                        
                        DispatchQueue.main.async 
                            self.tblVideos.reloadData()
                        
                    

                
            
            catch (let error)
                print("Error while parsing data: \(error.localizedDescription)")
            
        

        self.viewWait.isHidden = true

    )





//inter

fileprivate func loadInterstitial() 
    interstitial = GADInterstitial(adUnitID: "")
    interstitial!.delegate = self

    // Request test ads on devices you specify. Your test device ID is printed to the console when
    // an ad request is made.
    interstitial!.load(GADRequest())



// MARK: GADInterstitialDelegate implementation

func interstitialDidFailToReceiveAdWithError (
    _ interstitial: GADInterstitial,
    error: GADRequestError) 
    print("interstitialDidFailToReceiveAdWithError: %@" + error.localizedDescription)


func interstitialDidDismissScreen (_ interstitial: GADInterstitial) 
    print("interstitialDidDismissScreen")


我现在只需要将我的列表过滤为标题。可以请任何帮助我解决它吗?

【问题讨论】:

This 可能会有所帮助 在搜索栏中输入文本时是否调用了您的 searcBar(_:didChange:) 方法? @user1000 是的,它被称为 【参考方案1】:

您需要为 filtersArray 声明一个 var 以保留原始数组和所有元素

类似的东西

var filteredChannelsDataArray : Array<Dictionary<String, Any>> = []

您还需要在 getChannelDetails 方法中的 self.channelsDataArray.append(desiredValues) 之后添加这一行

self.filteredChannelsDataArray = channelsDataArray

试试这个

替换这个

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 

    if searchText == "" 
        //do something
        getChannelDetails(false)
    
    else 

         channelsDataArray = channelsDataArray.filter( (alldata) -> Bool in

        return true

    )

    


由此

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 

    if searchText == "" 
        //do something
        getChannelDetails(false)
        self.filteredChannelsDataArray = channelsDataArray
        self.tableView.reloadData()
    
    else 

            self.filteredChannelsDataArray = channelsDataArray.filter(($0["title"] as! String).contains(searchText))
           self.tableView.reloadData()
    


您还需要对 UITableViewDataSource 方法进行一些更改

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return self.filteredChannelsDataArray.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    var cell: UITableViewCell!


    cell = tableView.dequeueReusableCell(withIdentifier: "idCellChannel", for: indexPath)

    let channelTitleLabel = cell.viewWithTag(10) as! UILabel

    let thumbnailImageView = cell.viewWithTag(12) as! UIImageView

    let channelDetails = self.filteredChannelsDataArray[indexPath.row]
    channelTitleLabel.text = channelDetails["title"] as? String

    thumbnailImageView.image = UIImage(data: try! Data(contentsOf: URL(string: (channelDetails["url"] as? String)!)!))


    return cell

【讨论】:

【参考方案2】:

你可以试试这个代码:self.tblVideos.reloadData()

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
     if searchText == "" 
         //do something
         getChannelDetails(false)
     
     else 

        channelsDataArray = channelsDataArray.filter(($0["title"] as! String).contains(searchText))
        self.tblVideos.reloadData()
     

【讨论】:

以上是关于UISearch 在 JSON api UITableView 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

titleForHeaderInSection 与 UISearch 字段重叠

两个 NSMutables 数组中的 UISearch 栏

UISearch 栏总是显示:没有结果

IOS RxSwift中UISearch栏文本和视图模型属性之间的两种方式绑定

如何通过在iOS中进行JSON Pasing一次在tableview上显示不同的图像?

我们如何为多个 UITab 使用相同的 WKWebView