Complemento de tarjeta de mensajes de mensajería instantánea del cliente iOS

fondo

Actualmente, la lista de mensajes de chat de Tantan IM ha causado muchos problemas en la iteración empresarial debido a la acumulación de código a lo largo de los años. Por lo tanto, aprovechando algunas lagunas en el trabajo, se conecta la tarjeta de mensaje de la página de chat, de modo que se pueden agregar, eliminar e iterar fácilmente diferentes tipos de mensajes según las necesidades específicas. Permítanme compartir algunas ideas interesantes durante mi proceso de reconstrucción. Aunque actualmente se practica en la lista de mensajes de chat, también tiene cierta importancia de referencia para varios servicios complejos de flujo de alimentación.

Esta transformación de complemento utiliza IGListKit, que es un excelente marco de visualización UICollectionView basado en datos. Muchas ideas están inspiradas en algunos diseños de este marco. Si está interesado, puede encontrar algunos artículos para leer . Por supuesto, IGListKit no es necesario y su uso no afectará nuestro diseño.

La lista de mensajes de chat se puede generalizar en una lista de fuentes con muchas tarjetas lógicas comerciales diferentes y complejas, pero la lista de mensajes de chat todavía tiene mucho contenido único, como la lectura del almacenamiento de la base de datos, el envío y recepción de mensajes, la actualización en tiempo real, etc., pero en este artículo ignoraremos estos contenidos por ahora. Primero configure una bandera aquí, si tiene tiempo, escriba otro artículo para presentar la administración de datos de mensajes de mensajería instantánea y cómo controlar la visualización de la lista de mensajes. Espero que este artículo pueda serte de alguna ayuda en tu desenvolvimiento diario, si hay alguna deficiencia por favor corrígeme.

¿Qué es un complemento?

En muchos proyectos, hay más o menos diseños de complementos, pero muchos diseños de complementos no son muy buenos, la razón probable es que existe una desviación en la comprensión de las características esenciales de los complementos. Por ejemplo, la definición original de "complemento" en Tantan es fácil de causar confusión en la comprensión. Por ejemplo, algunos complementos se eliminan, lo que hace que todo el sistema de chat no funcione. Estas cosas no deben definirse como complementos.

Entonces, ¿qué debería ser un complemento? Creo que un complemento debe cumplir con estas características:

  1. Los complementos son complementos de las funciones del host;
  2. La eliminación de complementos no debería afectar la funcionalidad principal del host;
  3. Los complementos y el código de host son ortogonales y no se afectan entre sí.

Escenarios de aplicación del complemento de tarjeta

La siguiente es una breve descripción del escenario actual de la aplicación. Actualmente, hay alrededor de 120+ mensajes circulando en la lista de mensajes de chat de Tantan IM. Muchos mensajes tienen una lógica especial además de mostrarse. Vamos a describirlos brevemente a continuación.

  1. Haga clic para saltar a páginas especiales : como mensajes de invitación, mensajes de eventos, detalles de salto en el flujo de alimentación, etc.;
  2. Hay botones de función especiales : por ejemplo, para mensajes de votación, hay un botón Me gusta en la tarjeta;
  3. Mostrar datos comerciales sincrónicamente : por ejemplo, el mensaje hace referencia a un estado urgente y el producto requiere una actualización del estado en tiempo real;
  4. Vinculación entre múltiples mensajes : por ejemplo, cambiar para reproducir múltiples mensajes de audio o actualizar otras tarjetas cuando se muestra una determinada tarjeta.

Echemos un vistazo a cómo diseñar la arquitectura para satisfacer estas necesidades de manera elegante.

¿Cuáles son los contenidos de la tarjeta de mensaje ViewModel?

MessageCardViewModel es el modelo responsable de transportar información de representación de tarjetas de mensajes y herramientas de procesamiento lógico. Las fuentes de datos de la interfaz de usuario de mensajes y el procesamiento lógico pasan a través de la información de ViewModel y las herramientas adjuntas. Transporta principalmente contenido estático después del análisis de mensajes y también vincula algunas herramientas con capacidades de procesamiento lógico e información de configuración empresarial. Varios mensajes pueden ser polimórficos a través de BaseMessageCardViewModel.

Introduzcamos qué contenido se incluye en ViewModel, qué clases están involucradas y qué hacen estas clases: Cabe
señalar que para evitar que ViewModel se modifique accidentalmente durante el proceso de transferencia del flujo de datos, todos los atributos externos son de solo lectura. el flujo de datos desde la producción de datos hasta el consumo es unidireccional, el siguiente es el contenido específico contenido en ViewModel

1. Contenido de análisis de mensajes

