繁体   English   中英

从在线数据库填充 UICollectionView

[英]Populating UICollectionView from Online Database

我正在创建一个简单的聊天应用程序,它有一个加载屏幕,如果用户未登录,则它会跳转到登录屏幕,或者如果他登录,则直接跳转到他的聊天记录。 聊天记录显示在UICollectionView 当我第一次测试时,我用我在类中声明的虚拟数据填充它,一切正常。 现在我从加载屏幕中的在线数据库中获取用户的聊天记录,并将它们存储在一个名为user_chats的数组中,该数组是全局声明的。

在此处输入图片说明

我使用以下代码来填充UICollectionView

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
   // getUserChats()
    return user_chats.count

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

let cell = collectionView.dequeueReusableCellWithReuseIdentifier("chat_cell" , forIndexPath: indexPath) as! SingleChat

cell.chatName?.text = user_chats[indexPath.row].chat_partner!.name
cell.chatTextPreview?.text = user_chats[indexPath.row].chat_messages!.last!.text
let profile_pic_URL = NSURL(string : user_chats[indexPath.row].chat_partner!.profile_pic!)
downloadImage(profile_pic_URL!, imageView: cell.chatProfilePic)
cell.chatProfilePic.layer.cornerRadius = 26.5
cell.chatProfilePic.layer.masksToBounds = true

    let dividerLineView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
        return view
    }()
    dividerLineView.translatesAutoresizingMaskIntoConstraints = false

    cell.addSubview(dividerLineView)
    cell.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-1-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": dividerLineView]))
    cell.addSubview(dividerLineView)
    cell.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[v0(1)]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": dividerLineView]))
    return cell

}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    self.performSegueWithIdentifier("showChat", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if (segue.identifier == "showChat") {

        let IndexPaths = self.collectionView!.indexPathsForSelectedItems()!
        let IndexPath = IndexPaths[0] as NSIndexPath
        let vc = segue.destinationViewController as! SingleChatFull

        vc.title = user_chats[IndexPath.row].chat_partner!.name
    }

}

数据获取:

func getUserChats() {
    let scriptUrl = "*****"
    let userID = self.defaults.stringForKey("userId")
    let params = "user_id=" + userID!
    let myUrl = NSURL(string: scriptUrl);
    let request: NSMutableURLRequest = NSMutableURLRequest(URL: myUrl!)
    request.HTTPMethod = "POST"
    let data = params.dataUsingEncoding(NSUTF8StringEncoding)
    request.timeoutInterval = 10
    request.HTTPBody=data
    request.HTTPShouldHandleCookies=false
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    let queue:NSOperationQueue = NSOperationQueue()
    NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
        do {
            if (data != nil) {
                do {
                    var dataString = String(data: data!, encoding: NSUTF8StringEncoding)
                    var delimiter = "]"
                    var token = dataString!.componentsSeparatedByString(delimiter)
                    dataString = token[0] + "]"
                    print(dataString)
                    let data_fixed = dataString!.dataUsingEncoding(NSUTF8StringEncoding)
                    do {
                        let jsonArray = try NSJSONSerialization.JSONObjectWithData(data_fixed!, options:[])


                        // LOOP THROUGH JSON ARRAY AND FETCH VALUES
                        for anItem in jsonArray as! [Dictionary<String, AnyObject>] {
                            let curr_chat = Chat()
                            if let chatId = anItem["chatId"] as? String {
                                curr_chat.id = chatId
                            }
                            let friend = Friend()
                            let user1id = anItem["user1_id"] as! String
                            let user2id = anItem["user2_id"] as! String
                            if (user1id == userID) {
                                if let user2id = anItem["user2_id"] as? String {
                                    friend.id = user2id
                                }
                                if let user2name = anItem["user2_name"] as? String {
                                    friend.name = user2name
                                }
                                if let user2profilepic = anItem["user2_profile_pic"] as? String {
                                    friend.profile_pic = user2profilepic
                                }
                            }
                            else if (user2id == userID){
                                if let user1id = anItem["user1_id"] as? String {
                                    friend.id = user1id
                                }
                                if let user1name = anItem["user1_name"] as? String {
                                    friend.name = user1name
                                }
                                if let user1profilepic = anItem["user1_profile_pic"] as? String {
                                    friend.profile_pic = user1profilepic
                                }
                            }

                            curr_chat.chat_partner = friend

                            var chat_messages = [Message]()
                            if let dataArray = anItem["message"] as? [String : AnyObject] {
                                for (_, messageDictionary) in dataArray {
                                    if let onemessage = messageDictionary as? [String : AnyObject] {                                        let curr_message = Message()
                                        if let messageid = onemessage["message_id"] as? String {
                                            curr_message.id =  messageid
                                        }
                                        if let messagedate = onemessage["timestamp"] as? String {
                                            let dateFormatter = NSDateFormatter()
                                            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                                            let date = dateFormatter.dateFromString(messagedate)
                                            curr_message.date = date
                                        }
                                        if let messagesender = onemessage["sender"] as? String {

                                            curr_message.sender = messagesender
                                        }
                                        if let messagetext = onemessage["text"] as? String {
                                            curr_message.text = messagetext
                                        }
                                        chat_messages.append(curr_message)
                                    }}
                            }

                            curr_chat.chat_messages = chat_messages
                            user_chats.append(curr_chat)
                        }

                    }
                    catch {
                        print("Error: \(error)")
                    }
                }
//                       NSUserDefaults.standardUserDefaults().setObject(user_chats, forKey: "userChats")

            }
            else {
                dispatch_async(dispatch_get_main_queue(), {
                    let uiAlert = UIAlertController(title: "No Internet Connection", message: "Please check your internet connection.", preferredStyle: UIAlertControllerStyle.Alert)

                    uiAlert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { action in
                        self.dismissViewControllerAnimated(true, completion:nil)
                    }))
                    self.presentViewController(uiAlert, animated: true, completion: nil)
                })
            }

        } catch _ {
            NSLog("error")
        }

    })
}

