Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Murat KAYA
Murat KAYA
10,127 Points

UITableView.dataSource returning nil

class SecondViewController:  UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var messageLabel: UILabel!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var timeLabel: UILabel!
    @IBOutlet weak var txtMessage: UITextField!



    var usernamefield:UITextField?
    var serverIpfield:UITextField?
    var confirmButton:UIButton?
    var alert : UIAlertController?
    var serverIP = "192.168.1.3:120"
    var nickName = "Murat"
    var clientSocket: TCPClient?
    var toolbar: UIToolbar?
    @IBOutlet var messageTableView: UITableView!
    var messages:[Message]=[]
    var textView: UITextView = UITextView(frame: CGRectZero)


    override func viewDidLoad() {
        super.viewDidLoad()
         /* func messagetableViewFunc() {
            messageTableView.dataSource = self
            messageTableView.delegate = self
            //let nibName = UINib(nibName: "MessageCell", bundle:nil)
            //self.messageTableView.registerNib(nibName, forCellReuseIdentifier: "MessageCell")
            self.messageTableView.registerNib(UINib(nibName: "MessageCell", bundle:nil ), forCellReuseIdentifier: "MessageCell")
            self.messageTableView.rowHeight = UITableViewAutomaticDimension;
            self.messageTableView.estimatedRowHeight = 44.0;
            self.messageTableView.keyboardDismissMode = .Interactive
            self.view.addSubview(self.tableView!)

        } */



        self.navigationItem.hidesBackButton=true
        self.view.backgroundColor=UIColor.whiteColor()
        let nibName = UINib(nibName: "MessageCell", bundle:nil)
        self.messageTableView.registerNib(nibName, forCellReuseIdentifier: "MessageCell")
        messageTableView.dataSource = self
        messageTableView.delegate = self

        //self.messageTableView.registerNib(UINib(nibName: "MessageCell", bundle:nil ), forCellReuseIdentifier: "MessageCell")
        self.messageTableView.rowHeight = UITableViewAutomaticDimension;
        self.messageTableView.estimatedRowHeight = 44.0;
        self.messageTableView.keyboardDismissMode = .Interactive
        self.view.addSubview(self.tableView!)
        serverIP = serverIpfield!.text
        nickName = usernamefield!.text

        // Do any additional setup after loading the view, typically from a nib.
    }
    func doInBackground(block:()->()) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
          block()
        })
    }
    func sendMesage(msgtosend: NSDictionary) {
        var msgdata=NSJSONSerialization.dataWithJSONObject(msgtosend, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
        var len = Int32(msgdata!.length)
        var data:NSMutableData = NSMutableData(bytes: &len, length: 4)
        self.clientSocket!.send(data: data)
        self.clientSocket!.send(data: msgdata!)
    }
    override func canBecomeFirstResponder() -> Bool {
        return true
    }
    func disconnect(){

    }
    func proccessMessage(msg:NSDictionary){
        var cmd: String = msg["cmd"] as String
        switch(cmd){
        case "msg" :
            self.messages.append(Message(from: msg["from"] as String, incoming: true, text: msg["context"]as String, sentDate: NSDate()))
            self.messageTableView!.reloadData()
        default:
            print(msg)
        }
    }
    override var inputAccessoryView: UIView! {
        get {
            if toolbar == nil {
                toolbar = UIToolbar(frame: CGRectMake(0, 0, 320, 44))
                textView.backgroundColor = UIColor(white: 250/255, alpha: 1)

                textView.font = UIFont.systemFontOfSize(17.0)
                textView.layer.borderColor = UIColor(red: 200/255, green: 200/255, blue: 200/255, alpha: 1).CGColor
                textView.layer.borderWidth = 0.5
                textView.layer.cornerRadius = 5
                textView.scrollsToTop = false
                textView.textContainerInset = UIEdgeInsetsMake(4, 4, 3, 3)
                toolbar!.addSubview(textView)

                var sendButton = UIButton.buttonWithType(.System) as UIButton
                sendButton.titleLabel?.font = UIFont.boldSystemFontOfSize(17)
                sendButton.setTitle("Send", forState: .Normal)
                sendButton.setTitleColor(UIColor(red: 142/255, green: 142/255, blue: 147/255, alpha: 1), forState: .Disabled)
                sendButton.setTitleColor(UIColor(red: 1/255, green: 122/255, blue: 255/255, alpha: 1), forState: .Normal)
                toolbar!.addSubview(sendButton)
                textView.setTranslatesAutoresizingMaskIntoConstraints(false)
                sendButton.setTranslatesAutoresizingMaskIntoConstraints(false)
                toolbar!.addConstraint(NSLayoutConstraint(item: textView, attribute: .Left, relatedBy: .Equal, toItem: toolbar, attribute: .Left, multiplier: 1, constant: 8))
                toolbar!.addConstraint(NSLayoutConstraint(item: textView, attribute: .Top, relatedBy: .Equal, toItem: toolbar, attribute: .Top, multiplier: 1, constant: 7.5))
                toolbar!.addConstraint(NSLayoutConstraint(item: textView, attribute: .Right, relatedBy: .Equal, toItem: sendButton, attribute: .Left, multiplier: 1, constant: -2))
                toolbar!.addConstraint(NSLayoutConstraint(item: textView, attribute: .Bottom, relatedBy: .Equal, toItem: toolbar, attribute: .Bottom, multiplier: 1, constant: -8))
                toolbar!.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .Right, relatedBy: .Equal, toItem: toolbar, attribute: .Right, multiplier: 1, constant: 0))
                toolbar!.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .Bottom, relatedBy: .Equal, toItem: toolbar, attribute: .Bottom, multiplier: 1, constant: -4.5))
            }
            return toolbar!
        }
    }

    func sendAction() {
        var content = textView.text
        var message = ["cmd":"msg","content":content]
        self.sendMesage(message)
        textView.text = nil
    }
    func processSocket() {
        var alert = UIAlertController(title: "New name",
            message: "Add a new name",
            preferredStyle: .Alert)
        self.clientSocket = TCPClient(addr: self.serverIP,port: 120)
        self.doInBackground({
            var (success,msg) = self.clientSocket!.connect(timeout: 5)
            func readmsg()->NSDictionary? {
                if let data=self.clientSocket!.read(4){
                    if data.count == 4{
                        var ndata = NSData(bytes: data, length: data.count)
                        var len:Int32 = 0
                        ndata.getBytes(&len, length: data.count)
                        if let buff=self.clientSocket!.read(Int(len)){
                            var msgd:NSData=NSData(bytes: buff, length: buff.count)
                            var msgi:NSDictionary=NSJSONSerialization.JSONObjectWithData(msgd, options: .MutableContainers, error: nil) as NSDictionary
                            return msgi
                        }
                    }
                }
                return nil
            }
            if success{
                dispatch_async(dispatch_get_main_queue(), {
                    self.alert = UIAlertController(title: "connection success", message: nil, preferredStyle: .Alert )

                })

                var msgtosend = ["login":"nickname","nickname":self.nickName]
                self.sendMesage(msgtosend)

                while true {
                    if let msg=readmsg() {
                        dispatch_async(dispatch_get_main_queue(), {
                            self.proccessMessage(msg)
                        })
                    }else {
                        dispatch_async(dispatch_get_main_queue(), {
                            self.disconnect()
                        })
                        break
                    }
                }
            }else {
                dispatch_async(dispatch_get_main_queue(), {

                    self.alert = UIAlertController(title: msg, message: msg, preferredStyle: .Alert)

                })
            }
        })
    }





    var dateFormatter = NSDateFormatter()

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

    func formatDate(date: NSDate) ->String {
        let calender = NSCalendar.currentCalendar()
        let last18Hours = (-18*60*60 < date.timeIntervalSinceNow)

        if last18Hours {
            dateFormatter.dateStyle = .NoStyle
            dateFormatter.timeStyle = .ShortStyle
        }else {
            dateFormatter.dateStyle = .ShortStyle
            dateFormatter.timeStyle = .NoStyle
        }
        return dateFormatter.stringFromDate(date)
    }
    func configureWithMessage(message: Message){
        messageLabel.text = message.text
        nameLabel.text = message.from
        timeLabel.text = self.formatDate(message.sentDate)
    }


    func keyboardWillShow(n:NSNotification){
        let userInfo = n.userInfo as NSDictionary!
        let frameNew = (userInfo[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
        let insetNewBottom = messageTableView!.convertRect(frameNew, fromView: nil).height
        let insetOld = messageTableView!.contentInset
        let insetChange = insetNewBottom - insetOld.bottom
        let overflow = messageTableView!.contentSize.height - (messageTableView!.frame.height-insetOld.top-insetOld.bottom)

        let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as NSNumber).doubleValue
        let animations: (() -> Void) = {
            if !(self.messageTableView!.tracking || self.messageTableView!.decelerating) {
                // Move content with keyboard
                if overflow > 0 {                   // scrollable before
                    self.messageTableView!.contentOffset.y += insetChange
                    if self.messageTableView!.contentOffset.y < -insetOld.top {
                        self.messageTableView!.contentOffset.y = -insetOld.top
                    }
                } else if insetChange > -overflow { // scrollable after
                    self.messageTableView!.contentOffset.y += insetChange + overflow
                }
            }
        }
        if duration > 0 {
            let options = UIViewAnimationOptions(UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] as NSNumber).integerValue << 16))
            UIView.animateWithDuration(duration, delay: 0, options: options, animations: animations, completion: nil)
        } else {
            animations()
        }
    }
    func keyboardDidShow(notification: NSNotification) {
        let userInfo = notification.userInfo as NSDictionary!
        let frameNew = (userInfo[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
        let insetNewBottom = messageTableView!.convertRect(frameNew, fromView: nil).height

        // Inset `tableView` with keyboard
        let contentOffsetY = messageTableView!.contentOffset.y
        messageTableView!.contentInset.bottom = insetNewBottom
        messageTableView!.scrollIndicatorInsets.bottom = insetNewBottom
        // Prevents jump after keyboard dismissal
        if self.messageTableView!.tracking || self.messageTableView!.decelerating {
            messageTableView!.contentOffset.y = contentOffsetY
        }
    }

    func keyboardWillHide(n:NSNotification){

    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return messages.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {

        var cell:UITableViewCell=tableView.dequeueReusableCellWithIdentifier("MessageCell") as UITableViewCell
        var msg=self.messages[indexPath.row]

        //cell.configureWithMessage(msg)
        return cell

    }

}

fatal error: unexpectedly found nil while unwrapping an Optional value

messageTableView.dataSource = self what should I do now ?