El contenido del análisis de mensajes es analizar los datos originales del mensaje en datos utilizados directamente por la tarjeta de mensaje. BaseMessageCardViewModel contiene los datos originales del mensaje, así como los atributos analizados a través del mensaje que se pueden usar directamente de abajo hacia arriba. visualización, como texto mostrado, etc.

Otros mensajes pueden ensamblar los atributos que necesitan heredando BaseMessageCardViewModel. Por ejemplo, VideoMessageCardViewModel puede heredar y agregar el atributo videoInfo. Este atributo también se analiza a partir de los datos originales del mensaje. La interfaz de usuario correspondiente se puede representar a través de videoInfo y otra información.

2. Información de configuración

Se pasa a través del proxy de la lista y se vincula a un ViewModel específico a través de MessageCardViewModelFactory. La información de configuración incluye configuración del tema, configuración de estilo, etc.

Configuración del tema, incluido el color, fuente, fondo, etc., de cada elemento de la interfaz de usuario.
Configuración del estilo, que incluye si se muestran apodos, notas, si se necesitan avatares borrosos, URL de avatar personalizadas, etc.

Por ejemplo, este estilo de texto requiere que el agente devuelva diferentes colores de fondo de burbuja para diferentes mensajes según la lógica del producto específico y luego los vincule al ViewModel. La interfaz de usuario de la tarjeta de mensaje utiliza directamente el campo de color de fondo correspondiente a la información del tema en ViewModel. para rendir.
Por favor agregue una descripción de la imagen.

3. Información del componente de la interfaz de usuario de la tarjeta

Los componentes de la interfaz de usuario de la tarjeta se refieren a componentes de la interfaz de usuario que se pueden representar de forma independiente a través del modelo MessageCardViewModel. Cada componente de la interfaz de usuario tiene el mismo método de inicialización de información y método de actualización de contenido, y cada componente de la interfaz de usuario independiente se puede reutilizar de manera flexible. En otras palabras, puede obtener el nombre de la clase y el ViewModel correspondiente para representar y los gestos interactivos internos. Por lo general, una tarjeta de mensaje es un contenedor que contiene varios componentes de la interfaz de usuario de la tarjeta, por lo que la información del componente de la interfaz de usuario de la tarjeta contiene principalmente una matriz de clase de componentes de la interfaz de usuario.

Esta parte del contenido se registra externamente según el tipo de mensaje y luego se vincula al ViewModel específico a través de MessageCardViewModelFactory.

Pongamos un ejemplo para ilustrar:

Cada elemento enmarcado en amarillo oscuro es un componente de interfaz de usuario de tarjeta independiente y cada elemento enmarcado en rojo es una tarjeta de mensaje.
El mensaje anterior se refiere a una dinámica y contendrá un componente de UI dinámico y un componente de UI de mensaje de texto normal; el
siguiente mensaje se refiere a un tema y contendrá un componente de UI de tema y un componente de mensaje de texto normal.
La parte de acceso empresarial puede registrar el componente de interfaz de usuario de la tarjeta correspondiente según el tipo de mensaje correspondiente.

Por favor agregue una descripción de la imagen.
四、MessageCardPlugin

MessageCardPlugin se presentará en detalle más adelante. De manera similar a la información del componente de la interfaz de usuario de la tarjeta, también se registra de acuerdo con el tipo de mensaje a través de la parte de acceso comercial y luego se vincula a un ViewModel específico a través de MessageCardViewModelFactory. La celda de mensaje (componente de la interfaz de usuario de la tarjeta) puede obtener el MessageCardPlugin directamente desde ViewModel e interactuar directamente con los datos comerciales, evitando así la necesidad de pasarlo a través del delegado comercial al cellDelegate y luego al ViewDelegate correspondiente, etc. transmisión de capa, que requiere muchos cambios cada vez que se cambia la interfaz situación de capa.

MessageCardPlugin es responsable de proporcionar fuentes de datos comerciales para tarjetas de mensajes y, al mismo tiempo, puede actualizar total o parcialmente la interfaz de usuario inicializando las herramientas de contexto entrantes. Cada componente de la interfaz de usuario de la tarjeta dentro de la tarjeta de mensaje puede obtener el MessageCardPlugin correspondiente a través de ViewModel.

En la misma sesión de chat, los mensajes de la misma empresa pueden registrar el mismo MessageCardPlugin, de modo que varias tarjetas de mensajes puedan contener la misma instancia de MessageCardPlugin y, por lo tanto, tener una fuente de datos comerciales común.

