使用磁铁将用户聊天添加到iOS应用程序

越来越多的移动应用程序提供了使用该应用程序向其他用户发送消息的功能。 例如,在许多游戏中,您可以与其他玩家聊天,而聊天应用程序则允许您与喜欢的人聊天。 可能性是无止境。 将用户聊天添加到应用程序可能是应用程序的重要功能。

构建一种使用户能够彼此聊天的解决方案是许多开发人员宁愿回避的艰巨任务。 幸运的是,无需重新发明轮子。 Magnet Message是一个开放源代码移动消息传递框架,非常适合此用例。 他们提供iOS和Android支持以及REST API。 多亏了他们的沙箱环境 ,Magnet Message的入门操作变得轻松快捷。

在本教程中,您将学习如何使用Swift 2将Magnet Message集成到iOS应用程序中。您将学习在项目中设置Magnet Message并将消息发送给应用程序的其他用户是多么容易。 首先创建一个帐户并设置沙箱。

先决条件

即使iOS的Magnet库是用Objective-C编写的,在本教程中,我仍将使用Xcode 7.1和Swift 2.1。 您可以从Apple的开发人员网站或从App Store下载Xcode 7.1。

1.创建一个磁铁帐户

在开始将Magnet集成到移动应用程序中之前,我们需要一个Magnet帐户。 借助Magnet帐户,您可以访问用于开发的沙盒环境以及许多可供学习的示例应用程序。 要继续学习,请导航至Magnet的开发人员网站 ,单击顶部的“ 试用 ”,然后使用电子邮件地址进行注册。

创建一个免费的磁铁帐户

2.创建沙箱应用程序

您的免费Magnet帐户可让您访问一系列资源,包括可用于开发的沙箱。 转到developer.magnet.com并转到沙箱。 您立即注意到沙盒已经包含三个应用程序。 这些应用程序中的每一个都与示例应用程序之一相对应。

沙箱应用

对于本教程,我们将创建一个新的应用程序。 单击右上角的绿色加号按钮创建一个新应用程序并将其命名为MessageMe

创建一个新的应用程序

单击“ 保存”时 ,沙盒会自动打开应用程序并显示入门指南。 单击顶部的Apple徽标以显示iOS的说明。

入门指南

您可以跳过说明,因为我将指导您完成设置过程。 我们需要开始使用一种资源,该属性包含Magnet应用程序的配置。 在“ 构建应用程序”部分的第二步中,您可以看到下载MagnetMax.plist的链接。 单击链接将属性列表下载到您的计算机。 稍后我们将需要它。

如果打开MagnetMax.plist ,将会看到它包含三个键值对, BaseURLClientIDClientSecret 。 磁铁的库将使用此信息与“磁铁消息”后端进行交谈。

3.设置项目

启动Xcode 7.1,然后从iOS>应用程序模板列表中选择“ 单一视图应用 程序”模板。

选择单视图应用程序模板

将应用程序命名为MessageMe ,将Language设置为Swift ,将Devices设置iPhone ,并取消选中底部的复选框。 告诉Xcode您要将项目保存到何处,然后点击创建

配置项目

4.设置CocoaPods

正如我前面提到的,Magnet开发了一个开源库,用于与Magnet Message后端进行交互。 将库集成到Xcode项目中的最简单方法是通过CocoaPods。 关闭刚刚创建的项目,打开“ 终端”窗口,然后导航到项目的根目录。 通过从命令行执行pod init命令,为您的项目创建Podfile

Podfile位于项目的根目录。 在文本编辑器中将其打开,并将其内容替换为以下内容。

source 'https://github.com/CocoaPods/Specs'
source 'https://github.com/magnetsystems/Specs'

platform :ios, '9.0'
use_frameworks!

target 'MessageMe' do
  pod 'MagnetMax', '~> 2.0'
end

在命令行中,执行pod install命令以安装Podfile中指定的依赖 。 这将安装Magnet提供的MagnetMax库 ,该用于与Magnet Message API进行交互。 还将创建一个从现在开始将使用的工作空间。 完成安装过程后,在项目的根目录下打开MessageMe.xcworkspace

