インフラ

iOS + Firebaseで実装

特に何も考えずに2時間くらいでできた。

ログイン画面

//// LoginViewController.swiftimportUIKitimportFirebaseAuthimportFBSDKLoginKitimportFirebaseDatabaseclassLoginViewController:UIViewController{@IBOutletweakvarloginBtn:FBSDKLoginButton!varref:DatabaseReference!overridefuncviewDidLoad(){super.viewDidLoad()loginBtn.readPermissions=["public_profile","email","user_friends"]loginBtn.delegate=selfref=Database.database().reference()}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()// Dispose of any resources that can be recreated.}}extensionLoginViewController:FBSDKLoginButtonDelegate{funcloginButtonDidLogOut(_loginButton:FBSDKLoginButton!){}funcloginButton(_loginButton:FBSDKLoginButton!,didCompleteWithresult:FBSDKLoginManagerLoginResult!,error:Error!){if(error!=nil){print("Error \(error)")}elseifresult.isCancelled{print("Cancelled")}else{print("Login Succeeded")letcredential=FacebookAuthProvider.credential(withAccessToken:FBSDKAccessToken.current().tokenString)Auth.auth().signIn(with:credential){(user,error)inifleterror=error{print(error)return}self.postUser()}}}funcpostUser(){guardletuser=Auth.auth().currentUserelse{assert(true,"post user with nil")return}letfacebookId=FBSDKAccessToken.current().userIDletuserRef=ref.child("users")userRef.queryOrdered(byChild:"facebookId").queryEqual(toValue:facebookId).observeSingleEvent(of:DataEventType.value){(snapshot)inifsnapshot.exists(){print("Exist user")}else{letpostUser=["facebookId":FBSDKAccessToken.current().userID,"updated_at":Date().toStr(),"name":user.displayName]letpostUserRef=userRef.childByAutoId()postUserRef.setValue(postUser)}self.dismiss(animated:true,completion:nil)}}}

チャット詳細画面