Dado que es poco probable que el mismo mensaje pertenezca a dos empresas al mismo tiempo, para evitar riesgos de desarrollo, solo se puede vincular un complemento a cada tipo de mensaje para aislar cada empresa. Si realmente hay una situación que abarca varias empresas, el complemento se puede implementar internamente utilizando casos pseudoúnicos u otros métodos de memoria compartida para evitar dañar la arquitectura de la lista de mensajes.

Publique una imagen para ver cómo se genera ViewModel. Entre ellos, el análisis de mensajes correspondiente a la clase ViewModel específica, el complemento y la información del componente UI están registrados por la parte de acceso comercial.

Por favor agregue una descripción de la imagen.

como trabajar

Volvamos a los diversos problemas mencionados en la sección #Escenario de aplicación y veamos cómo resolverlos elegantemente a través de MessageCardPlugin:

  1. Hacer clic para saltar a una página especial y tener un botón de función especial son esencialmente el mismo problema. Puede exponer interfaces lógicas funcionales como saltos comerciales o me gusta al complemento correspondiente al mensaje. La celda del mensaje puede obtener el complemento a través de ViewModel para Llame a la función comercial correspondiente.

  2. Visualización sincrónica de datos comerciales : esto también es relativamente simple. La celda del mensaje obtiene el complemento a través de ViewModel. El complemento puede interactuar con empresas específicas internamente. Puede obtener directamente la información de la caché de acuerdo con el campo de ID de contenido al que hace referencia el cuerpo del mensaje. u obtenerlo de forma asincrónica y actualizarlo;

  3. Vinculación entre múltiples mensajes : el complemento monitorea internamente los cambios de datos y actualiza la tarjeta de mensaje correspondiente. También puede exponer una interfaz de devolución de llamada, y la tarjeta de mensaje correspondiente escucha la interfaz de devolución de llamada. Cada vez que el contenido cambia, se notifica a la tarjeta de mensaje correspondiente para actualizar la interfaz de usuario, logrando así el vínculo entre múltiples mensajes, etc.

A continuación se muestra un ejemplo de pseudocódigo de cómo abordar el problema anterior:

// 这个是 Cell
class MomentPreviewMessageCell: BaseMessageCell {
    
    
    
    private var plugin: MomentMessageCardPlugin? {
    
    
        return viewModel.messageCardPlugin as? MomentMessageCardPlugin
    }
    
    ... 省略代码

    // 针对问题 1,处理动态点赞事件(处理特殊事件)
    private func handleTappedLikeButton() {
    
    
        plugin.performLikeAction(viewModel.momentID)
    }

    override func render(_ viewModel: BaseMessageCardViewModel) {
    
    
        super.render(viewModel)
        // 从 plugin 获取对应的业务数据, 刷新 UI
        renderMoment(plugin.moment(viewModel.momentID))
    }
    ... 省略代码
}

class MomentMessageCardPlugin: BaseMessageCardPlugin {
    
    
    
    // 针对问题 1,
    func performLikeAction(_ momentID: String) {
    
    
        // 请求 like 接口
        requestLike(momentID) {
    
     success in
            // updateCaches
            // 完成回调, 刷新消息卡片
            context.reloadMessageCard()
        }
    }
    
    // 为消息卡片提供,业务方面的数据源
    func moment(momentID: String) -> Moment? {
    
    
        // 优先获取缓存
        if let moment = likedMomentCaches[momentID] {
    
    
            return moment
        }
        requestMoment(momentID) {
    
     moment in 
            // updateCaches
        }
        return nil
    }
    
    // 针对问题 2、3,同步业务数据,联动刷新多个 Cell 等
    private func handleNotification(_ data: Any) {
    
    
        // 收到了业务变更的通知,保存数据源,刷新列表
        updateCaches(data)
        context.reloadMessageCards()
    }
}

Como se puede ver en el código anterior, Message Cell y MessageCardPlugin están estrechamente relacionados entre sí. En este momento, se debe prestar atención a interfaces claras y estandarizadas para garantizar que la interfaz de usuario y la lógica estén separadas. Si la lógica empresarial de MessageCardPlugin es relativamente complejo, también se requieren ciertos patrones de diseño para garantizar la calidad del código.

Resumir

Este artículo presenta brevemente el complemento de las tarjetas de mensajes de mensajería instantánea y cómo abordar los problemas planteados anteriormente. Sin embargo, no presenta la situación anterior al complemento. Carece de alguna explicación comparativa. Teniendo en cuenta que cada proyecto tiene su propio método de implementación. Y los amigos que estén interesados ​​pueden compararlo con la situación real en sus propios proyectos.

Supongo que te gusta

Origin blog.csdn.net/ID314846818/article/details/128818082
Recomendado
Clasificación