5.设置磁铁

步骤1:添加MagnetMax.plist

设置和配置磁铁非常容易。 在本教程的前面,您从Magnet的沙箱下载了MagnetMax.plist 。 将此属性列表添加到MessageMe工作区中的MessageMe项目。 因为   磁铁最大列表   包含敏感数据,我已将其从源代码管理中排除,因此在本教程的源文件中将找不到它。

添加MagnetMaxplist

步骤2:导入MagnetMax框架

打开AppDelegate.swift并为我们通过CocoaPods安装的MagnetMax框架添加导入语句。

import UIKit
import MagnetMax

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    ...

}

步骤3:设定磁铁

application(_:didFinishLaunchingWithOptions:) ,在MagnetMax类上调用setupWithConfiguration(_:) ,在我们要使用的MagnetMax.plist传入配置名称。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Setting Up Magnet
    let configurationFile = NSBundle.mainBundle().pathForResource("MagnetMax", ofType: "plist")
    let configuration = MMPropertyListConfiguration(contentsOfFile: configurationFile!)
    MagnetMax.configure(configuration!)
    
    return true
}

步骤4:建立并执行

在物理设备或模拟器上构建并运行目标,以确保所有设置均正确。 如果遇到问题,请确保已正确执行上述步骤。

6.注册用户

在用户可以向其他用户发送消息之前,她需要在我们的应用程序中创建一个帐户。 Magnet的帐户系统简单而透明,注册用户也很容易实现。 在本部分中,我们将创建一个简单的表单,以使用户能够创建帐户,或者如果他们已经有一个帐户,则登录到其帐户。

步骤1:建立课程

在创建用户界面之前,我们需要创建两个UIViewController子类MessageViewControllerSignInViewController 。 第一个视图控制器将负责发送消息。 第二个视图控制器将管理用户注册以及登录过程。

创建一个View Controller子类

步骤2:建立使用者介面

打开Main.storyboard ,选择已经存在的视图控制器,然后从Xcode的Editor菜单中选择Embed In> Navigation Controller 。 打开右侧的对象库 ,然后在视图控制器的导航栏中添加一个栏按钮项。 选中条形按钮项目后,在Attributes Inspector中将System Item设置为Compose

添加撰写栏按钮项

对象库中拖动视图控制器,并将其类设置为Identity Inspector中的 MessageViewController 。 从撰写栏按钮项到消息视图控制器创建一个序列 ,将Kind设置为Present Modally 。 在消息视图控制器的顶部添加一个导航栏,在左侧添加一个栏按钮项。 在“ 属性”检查器中 ,将“ 系统项目 设置为“完成”

将两个常规按钮添加到消息视图控制器,并将它们放置在视图中。 这使得在必要时更容易隐藏两个按钮。 将按钮的标题分别设置为“ 登录”和“ 创建帐户”

添加登录并创建帐户按钮

最后,添加另一个视图控制器,并将其类设置为Identity Inspector中的 SignInViewController 。 在顶部添加导航栏,在左侧添加栏按钮项。 在“ 属性”检查器中将“ 系统项目”设置为“ 取消 ”。 将两个文本字段添加到视图控制器,一个用于用户的用户名,另一个用于用户的密码。 不要忘记在“ 属性”检查器中选中“ 安全文本输入”以获取密码文本字段。 最后但并非最不重要的一点是,在文本字段下方添加一个按钮,并将其标题设置为Sign In

从消息视图控制器的“ 登录”按钮到登录视图控制器创建一个序列并将序列的标识符设置为SegueSignIn 。 对“ 创建帐户”按钮重复此步骤,并将segue的标识符设置为SegueCreateAccount 。 两种说法都应该是Show

添加登录视图控制器

步骤3:建立销售点

打开MessageViewController.swift并为“ 登录”和“ 创建帐户”按钮所在的视图声明一个出口。 请注意,我还为导航栏中的“完成”按钮创建了一个动作。 不要忘记在故事板上连接插座和动作。 为了易于使用,我还为segue标识符声明了两个常量。

import UIKit

class MessageViewController: UIViewController {
    
