转载

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

NMessenger is a fast, lightweight messenger component built onAsyncDisplaykit and written in Swift . Developers can inherently achieve 60FPS scrolling and smooth transitions with rich content components.

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Features

Built-in support for:

  • Text
  • Images (network and local)
  • Collection Views
  • Rich Content
  • Typing Indicators
  • Avatars
  • Custom and Layer Masked Bubbles
  • Bubble Configurations
  • Extendable Components
  • Async Head Prefetching
  • Message Groups
  • Adding, Removing, and Updating Messages (with animations)

Version Information

  • 1.0.0

Requirements

  • iOS 8.2+

Installation for Cocoapods

# For latest release in cocoapods
pod 'NMessenger'

Getting Started

NMessengerViewController

NMessenger comes with a prebuilt NMessengerViewController that has a few supported features.

  • Posting messages
  • Input bar with a custom placeholder
  • Camera and photo library access
  • Typing indicator support

Posting Messages

Send a text message.

func sendText(text: String, isIncomingMessage:Bool) -> GeneralMessengerCell

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Send a message with an image.

func sendImage(image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell

Send a message with a network image. (Uses AsyncDisplayKit with PINCache to lazyload and cache network images)

func sendNetworkImage(imageURL: String, isIncomingMessage:Bool) -> GeneralMessengerCell

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

A message with a collection view can be created directly from an array of views or nodes. Note: Nodes take advantage of ASDK's async rendering capabilities and will make this component scroll more smoothly.

func sendCollectionViewWithViews(views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell
func sendCollectionViewWithNodes(nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell

One line CollectionView

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Multi line CollectionView

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Send a message with a custom view or node. Note: Nodes take advantage of ASDK's async rendering capabilities and will make this component scroll more smoothly.

func sendCustomView(view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell
func sendCustomNode(node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

These functions are meant to be overridden for network calls and other controller logic.

Typing Indicators

Typing indicators signify that incoming messages are being typed. This will be the last message in the messenger by default.

/** Adds an incoming typing indicator to the messenger */
func showTypingIndicator(avatar: ASDisplayNode) -> GeneralMessengerCell

/** Removes a typing indicator from the messenger */
func removeTypingIndicator(indicator: GeneralMessengerCell)

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

NMessenger

NMessenger can be added to any view.

self.messengerView = NMessenger(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))
messengerView.delegate = self
self.view.addSubview(self.messengerView)

With NMessenger, there is no need to manage a data source. Simply add a message and forget about it.

Changing and updating a message relies on a reference. These references can be passed through a delegate method or stored locally in a class.

self.delegate.deleteMessageBtnClick(self)
.
.
.
func deleteMessageBtnClick(message: GeneralMessageCell) {
  self.messengerView.removeMessage(message, .None)
}

Message Bubbles

NMessenger comes with a few prebuilt bubble types. bubble can also easily be subclassed to create a new bubble component.

SimpleBubble

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

DefaultBubble

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

StackedBubble

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

ImageBubble - Can be used with any9 Patch Image

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

By setting hasLayerMask = true , bubbles will mask their content. This is relevant for images and other rich content components.

Bubble Configuration

In order to configure custom bubbles for the messenger, you must create a new class that implements BubbleConfigurationProtocol .

/** Configures a bubble for a ContentNode. Implement this to create your own bubble configuration */
protocol BubbleConfigurationProtocol {
    var isMasked: Bool {get set}

    /** Create and return a UI color representing an incoming message */
    func getIncomingColor() -> UIColor

    /** Create and return a UI color representing an outgoing message */
    func getOutgoingColor() -> UIColor

    /** Create and return a bubble for the ContentNode */
    func getBubble() -> Bubble

    /** Create and return a bubble that is used by the Message group for Message nodes after the first. This is typically used to "stack" messages */
    func getSecondaryBubble() -> Bubble
}

This protocol is meant to provide a new instance of the bubble class for primary (messageNode) and secondary (messageGroup) bubble types. By changing var sharedBubbleConfiguration: BubbleConfigurationProtocol in NMessengerViewController , you can set the configuration for all newly added messages.

Content Nodes and Custom Components

Content Nodes

A Content Node holds message content in a MessageNode (everything inside of the bubble).

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Subclassing ContentNode gives you the ability to define your own content. This is particularly useful for creating rich content components that are not in our stock message kit. Alternatively, you can initialize a 'CustomContentNode' with your own view or node.

Content Nodes can also be given a BubbleConfigurationProtocol to customize their bubble.

GeneralMessengerCell

GeneralMessengerCell can be subclassed to make any type of component. All messenger cells extend this object.

Avatars

Custom avatars can be set with an AsyncDisplayKit ASImageNode .

let nAvatar = ASImageNode()
nAvatar.image = UIImage(named: "nAvatar")
.
.
.
messageNode.avatarNode = nAvatar

Head Prefetching

Many messengers prefetch at the head. This is not trivial with a UITableView or AysncDisplayKit features. NMessenger supports head prefetching out of the box.

To use the head prefetch feature, set var doesBatchFetch: Bool = true on NMessenger. NMessengerDelegate will also need to be implemented and set by your controller.

@objc protocol NMessengerDelegate {
    /**
     Triggered when a load batch content should be called. This method is called on a background thread.
     Make sure to add prefetched content with *endBatchFetchWithMessages(messages: [GeneralMessengerCell])**/
    optional func batchFetchContent()
    /** Returns a newly created loading Indicator that should be used at the top of the messenger */
    optional func batchFetchLoadingIndicator()->GeneralMessengerCell
}

All batch fetch network calls should be done in batchFetchContent . Make sure to add your message cells with endBatchFetchWithMessages(messages: [GeneralMessengerCell]) to end the batch fetch. Calling this function will remove the loading indicator and batch fetch lock.

Message Groups

Message Groups can be used to stack messages and animate avatars. Like MessageNode , MessageGroup extends GeneralMessageCell . The difference, however is that MessageGroup holds a table of MessageNode s rather than a ContentNode .

================
| MessageGroup | -> ===============    ===============
================    | MessageNode | -> | ContentNode | (Primary Bubble)
                    ---------------    ===============
                    | MessageNode | -> | ContentNode | (Secondary Bubble)
                    ---------------    ===============
                    | MessageNode | -> | ContentNode | (Secondary Bubble)
                    ---------------    ===============
                    | MessageNode | -> | ContentNode | (Secondary Bubble)
                    ===============    ===============

Additionally, MessageGroup determines the bubble type of the MessageNode 's content based on the position in the table. The first message's content will have a primary bubble, the rest will have a secondary bubble. Typically, the avatar will be disabled on any MessagesNode in the group, but kept for the MessageGroup .

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Adding, Removing, and Updating

Message Groups include a few slick animations for Adding, Removing, and Updating MessageNodes in the group. These can be called directly from MessageGroup or Added and Removed from NMessenger . Note: These are not surfaced in the NMessengerViewController yet

It is recommended that they are removed from NMessenger because of the possibility that the MessageNode removed was the last message in the group. If this happens, the MessageGroup will remain after the MessageGroup was removed. NMessenger makes sure that in this case the MessageGroup is removed from the messenger.

Adding

To add a MessageNode .

messageGroup.addMessageToGroup(message: GeneralMessengerCell, completion: (()->Void)?)

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Removing

To remove a MessageNode .

messageGroup.removeMessageFromGroup(message: GeneralMessengerCell, completion: (()->Void)?)

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Updating

To update an existing MessageNode with a new MessageNode .

messageGroup.replaceMessage(message: GeneralMessengerCell, withMessage newMessage: GeneralMessengerCell, completion: (()->Void)?)

[iOS] 一款构建于 AsyncDisplaykit 上的快速、轻量的消息组件

Authors

  • Aaron Tainter
  • David Schechter
原文  https://github.com/eBay/NMessenger
正文到此结束
Loading...