swift5学习之旅之简易聊天室

27 篇文章 0 订阅

swift5学习之旅------简易聊天室

在这里插入图片描述
在这里插入图片描述

  • 整体代码
    Github还没上传,先用着Dropbox(可能要翻墙),看完有收获的感谢点个赞👍,如果翻不了墙要代码可以私聊我
    https://www.dropbox.com/sh/5oyxgu8vwx0ypux/AAAJ_KACNiJXIdX77OT0srKUa?dl=0

Dropbox 简易聊天室

聊天室使用了Golang中的通信,可以参考别人的介绍
https://github.com/dariencdd/StudyLog/wiki/Golang中client-server模型
golang通信

  • 核心思想
  • 网络层
    要读取写入网络流数据,就要使用 CFReadStream,CFWriteStream

CFStreamCreatePairWithSocketToHost连接服务器
输入流:inputStream把硬盘文件中的数据,读取到内存中使用。对应的是readStream
输出流:outputStream把内存中的数据存到硬盘中,对应的是outputstream

//建立网络连接
    func setupNetworkCommunication(){
        //Unmanaged表示对不清晰的内存管理对象的封装
        var readStream: Unmanaged<CFReadStream>?
        var writeStream: Unmanaged<CFWriteStream>?
        CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, "127.0.0.1" as CFString, 98, &readStream, &writeStream)
        
        inputStream = readStream!.takeRetainedValue()
        outputStream = writeStream!.takeRetainedValue()
        
        inputStream.delegate = self
        
        inputStream.schedule(in: .current, forMode: .common)
        outputStream.schedule(in: .current, forMode: .common)
        
        inputStream.open()
        outputStream.open()
    }

输出流outputStream:加入聊天时,需要对username的值进行传递,所以需要把username输出到服务器,服务器再广播给所有使用者
发送信息也是输出流,把msg输出到服务器,再广播给所有使用者

outputStream.write(pointer, maxLength: data.count)

我们对username的判断可以知道服务器传送给自己的是否为自己发送的信息,再通过这个不同来改变UI

输入流inputStream:接收数据时,就是输入流,根据服务器接收到的数据对message的更改

//有字节输入
      while stream.hasBytesAvailable {
        let numberOfBytesRead = inputStream.read(buffer, maxLength: maxReadLength)
        
        if numberOfBytesRead < 0, let error = stream.streamError {
          print(error)
          break
        }
        
          //构造消息对象
        if let message = processedMessageString(buffer: buffer, length: numberOfBytesRead) {
          // 通知
          delegate?.received(message: message)
        }
      }
  • UI层
    因为msg信息不知道有多长,所以我们需要根据msg的信息对cell的高度进行更改
    这是cell高度的判断
//静态方法确定高度
    //message高度
    static func height(for message: Message) -> CGFloat {
      let maxSize = CGSize(width: 2*(UIScreen.main.bounds.size.width/3), height: CGFloat.greatestFiniteMagnitude)
      let nameHeight = message.messageSender == .ourself ? 0 : (height(forText: message.senderUsername, fontSize: 10, maxSize: maxSize) + 4 )
      let messageHeight = height(forText: message.message, fontSize: 17, maxSize: maxSize)
      
      return nameHeight + messageHeight + 32 + 16
    }
    
    //文本的高度判断
    private static func height(forText text: String, fontSize: CGFloat, maxSize: CGSize) -> CGFloat {
      let font = UIFont(name: "Helvetica", size: fontSize)!
      let attrString = NSAttributedString(string: text, attributes:[NSAttributedString.Key.font: font,NSAttributedString.Key.foregroundColor: UIColor.white])
      let textHeight = attrString.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil).size.height

      return textHeight
    }

cell添加新信息时需要重新布局

func apply(message: Message) {
        nameLabel.text = message.senderUsername
        messageLabel.text = message.message
        messageSender = message.messageSender
        //需要重新布局
        setNeedsLayout()
    }

判断自己发的信息还是别人发的信息,发送者messageSender肯定是自己,所以直接为ourself

enum MessageSender {
  case ourself
  case someoneElse
}
var messageSender: MessageSender = .ourself

文本信息的判断
根据自己的名字来判断

let messageSender: MessageSender = (name == self.username) ? .ourself : .someoneElse

UI显示的不同

if messageSender == .ourself {
        nameLabel.isHidden = true
        
        messageLabel.center = CGPoint(x: bounds.size.width - messageLabel.bounds.size.width/2 - 16, y: bounds.size.height/2)
        messageLabel.backgroundColor = #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)
      }
  • 怎么使用
    直接使用肯定是不行的,需要golang的编译
    定位到server.go的文件夹,在终端运行在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是一个简易的注册界面的 Swift 5 代码: ```swift import UIKit class RegisterViewController: UIViewController { let emailTextField: UITextField = { let textField = UITextField() textField.placeholder = "邮箱" textField.borderStyle = .roundedRect textField.translatesAutoresizingMaskIntoConstraints = false return textField }() let passwordTextField: UITextField = { let textField = UITextField() textField.placeholder = "密码" textField.borderStyle = .roundedRect textField.isSecureTextEntry = true textField.translatesAutoresizingMaskIntoConstraints = false return textField }() let registerButton: UIButton = { let button = UIButton(type: .system) button.setTitle("注册", for: .normal) button.addTarget(self, action: #selector(registerButtonTapped), for: .touchUpInside) button.translatesAutoresizingMaskIntoConstraints = false return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white navigationItem.title = "注册" view.addSubview(emailTextField) view.addSubview(passwordTextField) view.addSubview(registerButton) NSLayoutConstraint.activate([ emailTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor), emailTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50), emailTextField.widthAnchor.constraint(equalToConstant: 300), passwordTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor), passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 20), passwordTextField.widthAnchor.constraint(equalToConstant: 300), registerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), registerButton.topAnchor.constraint(equalTo: passwordTextField.bottomAnchor, constant: 50), registerButton.widthAnchor.constraint(equalToConstant: 200), registerButton.heightAnchor.constraint(equalToConstant: 50) ]) } @objc func registerButtonTapped() { guard let email = emailTextField.text, !email.isEmpty, let password = passwordTextField.text, !password.isEmpty else { // 如果邮箱或密码为空,弹出提示框 let alert = UIAlertController(title: "错误", message: "请输入邮箱和密码", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "好的", style: .default, handler: nil)) present(alert, animated: true, completion: nil) return } // 注册逻辑 } } ``` 这个简易的注册界面只包括了一个邮箱输入框、一个密码输入框和一个注册按钮。在视图加载时,我们添加了这些视图并使用了自动布局约束来布局它们。 当用户点击注册按钮时,`registerButtonTapped` 方法将会被调用。在这个方法中,我们首先检查邮箱和密码是否为空,如果为空则弹出一个提示框。如果邮箱和密码都不为空,你可以在这个方法中添加你自己的注册逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值