    let SegueSignIn = "SegueSignIn"
    let SegueCreateAccount = "SegueCreateAccount"
    
    @IBOutlet weak var buttonsView: UIView!
    
    // MARK: -
    // MARK: Actions
    @IBAction func done(sender: UIBarButtonItem) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    
}

打开SignInViewController.swift并声明三个出口和一个辅助变量,如下所示。 helper变量将帮助我们确定用户是点击“ 登录”还是“ 创建帐户”按钮。 我还为“ 登录”和“ 取消”按钮创建了动作。 在继续之前,将所有内容都连接到情节提要中。

import UIKit

class SignInViewController: UIViewController {

    @IBOutlet weak var signInButton: UIButton!
    @IBOutlet weak var usernameTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    
    var hasAccount = true
    
    // MARK: -
    // MARK: Actions
    @IBAction func signIn(sender: UIButton) {
        
    }
    
    @IBAction func cancel(sender: UIBarButtonItem) {
        
    }


}

步骤4:委派协议

当用户成功登录后,需要通知消息视图控制器。 我们可以通过创建委托协议来做到这一点。 在SignInViewController.swift的顶部,我为MagnetMax库添加了import语句,并声明了SignInViewControllerDelegate协议。 该协议包含一个方法controller(_:didSignInWithUser:) ,当用户成功登录时将调用该方法。我们还需要声明SignInViewControllerDelegate?类型的delegate属性SignInViewControllerDelegate? 保留对登录视图控制器委托的引用。

import UIKit
import MagnetMax

protocol SignInViewControllerDelegate {
    
    func controller(controller: SignInViewController, didSignInWithUser user: MMUser)
    
}

class SignInViewController: UIViewController {
    
    @IBOutlet weak var signInButton: UIButton!
    @IBOutlet weak var usernameTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    
    var delegate: SignInViewControllerDelegate?
    
    var hasAccount = true
    
    ...

}

步骤5:登入

我们需要做的第一件事是在MessageViewController类中实现prepareForSegue(_:sender:) 。 在此方法中,我们检查用户点击了哪个按钮,并通过设置其hasAccount属性来相应地配置SignInViewController实例。

// MARK: -
// MARK: Prepare for Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == SegueSignIn {
        let signInViewController = segue.destinationViewController as! SignInViewController
        
        // Configure Sign In View Controller
        signInViewController.hasAccount = true
        signInViewController.delegate = self
        
    } else if segue.identifier == SegueCreateAccount {
        let signInViewController = segue.destinationViewController as! SignInViewController
        
        // Configure Sign In View Controller
        signInViewController.hasAccount = false
        signInViewController.delegate = self
        
    }
}

请注意,我们还设置了登录视图控制器的delegate属性。 这意味着MessageViewController类需要符合SignInViewControllerDelegate协议,如下所示。 controller(_:didSignInWithUser:)方法的实现目前为空。 不要忘记为MagnetMax库添加导入语句,以避免编译器警告。

import UIKit
import MagnetMax

class MessageViewController: UIViewController, SignInViewControllerDelegate {

    ...

    // MARK: -
    // MARK: Sign In View Controller Delegate Methods
    func controller(controller: SignInViewController, didSignInWithUser user: MMUser) {
        
    }

    ...

}

现在让我们集中讨论有趣的部分,即SignInViewController类的操作。 在实现signIn(_:)cancel(_:)操作之前,我想实现viewDidLoad()方法以基于hasAccount属性的值更新“ 登录”按钮的标题。

// MARK: -
// MARK: View Life Cycle
override func viewDidLoad() {
    if hasAccount {
        signInButton.setTitle("Sign In", forState: UIControlState.Normal)
    } else {
        signInButton.setTitle("Create Account", forState: UIControlState.Normal)
    }
}

可以很容易地执行cancel(_:)操作,如下所示。

@IBAction func cancel(sender: UIBarButtonItem) {
    dismissViewControllerAnimated(true, completion: nil)
}

signIn(_:)操作更有趣。 在此操作中,我们确保用户输入了有效数据,用户名和密码,然后根据hasAccount属性的值调用帮助程序方法。

