Skip to content
howardfuntek edited this page Jan 8, 2023 · 6 revisions

IMKit iOS Framework v3.0

IMKit iOS Framework is the core of IMKit iOS SDK.

About IMKit

IMKit is a live chat platform solution, more detail please visit: https://imkit.io

Features

  • Room list / Chat room
  • Support text, sticker, image, video, audio, location message
  • Support reply message
  • URL detection and preview
  • Typing indicator
  • Support Traditional Chinese and English

Requirements

  • iOS 10.0+
  • Xcode 10.1+
  • Swift 4.2+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate IMKit into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'IMKit', :git => 'https://github.com/imkit/imkit-ios-framework-v3.git', :branch => 'swift5.7'
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
    end
  end
  installer.pods_project.build_configurations.each do |config|
    config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
  end
end

We enhanced IGListKit and SwiftLinkPreview to fit our need. So also specify them in your Podfile:

pod 'IGListKit', :git => 'https://github.com/imkit/IGListKit.git'
pod 'SwiftLinkPreview', :git => 'https://github.com/imkit/SwiftLinkPreview.git'

Note: If you run app using simulators, add arm64 for Excluded Architectures in target's Build Settings. https://stackoverflow.com/questions/66948010/no-such-module-error-in-xcode-12-4-apple-m1

Quick Start - Demo App

$ git clone https://github.com/imkit/imkit-ios-sdk-v3.git
$ cd imkit-ios-sdk-v3/
$ pod install
$ open imkit-ios-sdk-v3-demo.xcworkspace

Integration

Initial Settings

In your App Delegate, initialize IMKit with your client key and chat server url:

import IMKit
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    IMKit.configure(clientKey: "fangho_imkit_0412_2018_001_clientkey", chatServerURL: URL(string: "https://chat.fangho.com")!)
    return true
}

In demo app, we use IMFetchTokenTask to get the token just for demo. In real case, your backend needs to provide a token, then initialize IMKit with token and user id.(Our chat server will ask your backend if the token is validated.)

IMKit.token = token
IMKit.uid = uid

Then, specify following privacy purpose String in Info.plist.

Privacy - Camera Usage Description
Privacy - Microphone Usage Description
Privacy - Photo Library Additions Usage Description
Privacy - Photo Library Usage Description

Congratulations! From now on, leverage the powerful IMKit.

UI

There are tow main classes. One is IMRoomsViewController, the other is IMMessagesViewController. You can use them anywhere in your iOS app:

let vc = UINavigationController(rootViewController: IMRoomsViewController())
present(vc, animated: true)

// Or
navigationController?.pushViewController(IMRoomsViewController(), animated: true)

// Or
navigationController?.pushViewController(IMMessagesViewController(roomID: room.id), animated: true)

We provide customizable UI. Place the code before using IMKit ui elements.

// For example
IMStyle.rooms.backgroundColor = UIColor(red: 249/255, green: 249/255, blue: 249/255, alpha: 1)
IMStyle.rooms.cell.height = 66
IMStyle.rooms.cell.title.font = UIFont.systemFont(ofSize: 17, weight: .regular)
IMStyle.messages.inputAccessory.textBar.cornerRadius = 17
IMStyle.messages.outgoingCell.borderWidth = 1

Advanced

Override IMRoomsViewController or IMMessagesViewController to do anything you want.

// For example
class RoomsViewController: IMRoomsViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let logoutButton = UIBarButtonItem(title: "登出", style: .plain, target: self, action: #selector(logout))
        navigationItem.setLeftBarButton(logoutButton, animated: false)
    }
    
    override func didSelectRoom(room: IMRoom) {
        navigationController?.pushViewController(MessagesViewController(roomID: room.id), animated: true)
    }
    
    @objc func logout() {
        IMKit.logout()
        navigationController?.dismiss(animated: true, completion: nil)
    }
    
    override func emptyView(for listAdapter: ListAdapter) -> UIView? {
        if viewModel.state == .Loaded {
            let imageView = UIImageView(image: UIImage(named: "empty"))
            imageView.contentMode = .scaleAspectFill
            return imageView
        } else {
            return nil
        }
    }
}
class MessagesViewController: IMMessagesViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
        inputBarViewController.sendButton.setImage(UIImage(named: "sent"), for: .normal)
        inputBarViewController.addButton.setImage(UIImage(named: "add"), for: .normal)
        let image = UIImage(named: "happy")?.withRenderingMode(.alwaysTemplate)
        inputBarViewController.stickerButton.setImage(image, for: .normal)
        inputBarViewController.stickerButton.tintColor = UIColor(red: 158/255, green: 158/255, blue: 158/255, alpha: 1)
        
        let imagePickerViewController = UIImagePickerController()
        imagePickerViewController.delegate = inputBarViewController
        inputBarViewController.photosImagePicker = imagePickerViewController
        
        bottomButton.setImage(UIImage(named: "btnBackToButton"), for: .normal)
        
        let infoButton = UIBarButtonItem(image: UIImage(named: "setting"), style: .plain, target: self, action: #selector(infoButtonTapped))
        infoButton.tintColor = UIColor(red: 47/255, green: 60/255, blue: 75/255, alpha: 1)
        navigationItem.setRightBarButton(infoButton, animated: false)
        
        let backButton = UIBarButtonItem(title: nil, style: .plain, target: self, action: #selector(back))
        backButton.image = UIImage(named: "back")
        backButton.tintColor = UIColor(red: 47/255, green: 60/255, blue: 75/255, alpha: 1)
        navigationItem.setLeftBarButton(backButton, animated: false)
    }
    
    @objc func back() {
        _ = navigationController?.popViewController(animated: true)
    }
    
    override func messageDidSelect(_ message: IMMessage) {
      
    }
    
    override func infoButtonTapped() {
        
    }
    
    override func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
        if object is IMDate {
            return IMDateSectionController()
        } else if object is String {
            return IMTypingSectionController()
        }
        if let message = object as? IMMessage {
            switch message.type {
            case .Text:
                return TextMessageSectionController()
            case .Image:
                return ImageMessageSectionController()
            case .Audio:
                return AudioMessageSectionController()
            case .Video:
                return VideoMessageSectionController()
            case .File:
                return FileMessageSectionController()
            case .Location:
                return MapMessageSectionController()
            case .Sticker:
                return StickerMessageSectionController()
            case .System:
                return IMSystemMessageSectionController()
            case .Other:
                return TextMessageSectionController()
            }
        }
        return TextMessageSectionController()
    }
}

Tasks

We wrap all our task using PromiseKit. Before using IMKit, you should know how to deal with promise.

Clone this wiki locally