Last active
July 12, 2021 21:56
-
-
Save asciimike/cc45567cd95ba2a62017cb21e891effd to your computer and use it in GitHub Desktop.
Zero to App: Develop with Firebase (for iOS - Google I/O 2016)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
// AppDelegate.swift | |
// ZeroToApp | |
// | |
import UIKit | |
import Firebase | |
import FBSDKCoreKit | |
@UIApplicationMain | |
class AppDelegate: UIResponder, UIApplicationDelegate { | |
var window: UIWindow? | |
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { | |
// Configure Firebase SDK | |
FIRApp.configure() | |
// Configure Facebook SDK | |
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions) | |
return true | |
} | |
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { | |
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation) | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.swift | |
// ZeroToApp | |
// | |
import UIKit | |
import Firebase | |
import FBSDKLoginKit | |
import Photos | |
struct ChatMessage { | |
var name: String! | |
var message: String! | |
var image: UIImage? | |
} | |
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { | |
// Outlets | |
@IBOutlet weak var messageTextField: UITextField! | |
@IBOutlet weak var sendButton: UIButton! | |
@IBOutlet weak var tableView: UITableView! | |
// Useful app properties | |
let imagePicker = UIImagePickerController() | |
var messages: [ChatMessage]! | |
var username: String! | |
// Firebase services | |
var database: FIRDatabase! | |
var auth: FIRAuth! | |
var storage: FIRStorage! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Initialize navigation bar | |
self.title = "Zero To App" | |
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Log in", | |
style: UIBarButtonItemStyle.Plain, | |
target: self, | |
action: #selector(toggleAuthState)) | |
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Camera, | |
target: self, | |
action: #selector(selectImage)) | |
// Initialize send button | |
sendButton.addTarget(self, | |
action: #selector(sendMessage), | |
forControlEvents: .TouchUpInside) | |
// Initialize UIImagePicker | |
imagePicker.delegate = self | |
// Initialize other properties | |
messages = [] | |
username = "iOS" | |
// Initialize UITableView | |
tableView.delegate = self | |
tableView.dataSource = self | |
let nib = UINib(nibName: "ChatMessageTableViewCell", bundle: nil) | |
tableView.registerNib(nib, forCellReuseIdentifier: "chatMessageCell") | |
// Initialize Database, Auth, Storage | |
database = FIRDatabase.database() | |
auth = FIRAuth.auth() | |
storage = FIRStorage.storage() | |
// Listen for when child nodes get added to the collection | |
let chatRef = database.reference().child("chat") | |
chatRef.observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in | |
// Get the chat message from the snapshot and add it to the UI | |
let data = snapshot.value as! Dictionary<String, String> | |
guard let name = data["name"] as String! else { return } | |
guard let message = data["message"] as String! else { return } | |
let chatMessage = ChatMessage(name: name, message: message, image: nil) | |
self.addMessage(chatMessage) | |
}) | |
// Observe auth state change | |
self.auth.addAuthStateDidChangeListener { (auth, user) in | |
if (user != nil) { | |
self.username = user?.displayName | |
self.navigationItem.rightBarButtonItem?.title = "Log out" | |
} else { | |
self.username = "iOS" | |
self.navigationItem.rightBarButtonItem?.title = "Log in" | |
} | |
} | |
} | |
// Send a chat message | |
func sendMessage(sender: AnyObject) { | |
// Create chat message | |
let chatMessage = ChatMessage(name: self.username, message: messageTextField.text!, image: nil) | |
messageTextField.text = "" | |
// Create a reference to our chat message | |
let chatRef = database.reference().child("chat") | |
// Push the chat message to the database | |
chatRef.childByAutoId().setValue(["name": chatMessage.name, "message": chatMessage.message]) | |
} | |
// Show a popup when the user asks to sign in | |
func toggleAuthState() { | |
if (auth.currentUser != nil) { | |
// Allow the user to sign out | |
do { | |
try auth.signOut() | |
} catch {} | |
} else { | |
// Log in to Facebook | |
let login = FBSDKLoginManager() | |
login.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) in | |
if (error != nil || result.isCancelled) { | |
print(error) | |
} else { | |
// Log in to Firebase via Facebook | |
let credential = FIRFacebookAuthProvider.credentialWithAccessToken(result.token.tokenString) | |
FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in | |
if (error != nil) { | |
print(error) | |
} | |
} | |
} | |
}) | |
} | |
} | |
// Handle photo uploads button | |
func selectImage() { | |
imagePicker.allowsEditing = false | |
imagePicker.sourceType = .PhotoLibrary | |
presentViewController(imagePicker, animated: true, completion: nil) | |
} | |
// pragma mark - UIImagePickerDelegate overrides | |
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { | |
// Get local file URLs | |
guard let image: UIImage = info[UIImagePickerControllerOriginalImage] as? UIImage else { return } | |
let imageData = UIImagePNGRepresentation(image)! | |
guard let imageURL: NSURL = info[UIImagePickerControllerReferenceURL] as? NSURL else { return } | |
// Get a reference to the location where we'll store our photos | |
let photosRef = storage.reference().child("chat_photos") | |
// Get a reference to store the file at chat_photos/<FILENAME> | |
let photoRef = photosRef.child("\(NSUUID().UUIDString).png") | |
// Upload file to Firebase Storage | |
let metadata = FIRStorageMetadata() | |
metadata.contentType = "image/png" | |
photoRef.putData(imageData, metadata: metadata).observeStatus(.Success) { (snapshot) in | |
// When the image has successfully uploaded, we get it's download URL | |
let text = snapshot.metadata?.downloadURL()?.absoluteString | |
// Set the download URL to the message box, so that the user can send it to the database | |
self.messageTextField.text = text | |
} | |
// Clean up picker | |
dismissViewControllerAnimated(true, completion: nil) | |
} | |
func addMessage(var chatMessage: ChatMessage) { | |
// Handle remote image messages | |
if (chatMessage.message.containsString("https://firebasestorage.googleapis.com")) { | |
self.storage.referenceForURL(chatMessage.message).dataWithMaxSize(25 * 1024 * 1024, completion: { (data, error) -> Void in | |
let image = UIImage(data: data!) | |
chatMessage.image = image! | |
self.messages.append(chatMessage) | |
self.tableView.reloadData() | |
self.scrollToBottom() | |
}) | |
// Handle asset library messages | |
} else if (chatMessage.message.containsString("assets-library://")) { | |
let assetURL = NSURL(string: chatMessage.message) | |
let assets = PHAsset.fetchAssetsWithALAssetURLs([assetURL!], options: nil) | |
let asset: PHAsset = assets.firstObject as! PHAsset | |
let manager = PHImageManager.defaultManager() | |
manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: {(result, info)->Void in | |
chatMessage.image = result! | |
self.messages.append(chatMessage) | |
self.tableView.reloadData() | |
self.scrollToBottom() | |
}) | |
// Handle regular messages | |
} else { | |
self.messages.append(chatMessage) | |
self.tableView.reloadData() | |
self.scrollToBottom() | |
} | |
} | |
func scrollToBottom() { | |
if (self.messages.count > 8) { | |
let bottomOffset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.bounds.size.height) | |
tableView.setContentOffset(bottomOffset, animated: true) | |
} | |
} | |
// pragma mark - UITableViewDataSource overrides | |
func numberOfSectionsInTableView(tableView: UITableView) -> Int { | |
return 1 | |
} | |
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCellWithIdentifier("chatMessageCell", forIndexPath: indexPath) as! ChatMessageTableViewCell | |
let chatMessage = messages[indexPath.row] | |
cell.nameLabel.text = chatMessage.name | |
cell.messageLabel.text = chatMessage.message | |
cell.photoView.image = chatMessage.image | |
return cell | |
} | |
// pragma mark - UITableViewDelegate overrides | |
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { | |
let chatMessage = messages[indexPath.row] | |
if (chatMessage.image != nil) { | |
return 345.0 | |
} else { | |
return 58.0 | |
} | |
} | |
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return messages.count | |
} | |
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { | |
tableView.deselectRowAtIndexPath(indexPath, animated: true) | |
} | |
// Create a chat message from a FIRDataSnapshot | |
func chatMessageFromSnapshot(snapshot: FIRDataSnapshot) -> ChatMessage? { | |
let data = snapshot.value as! Dictionary<String, String> | |
guard let name = data["name"] as String! else { return nil } | |
guard let message = data["message"] as String! else { return nil } | |
let chatMessage = ChatMessage(name: name, message: message, image: nil) | |
return chatMessage | |
} | |
} | |
could you please share your ChatMessageTableViewCell class and your story board
@aruld this may be because there may be some possibel error in your ChatMessageTableViewCell or you might have forgot to create one.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ty this really help me