@IBAction func signIn(sender: UIButton) {
    guard let username = usernameTextField.text else {
        showAlertWithTitle("Username Required", message: "Enter a valid username.")
        return
    }
    
    guard let password = passwordTextField.text else {
        showAlertWithTitle("Password Required", message: "Enter a valid password.")
        return
    }
    
    guard !username.isEmpty && !password.isEmpty else {
        showAlertWithTitle("Error", message: "Enter a valid username and password.")
        return;
    }
    
    // Create Credential
    let credential = NSURLCredential(user: username, password: password, persistence: .None)
    
    if hasAccount {
        signInWithCredential(credential)
    } else {
        createAccountWithCredential(credential)
    }
}

showAlertWithTitle(_:message:)方法是用于向用户显示警报的私有便捷方法。

// MARK: -
// MARK: Helper Methods
private func showAlertWithTitle(title: String, message: String) {
    // Initialize Alert Controller
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    
    // Configure Alert Controller
    alertController.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
    
    // Present Alert Controller
    presentViewController(alertController, animated: true, completion: nil)
}

createAccountWithCredential(_:)方法是另一个用于注册用户的私有帮助器方法。 我们首先创建MMUser类的实例。 此类表示Magnet Message后端的用户。 我们通过调用registerWithCredential(_:success:failure:)注册用户,传入NSURLCredential对象和两个闭包。

private func createAccountWithCredential(credential: NSURLCredential) {
    // Create User
    let user = MMUser()
    
    // Configure User
    user.userName = credential.user
    user.password = credential.password
    
    // Register User
    user.register({ (user) -> Void in
        // Sign User In
        self.signInWithCredential(credential)
        
        }) { (error) -> Void in
            print(error)
            
            if error.code == 409 {
                // Account Already Exists
                self.signInWithCredential(credential)
                
            } else {
                // Notify User
                self.showAlertWithTitle("Error", message: "We were unable to create an account. Please try again.")
            }
    }
}

如果注册成功,我们将通过调用signInWithCredential(_:)立即登录用户。 如果出现问题,我们将检查传递给我们的错误。 如果错误代码等于409 ,我们知道用户不小心用现有凭据创建了一个帐户。 这样就可以使用户登录,而不是向他们显示警报。 如果注册失败,我们会向用户显示警报。

signInWithCredential(_:)方法不太复杂。 如果登录成功,则通过在MagnetMax上调用initModule(_:success:failure:)来初始化消息模块。 我们将用户名存储在用户默认数据库中,并通过将MMUser实例传递给该委托来通知委托。 我们还将关闭登录视图控制器。 如果登录用户失败,我们将向用户显示警报。