问题是集合视图现在总是空的。 我已经做了一些调试并在第一个函数中放置了一个断点,我看到当加载屏幕仍然显示给用户并且聊天屏幕甚至没有加载时调用这个方法。 我怀疑这是在加载屏幕中从 Internet 获取数据之前调用的,因此user_chats数组的大小为 0。我习惯于使用 Android 和ListView ,其中ListView直到父视图显示在屏幕上,因此我很困惑。 从在线数据库中获取数据的方法工作正常,因为我已经对其进行了广泛的调试,所以问题不存在。

最好的选择是向您的函数添加一个completionHandler ,以便在数据返回和/或async函数完成执行时收到通知。 下面的代码是您的截断版本getUserCharts与函数completionHandler ,它返回一个true或当数据是假负载(您可以修改此返回任何你愿意的话)。 您可以阅读有关闭包/完成处理程序的更多信息https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html或 google。

功能

func getUserChats(completionHandler: (loaded: Bool, dataNil: Bool) -> ()) -> (){
        NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler:{ (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
            do {
                if (data != nil) {
                    do {
                        var dataString = String(data: data!, encoding: NSUTF8StringEncoding)
                        var delimiter = "]"
                        var token = dataString!.componentsSeparatedByString(delimiter)
                        dataString = token[0] + "]"
                        print(dataString)
                        let data_fixed = dataString!.dataUsingEncoding(NSUTF8StringEncoding)
                        do {
                            let jsonArray = try NSJSONSerialization.JSONObjectWithData(data_fixed!, options:[])

                            // LOOP THROUGH JSON ARRAY AND FETCH VALUES
                            completionHandler(loaded: true, dataNil: false)
                        }
                        catch {
                            print("Error: \(error)")
                        }
                    }
                }
                else {
                    //Handle error or whatever you wish
                    completionHandler(loaded: true, dataNil: true)
                }

            } catch _ {
                NSLog("error")
            }

如何使用它

override func viewDidLoad() {
        getUserChats(){
            status in
            if status.loaded == true && status.dataNil == false{
                self.collectionView?.reloadData()
            }
        }
    }

听起来这是一个异步问题。 我不确定您的项目是如何设置的,但您需要在返回响应时在集合视图上调用 reloadData()。

从服务器接收回数据并更新集合视图的数据源后,您需要刷新集合视图(确保您在主线程上,因为它正在修改 UI):

dispatch_async(dispatch_get_main_queue()) {
        self.collectionView.reloadData()
}

编辑:

另外,我不完全确定您是如何设置项目的,但是您可以为数据获取创建一个委托,因此每次您从服务器获取某些信息时,它都会调用一个委托方法来表示有新消息。 您的集合视图控制器将订阅该委托,并且每次调用该方法时,它都会重新加载您的集合视图。

代表:

protocol ChatsDelegate {
   func didUpdateChats(chatsArray: NSArray)
}

在您的数据提取中:

user_chats.append(cur_chat)
self.delegate.didUpdateChats(user_chats)

在您的 collectionView 控制器中:

class viewController: ChatsDelegate, ... {
...
   func didUpdateChats(chatsArray: NSArray) {
      dispatch_async(dispatch_get_main_queue()) {
         self.collectionView.reloadData()
      }
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM