IMKit iOS Framework is the core of IMKit iOS SDK.
IMKit is a live chat platform solution, more detail please visit: https://imkit.io
- 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
- iOS 13.0+
- Xcode 12.5+
- Swift 5.4
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'
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
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'
$ 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
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(apiKey: "", clientKey: "fangho_imkit_0412_2018_001_clientkey", chatServerURL: URL(string: "https://chat.fangho.com")!, authServerURL: URL(string: "https://auth.fangho.com")!, bucket: "chatserver-upload")
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
Congratulations! From now on, leverage the powerful IMKit.
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
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()
}
}
We wrap all our task using PromiseKit. Before using IMKit, you should know how to deal with promise.
// There are tow types of chat room, direct char and group chat
IMCreateDirectChatTask().perform(roomName: <#T##String?#>, coverURL: <#T##URL?#>, description: <#T##String?#>, invitee: <#T##String#>, isSystemMessageEnabled: <#T##Bool#>)
IMCreateGroupChatTask().perform(roomName: <#T##String?#>, coverURL: <#T##URL?#>, description: <#T##String?#>, invitees: <#T##[String]#>, isSystemMessageEnabled: <#T##Bool#>)
IMAddMembersTask().perform(roomID: <#T##String#>, invitees: <#T##[String]#>, isSystemMessageEnabled: <#T##Bool#>)
IMJoinRoomTask().perform(id: <#T##String#>)
IMDeleteMemberTask().perform(roomdID: <#T##String#>, uid: <#T##String#>)
IMMuteRoomTask().perform(id: <#T##String#>)
IMUnmuteRoomTask().perform(id: <#T##String#>)
// These are for push notifications. Type needs to be `fcm` for using Firebase Cloud Messaging and `ios` for APNS
IMSubscribeTask().perform(fcmToken: <#T##String#>, type: <#T##String#>)
IMUnsubscribeTask().perform(fcmToken: <#T##String#>, type: <#T##String#>)
IMUpdateRoomTask().perform(id: <#T##String#>, name: <#T##String?#>, coverURL: <#T##URL?#>)
IMUpdateMyProfileTask().perform(nickname: <#T##String?#>, avatarURL: <#T##URL?#>, description: <#T##String?#>)
IMFetchBadgeTask().perform()
IMFetchMyProfileTask().perform()