private func signInWithCredential(credential: NSURLCredential) {
MMUser.login(credential, success: { () -> Void in
    MagnetMax.initModule(MMX.sharedInstance(), success: { () -> Void in
        // Store Username in User Defaults
        NSUserDefaults.standardUserDefaults().setObject(credential.user, forKey: "username")
        
        // Notify Delegate
        self.delegate?.controller(self, didSignInWithUser: MMUser.currentUser()!)
        
        // Pop View Controller
        self.dismissViewControllerAnimated(true, completion: nil)
        
        }, failure: { (error) -> Void in
            print(error)
            
            // Notify User
            self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
    })
    
    }) { (error) -> Void in
        print(error)
        
        // Notify User
        self.showAlertWithTitle("Error", message: "We were unable to sign you in. Please make sure that the credentials you entered are correct.")
}

在物理设备或模拟器上运行该应用程序以测试到目前为止所获得的结果。 请注意,用户名不能包含空格。 现在,您应该可以注册为用户了。

7.创建表格

步骤1:建立使用者介面

用户登录后,她应该能够使用该应用程序将消息发送给其他人。 让我们从创建用于编写消息的表单开始。 在我们重新访问Main.storyboard之前,我们将声明一些出口和一个动作。

我们首先声明一个名为messageView的出口。 当用户登录时,我们将显示此视图。同时,我们隐藏buttonsView ,其中包含“ 登录”和“ 创建帐户”按钮。

消息视图将包含用于输入收件人的文本字段,用于消息本身的文本字段,用于在消息中包括用户位置的开关以及用于发送消息的按钮。 还要注意, MessageViewController类符合UITextFieldDelegate协议。 我将在本教程的后面部分解释为什么。

我还添加了两个操作。 点击“ 发送消息”按钮将触发sendMessage(_:)操作。 当用户打开开关时,会调用locationSwitchDidChange(_:)操作。

import UIKit
import MagnetMax

class MessageViewController: UIViewController, UITextFieldDelegate, SignInViewControllerDelegate {
    
    let SegueSignIn = "SegueSignIn"
    let SegueCreateAccount = "SegueCreateAccount"
    
    @IBOutlet weak var messageView: UIView!
    @IBOutlet weak var buttonsView: UIView!
    
    @IBOutlet weak var sendButton: UIButton!
    @IBOutlet weak var locationSwitch: UISwitch!
    @IBOutlet weak var messageTextField: UITextField!
    @IBOutlet weak var recipientsTextField: UITextField!
    
    ...
    
    @IBAction func sendMessage(sender: UIButton) {
        
    }
    
    @IBAction func locationSwitchDidChange(sender: UISwitch) {
        
    }
    
    ...

}

消息视图控制器的用户界面发生了很大变化,如下所示。 有几点要指出。

  • 消息视图控制器应设置为收件人文本字段(顶部文本字段)的委托。
  • 应该在“ 属性”检查器中将位置开关设置为关闭,并且需要将locationSwitchDidChange(_:)操作连接到“ Value Changed”事件。
  • Touch Up Inside事件连接到我们刚才在MessageViewController类中声明的sendMessage(_:)操作。
创建表单以发送消息

步骤2:显示表格

我们仅在用户登录时显示表单。我们可以通过属性观察器轻松地执行此操作。 首先创建类型为MMXUser?的属性user MMXUser? 在消息视图控制器中,并向其添加didSet属性观察器。 在didSet属性观察器中,我们调用一个辅助方法updateView()

var user: MMUser? {
    didSet {
        updateView()
    }
}

updateView()方法的实现很简单。 我们还实现了setupView()方法,该方法在MessageViewController类的viewDidLoad()方法中调用。

// MARK: -
// MARK: View Methods
func setupView() {
    updateView()
}

func updateView() {
    let signedIn = (user != nil)
    buttonsView.hidden = signedIn
    messageView.hidden = !signedIn
}
// MARK: -
// MARK: View Life Cycle
override func viewDidLoad() {
    super.viewDidLoad()
    
    setupView()
}

剩下要做的唯一事情就是在controller(_:didSignInWithUser:)委托方法中更新消息视图控制器的用户属性。

// MARK: -
// MARK: Sign In View Controller Delegate Methods
func controller(controller: SignInViewController, didSignInWithUser user: MMUser) {
    self.user = user
}

运行该应用程序,登录到您的帐户,并确保该表单显示在消息视图控制器中。

8.获取用户的位置

获取用户位置非常简单,尤其是在iOS 9中。从iOS 9开始, CLLocationManager类声明一个方法requestLocation() ,以向操作系统询问设备的位置。 让我们看看它是如何工作的。

步骤1:更新Info.plist

为了使这项工作有效,我们首先需要在目标的Info.plist中添加一个条目。 我们需要添加的是一条消息,通知用户为什么我们需要访问他们的位置。 在Xcode中打开目标的Info.plist ,并添加一个新行,其键为NSLocationWhenInUseUsageDescription ,值MessageMe想使用您的当前位置。

步骤2:声明属性

我们还需要在MessageViewController类中声明两个属性,即位置管理器的属性和当前位置的属性。 两者都是可选的。

import UIKit
import MagnetMax
import CoreLocation

class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate {
    
    let SegueSignIn = "SegueSignIn"
    let SegueCreateAccount = "SegueCreateAccount"
    
    @IBOutlet weak var messageView: UIView!
    @IBOutlet weak var buttonsView: UIView!
    
    @IBOutlet weak var sendButton: UIButton!
    @IBOutlet weak var locationSwitch: UISwitch!
    @IBOutlet weak var messageTextField: UITextField!
    @IBOutlet weak var recipientsTextField: UITextField!
    
    var locationManager: CLLocationManager?
    var currentLocation: CLLocation?
    
    ...

}

请注意,我们还为CoreLocation框架添加了一个import语句, 并使 MessageViewController类符合CLLocationManagerDelegate协议。

步骤3:请求权限

然后,我们更新locationSwitchDidChange(_:)方法,该方法在位置开关的值更改时触发。 当开关打开时,我们调用requestLocation()

@IBAction func locationSwitchDidChange(sender: UISwitch) {
    if sender.on {
        requestLocation()
    }
}

requestLocation()方法是一个私有帮助器方法,我们在其中设置了位置管理器。 在我们向操作系统询问设备的位置之前,我们先验证我们是否有权这样做。 如果不这样做,我们首先通过调用requestWhenInUseAuthorization()来请求用户的许可。

// MARK: -
// MARK: Helper Methods
private func requestLocation() {
    if locationManager == nil {
        // Initialize Location Manager
        let locationManager = CLLocationManager()
        
        // Configure Location Manager
        locationManager.delegate = self
        
        // Set Location Manager
        self.locationManager = locationManager
    }
    
    if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
        // Request Location
        locationManager?.requestLocation()
    } else {
        // Ask User for Permission
        locationManager?.requestWhenInUseAuthorization()
    }
}