//// ChatViewController.swiftimportUIKitimportFirebaseAuthimportFBSDKLoginKitimportJSQMessagesViewControllerimportFirebaseDatabaseimportSDWebImageclassChatViewController:JSQMessagesViewController{varmessages=[JSQMessage]()vartargetUser:User!varref:DatabaseReference!varroomKey:String!fileprivatevarincomingBubble:JSQMessagesBubbleImage!fileprivatevaroutgoingBubble:JSQMessagesBubbleImage!fileprivatevarincomingAvatar:JSQMessagesAvatarImage!fileprivatevaroutgoingAvatar:JSQMessagesAvatarImage!classfunccreate(user:User)->ChatViewController{letvc=UIStoryboard(name:"Chat",bundle:nil).instantiateViewController(withIdentifier:"chat")as!ChatViewControllervc.targetUser=userreturnvc}overridefuncviewDidLoad(){super.viewDidLoad()letfacebookId=FBSDKAccessToken.current().userID!self.senderId=facebookIdself.senderDisplayName=Auth.auth().currentUser?.displayNameself.ref=Database.database().reference()self.title=targetUser.nameletbubbleFactory=JSQMessagesBubbleImageFactory()self.incomingBubble=bubbleFactory?.incomingMessagesBubbleImage(with:UIColor.jsq_messageBubbleLightGray())self.outgoingBubble=bubbleFactory?.outgoingMessagesBubbleImage(with:UIColor.jsq_messageBubbleBlue())SDWebImageDownloader.shared().downloadImage(with:targetUser.iconURL,options:[],progress:nil){(image,data,err,res)inself.incomingAvatar=JSQMessagesAvatarImageFactory.avatarImage(with:image,diameter:64)}leturl=URL(string:"https://graph.facebook.com/\(facebookId)/picture")SDWebImageDownloader.shared().downloadImage(with:url,options:[],progress:nil){(image,data,err,res)inself.outgoingAvatar=JSQMessagesAvatarImageFactory.avatarImage(with:image,diameter:64)}createTalkRoomIfNeeded()}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()// Dispose of any resources that can be recreated.}}extensionChatViewController{funccreateTalkRoomIfNeeded(){letfacebookId=FBSDKAccessToken.current().userID!letroomRef=ref.child("rooms")letuserIds:[String]=[targetUser.faceboookId,facebookId].sorted()roomRef.observeSingleEvent(of:DataEventType.value){(snapshot)inifsnapshot.exists(){foriteminsnapshot.children{ifletroomSnap=(itemas?DataSnapshot),letroom=(roomSnap.valueas?[String]),room==userIds{print("exist room")self.roomKey=roomSnap.keyself.observe()return}}}print("create room")letnewRoomRef=roomRef.childByAutoId()newRoomRef.setValue(userIds)self.roomKey=newRoomRef.keyself.observe()}}funcupdateUserDate(){letuserRef=ref.child("users")userRef.queryOrdered(byChild:"facebookId").queryEqual(toValue:targetUser.faceboookId).queryLimited(toFirst:1).observeSingleEvent(of:DataEventType.value){(snapshot)inifletkey=(snapshot.children.allObjects[0]as?DataSnapshot)?.key{letmyuserRef=userRef.child(key)myuserRef.updateChildValues(["updated_at":Date().toStr()])}}}funcobserve(){print(self.roomKey)letchatRef=ref.child("chats")chatRef.queryOrdered(byChild:"roomId").queryEqual(toValue:self.roomKey).observe(DataEventType.value){(snapshot)inself.messages=[JSQMessage]()foriteminsnapshot.children{ifletchatSnap=itemas?DataSnapshot{letsenderId=chatSnap.childSnapshot(forPath:"senderId").valueas?Stringlettext=chatSnap.childSnapshot(forPath:"text").valueas?StringifsenderId==self.senderId{letmessage=JSQMessage(senderId:senderId,displayName:self.senderDisplayName,text:text)self.messages.append(message!)}else{letmessage=JSQMessage(senderId:senderId,displayName:self.targetUser.name,text:text)self.messages.append(message!)}}}self.collectionView.reloadData()}}}// MARK: JSQMessagesViewControllerextensionChatViewController{overridefuncdidPressSend(_button:UIButton!,withMessageTexttext:String!,senderId:String!,senderDisplayName:String!,date:Date!){letfacebookId=FBSDKAccessToken.current().userID!letchatRef=ref.child("chats").childByAutoId()letnewMessage=["roomId":roomKey,"senderId":facebookId,"text":text]chatRef.setValue(newMessage)self.updateUserDate()}overridefunccollectionView(_collectionView:JSQMessagesCollectionView!,messageBubbleImageDataForItemAtindexPath:IndexPath!)->JSQMessageBubbleImageDataSource!{ifself.messages[indexPath.item].senderId==senderId{returnself.outgoingBubble}returnself.incomingBubble}overridefunccollectionView(_collectionView:UICollectionView,cellForItemAtindexPath:IndexPath)->UICollectionViewCell{letcell=super.collectionView(collectionView,cellForItemAt:indexPath)as!JSQMessagesCollectionViewCellifself.messages[indexPath.item].senderId==senderId{cell.textView.textColor=UIColor.white}else{cell.textView.textColor=UIColor.darkGray}returncell}overridefunccollectionView(_collectionView:UICollectionView,numberOfItemsInSectionsection:Int)->Int{returnmessages.count}overridefunccollectionView(_collectionView:JSQMessagesCollectionView!,avatarImageDataForItemAtindexPath:IndexPath!)->JSQMessageAvatarImageDataSource!{ifself.messages[indexPath.item].senderId==senderId{returnself.outgoingAvatar}else{returnself.incomingAvatar}}overridefunccollectionView(_collectionView:JSQMessagesCollectionView!,messageDataForItemAtindexPath:IndexPath!)->JSQMessageData!{returnmessages[indexPath.row]}}