通过请求用户的许可,将提示用户许可。 用户做出决定(允许或拒绝许可)后,将调用一个委托方法locationManager(_:didChangeAuthorizationStatus:) 。 在这种方法中,如果允许我们请求位置。

// MARK: -
// MARK: Location Manager Delegate Methods
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    if status == .AuthorizedWhenInUse {
        locationManager?.requestLocation()
    }
}

请求设备位置时,将调用CLLocationManagerDelegate协议的两个委托方法之一:

  • 如果操作系统已找到设备,则会调用locationManager(_:didUpdateLocations:)
  • 如果由于某种原因无法找到设备,则会调用locationManager(_:didFailWithError:)
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location = locations.first {
        // Update Current Location
        currentLocation = location
    }
}

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    locationSwitch.setOn(false, animated: true)
}

locationManager(_:didUpdateLocations:) ,我们将位置存储在currentLocation属性中。

9.选择收件人

步骤1:创建RecipientsViewController

难题的最后一步是选择要发送邮件的收件人。 创建一个新类RecipientsViewController ,并为MagnetMax库添加一个import语句。 在顶部,声明一个协议RecipientsViewControllerDelegate ,以告知委托用户用户选择了哪些收件人。 委托将是消息视图控制器。 我们还需要一个属性来保留对委托的引用。

import UIKit
import MagnetMax

protocol RecipientsViewControllerDelegate {
    
    func controller(controller: RecipientsViewController, didSelectRecipients recipients: [MMUser])
    
}

class RecipientsViewController: UIViewController {
    
    var delegate: RecipientsViewControllerDelegate?

    ...

}

在创建视图控制器的用户界面之前,为表视图声明一个出口,并执行以下两个操作。

class RecipientsViewController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!
    
    ...
    
    // MARK: -
    // MARK: Actions
    @IBAction func cancel(sender: UIBarButtonItem) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    
    @IBAction func done(sender: UIBarButtonItem) {
        
    }

}

步骤2:建立使用者介面

用户界面非常简单。 在顶部添加一个导航栏,并在其中添加两个栏按钮项,左侧为 取消 ,右侧为“完成” 。 将表视图添加到视图控制器,设置其dataSourcedelegate出口,并在表视图顶部添加搜索栏。 视图控制器是搜索栏的委托,这一点很重要。

最后,创建一个从消息视图控制器到收件人视图控制器的手动序列。 将segue的标识符设置为SegueRecipients ,将Kind设置为在Attributes Inspector中 显示

创建收件人视图控制器的用户界面

步骤3:实现委托协议

打开RecipientsViewController.swift并使RecipientsViewController控制器符合UITableViewDataSourceUITableViewDelegateUISearchBarDelegate协议。

为表视图单元的重用标识符声明一个常量,并声明一个属性users ,该属性将用作表视图的数据源。 users属性的类型为[MMUser]

class RecipientsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {

    let SearchCell = "SearchCell"

    @IBOutlet weak var tableView: UITableView!
    
    var delegate: RecipientsViewControllerDelegate?
    
    var users: [MMUser] = []
    
    ...

}

viewDidLoad()方法中,注册UITableViewCell类以进行单元重用。

// MARK: -
// MARK: View Life Cycle
override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: SearchCell)
}

UITableViewDataSource协议的实现也很简单。 我们显示将从“磁贴消息”后端获取的每个用户的用户名。

// MARK: -
// MARK: Table View Data Source Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return users.count > 0 ? 1 : 0
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return users.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(SearchCell, forIndexPath: indexPath)
    
    // Fetch User
    let user = users[indexPath.row]
    
    // Configure Cell
    cell.textLabel?.text = user.userName
    
    return cell
}

func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return false
}

更有趣的是searchBar(_:textDidChange:)方法的实现。 在此方法中,我们在MMUser类上调用searchUsers(_:limit:offset:sort:success:failure:) 。 我们传入查询,要接收多少结果,偏移量,用于对结果进行排序的键以及两个闭包,一个用于成功,一个用于失败。

// MARK: -
// MARK: Search Bar Delegate Methods
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    guard searchText.characters.count > 3 else { return }
    
    MMUser.searchUsers("userName:\(searchText)*", limit: 50, offset: 0, sort: "userName:asc", success: { (users) -> Void in
        self.users = users
        self.tableView.reloadData()
        
        }) { (error) -> Void in
            print(error)
    }
}

步骤4:通知代表

当用户做出选择并点击“ 完成”按钮时,我们会将收件人的选择转发给委托,即消息视图控制器。

@IBAction func done(sender: UIBarButtonItem) {
    // Fetch Selection
    var selection: [MMUser] = []
    
    if let indexPaths = tableView.indexPathsForSelectedRows {
        for indexPath in indexPaths {
            selection.append(users[indexPath.row])
        }
    }
    
    // Notify Delegate
    delegate?.controller(self, didSelectRecipients: selection)
    
    // Dismiss View Controller
    dismissViewControllerAnimated(true, completion: nil)
}

剩下要做的就是在执行SegueRecipients segue时配置收件人视图控制器。 我们在MessageViewController类中执行此操作。 如下所示更新prepareForSegue(_:sender:)

// MARK: -
// MARK: Prepare for Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    ...

    } else if segue.identifier == SegueRecipients {
        let recipientsViewController = segue.destinationViewController as! RecipientsViewController
        
        // Configure Recipients View Controller
        recipientsViewController.delegate = self
    }
}

这也意味着我们需要声明SegueRecipients常量,并使MessageViewController类符合RecipientsViewControllerDelegate协议。

class MessageViewController: UIViewController, UITextFieldDelegate, CLLocationManagerDelegate, SignInViewControllerDelegate, RecipientsViewControllerDelegate {
    
    let SegueSignIn = "SegueSignIn"
    let SegueRecipients = "SegueRecipients"
    let SegueCreateAccount = "SegueCreateAccount"
    
    ...

}

步骤5:存储收件人

MessageViewController类,我们暂时收件人存储在一个属性, recipients ,类型[MMUser]

var recipients: [MMUser] = []

RecipientsViewControllerDelegate协议的controller(_:didSelectRecipients:)方法中,我们更新recipients属性和收件人文本字段。 我们可以使用属性观察器来完成同样的事情。

// MARK: -
// MARK: Recipients View Controller Delegate Methods
func controller(controller: RecipientsViewController, didSelectRecipients recipients: [MMUser]) {
    // Update Recipients
    self.recipients = recipients
    
    var recipientsAsStrings: [String] = []
    
    for recipient in recipients {
        recipientsAsStrings.append(recipient.userName)
    }
    
    // Update Text Field
    recipientsTextField.text = recipientsAsStrings.joinWithSeparator(", ")
}

最后,当用户点击收件人文本字段时,我们将显示收件人视图控制器。 因此,消息视图控制器需要成为收件人文本字段的委托。

// MARK: -
// MARK: Text Field Delegate Methods
func textFieldDidBeginEditing(textField: UITextField) {
    performSegueWithIdentifier(SegueRecipients, sender: self)
}

10.发送信息

现在是时候发送消息了。 MagnetMax库的简单性会让您感到惊讶。 我们通过sendMessage(_:)操作发送一条消息。

@IBAction func sendMessage(sender: UIButton) {
    guard let messageAsString = messageTextField.text else {
        showAlertWithTitle("Message Required", message: "You need to enter a message.")
        return
    }
    
    guard recipients.count > 0 else {
        showAlertWithTitle("Recipients Required", message: "You need to have at least one recipient.")
        return
    }
    
    let toRecipients = Set(recipients)
    var contents: [String : String] = ["message" : messageAsString]
    
    if let location = currentLocation {
        let coordinate = location.coordinate
        contents["location"] = "\(coordinate.latitude),\(coordinate.longitude)"
    }
    
    let message = MMXMessage(toRecipients: toRecipients, messageContent: contents)
    message.sendWithSuccess({ (invalidUsernames) -> Void in
        self.showAlertWithTitle("Message Sent", message: "Your message was successfully sent.")
        
        }) { (error) -> Void in
            print(error)
    }
}

我们首先确保用户填写了必填字段。 位置是可选的。 我们通过创建MMXMessage类的实例来发送消息,并传递收件人和我们想要发送的内容。 请注意,Magnet Message支持富消息传递,因此您可以添加文本和媒体。

要发送消息,我们在MMXMessage对象上调用sendWithSuccess(_:failure:) ,并传递成功和失败的结束信息。 此消息立即返回,并向我们提供消息的标识符。 在此示例中,我们不需要这样做。 showAlertWithTitle(_:message:)的实现与我们之前所见类似。

private func showAlertWithTitle(title: String, message: String) {
    // Initialize Alert Controller
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    
    // Configure Alert Controller
    alertController.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
    
    // Present Alert Controller
    presentViewController(alertController, animated: true, completion: nil)
}

请注意,如果其他用户正在使用该应用程序,则您只能将其成功发送给其他用户。 要测试我们到目前为止构建的内容,您需要在两台设备上登录或使用模拟器。

11.接收消息

步骤1:开始观察

要接收来自其他用户的消息,我们需要注意MessageViewController的两件事。 在viewDidLoad() ,我们通过调用start()类方法来告诉MagnetMax库我们希望接收消息。

viewDidLoad()方法中,我们还将视图控制器添加为名称为MMXDidReceiveMessageNotification的通知的观察者。 每当MagnetMax库收到来自Magnet Message后端的消息时,都会使用该名称发布通知。

override func viewDidLoad() {
    super.viewDidLoad()
    
    MMX.start()
    
    let notificationCenter = NSNotificationCenter.defaultCenter()
    notificationCenter.addObserver(self, selector: "didReceiveMessage:", name: MMXDidReceiveMessageNotification, object: nil)
    
    setupView()
}

步骤2:处理邮件

didReceiveMessage(_:) ,我们使用guard进行了许多检查,然后将传递确认发送到Magnet Message后端,以告知它我们已收到消息。

// MARK: -
// MARK: Notification Handling
func didReceiveMessage(notification: NSNotification) {
    guard let userInfo = notification.userInfo else { return }
    guard let message = userInfo[MMXMessageKey] as? MMXMessage else { return }
    
    // Send Delivery Confirmation
    message.sendDeliveryConfirmation()
    
    print(message)
}

结论

尽管本教程相当冗长,但我相信您同意集成Magnet Message并不需要我们付出很多努力。 繁重的工作由MagnetMax库完成。 发送和接收消息只是Magnet平台可以做的一部分。 磁铁为媒体,公共和私人频道以及推送通知提供支持。 您可以在Magnet的网站上了解有关这些功能的更多信息。

翻译自: https://code.tutsplus.com/tutorials/add-user-chat-to-an-ios-application-with-magnet--cms-25100

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值