├── .DS_Store ├── fbMessenger ├── Assets.xcassets │ ├── Contents.json │ ├── calls.imageset │ │ ├── calls@3x.png │ │ └── Contents.json │ ├── gandhi.imageset │ │ ├── gandhi.png │ │ └── Contents.json │ ├── groups.imageset │ │ ├── groups@3x.png │ │ └── Contents.json │ ├── people.imageset │ │ ├── people@3x.png │ │ └── Contents.json │ ├── recent.imageset │ │ ├── recent@3x.png │ │ └── Contents.json │ ├── settings.imageset │ │ ├── settings@3x.png │ │ └── Contents.json │ ├── zuckprofile.imageset │ │ ├── zuckprofile.jpg │ │ └── Contents.json │ ├── bubble_blue.imageset │ │ ├── bubble_blue@2x.png │ │ └── Contents.json │ ├── bubble_gray.imageset │ │ ├── bubble_gray@2x.png │ │ └── Contents.json │ ├── steve_profile.imageset │ │ ├── steve_profile.png │ │ └── Contents.json │ ├── hillary_profile.imageset │ │ ├── hillary_profile.jpg │ │ └── Contents.json │ ├── donald_trump_profile.imageset │ │ ├── donald_trump_profile.png │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── fbMessenger.xcdatamodeld │ ├── .xccurrentversion │ └── fbMessenger.xcdatamodel │ │ └── contents ├── Extensions.swift ├── Info.plist ├── CustomTabbarController.swift ├── Base.lproj │ └── LaunchScreen.storyboard ├── FriendsControllerHelper.swift ├── AppDelegate.swift ├── FriendsController.swift └── ChatLogController.swift ├── fbMessenger.xcodeproj ├── xcuserdata │ └── VamshiKrishna.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── fbMessenger.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── VamshiKrishna.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── project.pbxproj └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/.DS_Store -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/calls.imageset/calls@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/calls.imageset/calls@3x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/gandhi.imageset/gandhi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/gandhi.imageset/gandhi.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/groups.imageset/groups@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/groups.imageset/groups@3x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/people.imageset/people@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/people.imageset/people@3x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/recent.imageset/recent@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/recent.imageset/recent@3x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/settings.imageset/settings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/settings.imageset/settings@3x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/zuckprofile.imageset/zuckprofile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/zuckprofile.imageset/zuckprofile.jpg -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/bubble_blue.imageset/bubble_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/bubble_blue.imageset/bubble_blue@2x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/bubble_gray.imageset/bubble_gray@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/bubble_gray.imageset/bubble_gray@2x.png -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/steve_profile.imageset/steve_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/steve_profile.imageset/steve_profile.png -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/xcuserdata/VamshiKrishna.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/hillary_profile.imageset/hillary_profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/hillary_profile.imageset/hillary_profile.jpg -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/donald_trump_profile.imageset/donald_trump_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger/Assets.xcassets/donald_trump_profile.imageset/donald_trump_profile.png -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/project.xcworkspace/xcuserdata/VamshiKrishna.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VamshiIITBHU14/FBChatClone/HEAD/fbMessenger.xcodeproj/project.xcworkspace/xcuserdata/VamshiKrishna.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /fbMessenger/fbMessenger.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | fbMessenger.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FBChatClone 2 | 1) Auto Layout Using Code 3 | 2) Core Data Entities: Create, Read, Delete and a lot more operations involving Core Data which would help in understanding the power of Core Data 4 | 3) Creating a Tab Bar Menu Programatically 5 | 4) Creating Chat Bubbles With Tails 6 | 5) How to Auto Update UICollectionView by inserting rows using NSFetchedResultsController 7 | 6) No Storyboards used 8 | -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/calls.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "calls@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/gandhi.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "gandhi.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/groups.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "groups@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/people.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "people@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/recent.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "recent@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/settings.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "settings@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/zuckprofile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "zuckprofile.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/bubble_blue.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "bubble_blue@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/bubble_gray.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "bubble_gray@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/steve_profile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "steve_profile.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/hillary_profile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "hillary_profile.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/donald_trump_profile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "donald_trump_profile.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/xcuserdata/VamshiKrishna.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | fbMessenger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 96988E951EDDD5CA0098F653 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /fbMessenger/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /fbMessenger/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 30/05/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIColor{ 13 | static func returnRGBColor(r:CGFloat, g:CGFloat, b:CGFloat, alpha:CGFloat) -> UIColor{ 14 | return UIColor(red: r/255, green: g/255, blue: b/255, alpha: alpha) 15 | } 16 | } 17 | 18 | extension UIView{ 19 | func addConstraintsWithFormat(format:String, views: UIView...){ 20 | 21 | var viewsDictionary = [String:UIView]() 22 | for (index, view) in views.enumerated(){ 23 | let key = "v\(index)" 24 | view.translatesAutoresizingMaskIntoConstraints = false 25 | viewsDictionary[key] = view 26 | } 27 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary)) 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /fbMessenger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /fbMessenger/CustomTabbarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTabbarController.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 01/06/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class CustomTabbarController: UITabBarController { 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | let layout = UICollectionViewFlowLayout() 17 | let friendsController = FriendsController(collectionViewLayout: layout) 18 | let recentMessagesControlelr = UINavigationController(rootViewController: friendsController) 19 | recentMessagesControlelr.tabBarItem.title = "Recent" 20 | recentMessagesControlelr.tabBarItem.image = UIImage(named: "recent") 21 | 22 | viewControllers = [recentMessagesControlelr, createDummyTabbarController(title: "Calls", imageName: "calls"), createDummyTabbarController(title: "Groups", imageName: "groups"), createDummyTabbarController(title: "People", imageName: "people"), createDummyTabbarController(title: "Settings", imageName: "settings")] 23 | } 24 | 25 | private func createDummyTabbarController(title:String, imageName:String) -> UINavigationController{ 26 | let viewController = UIViewController() 27 | let navController = UINavigationController(rootViewController: viewController) 28 | navController.tabBarItem.title = title 29 | navController.tabBarItem.image = UIImage(named: imageName) 30 | return navController 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /fbMessenger/fbMessenger.xcdatamodeld/fbMessenger.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /fbMessenger/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/xcuserdata/VamshiKrishna.xcuserdatad/xcschemes/fbMessenger.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /fbMessenger/FriendsControllerHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FriendsControllerHelper.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 30/05/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import UIKit 12 | import CoreData 13 | 14 | extension FriendsController{ 15 | 16 | func clearData(){ 17 | guard let delegate = UIApplication.shared.delegate as? AppDelegate else{ 18 | return 19 | } 20 | 21 | let context = delegate.persistentContainer.viewContext 22 | do{ 23 | let entityNames = ["Friend", "Message"] 24 | for entityName in entityNames{ 25 | let fetchRequest = NSFetchRequest(entityName: entityName) 26 | let objects = try (context.fetch(fetchRequest)) 27 | for object in objects{ 28 | context.delete(object) 29 | } 30 | } 31 | try (context.save()) 32 | } catch let error{ 33 | print(error) 34 | } 35 | } 36 | func setupData(){ 37 | clearData() 38 | guard let delegate = 39 | UIApplication.shared.delegate as? AppDelegate else { 40 | return 41 | } 42 | let context = delegate.persistentContainer.viewContext 43 | 44 | createSteveMessagesWithContext(context: context) 45 | 46 | let donald = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 47 | donald.name = "Donald Trump" 48 | donald.profileImageName = "donald_trump_profile" 49 | _=FriendsController.createMessageWithText(text: "My name is Donald Trump!", friend: donald, minutesAgo: 5, context: context) 50 | 51 | let gandhi = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 52 | gandhi.name = "Mahatma Gandhi" 53 | gandhi.profileImageName = "gandhi" 54 | _=FriendsController.createMessageWithText(text: "My name is MK Gandhi", friend: gandhi, minutesAgo: 60*36, context: context) 55 | 56 | let hillary = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 57 | hillary.name = "Hillary Clinton" 58 | hillary.profileImageName = "hillary_profile" 59 | _=FriendsController.createMessageWithText(text: "My name is Hillary Clinton", friend: hillary, minutesAgo: 8*60*36, context: context) 60 | 61 | do{ 62 | try(context.save()) 63 | } catch let error{ 64 | print (error) 65 | } 66 | } 67 | 68 | private func createSteveMessagesWithContext(context: NSManagedObjectContext){ 69 | let steve = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 70 | steve.name = "Steve Jobs" 71 | steve.profileImageName = "steve_profile" 72 | 73 | _=FriendsController.createMessageWithText(text: "Hello! I am Jobs!Hello! I am Jobs!Hello! I am Jobs!Hello! I am Jobs!Hello! I am Jobs!Hello! I am Jobs!", friend: steve, minutesAgo: 10, context: context) 74 | _=FriendsController.createMessageWithText(text: "How are you doing?", friend: steve, minutesAgo: 8, context: context) 75 | _=FriendsController.createMessageWithText(text: "How's work? Interested in working for apple?How's work? Interested in working for apple?How's work? Interested in working for apple?", friend: steve, minutesAgo: 7, context: context) 76 | 77 | //response messages 78 | _=FriendsController.createMessageWithText(text: "Yes! I would love to", friend: steve, minutesAgo: 4, context: context, isSender: true) 79 | _=FriendsController.createMessageWithText(text: "Whatever you say!Whatever you say!Whatever you say!Whatever you say!", friend: steve, minutesAgo: 6, context: context, isSender: true) 80 | _=FriendsController.createMessageWithText(text: "Yes! I would be humbled!Yes! I would be humbled!Yes! I would be humbled!Yes! I would be humbled!", friend: steve, minutesAgo: 2, context: context, isSender: true) 81 | } 82 | 83 | static func createMessageWithText(text:String, friend:Friend,minutesAgo:Double, context:NSManagedObjectContext, isSender:Bool = false) -> Message { 84 | let message = NSEntityDescription.insertNewObject(forEntityName: "Message", into: context) as! Message 85 | message.friend = friend 86 | message.text = text 87 | message.date = NSDate().addingTimeInterval(-minutesAgo * 60) 88 | message.isSender = NSNumber(booleanLiteral: isSender) as! Bool 89 | friend.lastMessage = message 90 | return message 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /fbMessenger/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 30/05/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | // Override point for customization after application launch. 20 | window = UIWindow(frame:UIScreen.main.bounds) 21 | window?.makeKeyAndVisible() 22 | 23 | window?.rootViewController = CustomTabbarController() 24 | 25 | return true 26 | } 27 | 28 | func applicationWillResignActive(_ application: UIApplication) { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 31 | } 32 | 33 | func applicationDidEnterBackground(_ application: UIApplication) { 34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 36 | } 37 | 38 | func applicationWillEnterForeground(_ application: UIApplication) { 39 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | func applicationDidBecomeActive(_ application: UIApplication) { 43 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 44 | } 45 | 46 | func applicationWillTerminate(_ application: UIApplication) { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | // Saves changes in the application's managed object context before the application terminates. 49 | self.saveContext() 50 | } 51 | 52 | // MARK: - Core Data stack 53 | 54 | lazy var persistentContainer: NSPersistentContainer = { 55 | /* 56 | The persistent container for the application. This implementation 57 | creates and returns a container, having loaded the store for the 58 | application to it. This property is optional since there are legitimate 59 | error conditions that could cause the creation of the store to fail. 60 | */ 61 | let container = NSPersistentContainer(name: "fbMessenger") 62 | container.loadPersistentStores(completionHandler: { (storeDescription, error) in 63 | if let error = error as NSError? { 64 | // Replace this implementation with code to handle the error appropriately. 65 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 66 | 67 | /* 68 | Typical reasons for an error here include: 69 | * The parent directory does not exist, cannot be created, or disallows writing. 70 | * The persistent store is not accessible, due to permissions or data protection when the device is locked. 71 | * The device is out of space. 72 | * The store could not be migrated to the current model version. 73 | Check the error message to determine what the actual problem was. 74 | */ 75 | fatalError("Unresolved error \(error), \(error.userInfo)") 76 | } 77 | }) 78 | return container 79 | }() 80 | 81 | // MARK: - Core Data Saving support 82 | 83 | func saveContext () { 84 | let context = persistentContainer.viewContext 85 | if context.hasChanges { 86 | do { 87 | try context.save() 88 | } catch { 89 | // Replace this implementation with code to handle the error appropriately. 90 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 91 | let nserror = error as NSError 92 | fatalError("Unresolved error \(nserror), \(nserror.userInfo)") 93 | } 94 | } 95 | } 96 | 97 | } 98 | 99 | -------------------------------------------------------------------------------- /fbMessenger/FriendsController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 30/05/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreData 11 | 12 | class FriendsController: UICollectionViewController, UICollectionViewDelegateFlowLayout, NSFetchedResultsControllerDelegate { 13 | 14 | private let cellId = "cellId" 15 | 16 | lazy var fetchedResultsController:NSFetchedResultsController = { () -> NSFetchedResultsController in 17 | let fetchRequest = NSFetchRequest(entityName: "Friend") 18 | fetchRequest.sortDescriptors = [NSSortDescriptor(key: "lastMessage.date", ascending: false)] 19 | fetchRequest.predicate = NSPredicate(format:"lastMessage != nil") 20 | let delegate = UIApplication.shared.delegate as?AppDelegate; 21 | let context = delegate?.persistentContainer.viewContext 22 | let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context!, sectionNameKeyPath: nil, cacheName: nil) 23 | frc.delegate = self 24 | return frc 25 | }() 26 | 27 | func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 28 | if type == .insert{ 29 | blockOperations.append(BlockOperation(block: { 30 | (self.collectionView?.insertItems(at: [newIndexPath!]))! 31 | })) 32 | } 33 | } 34 | 35 | var blockOperations = [BlockOperation]() 36 | 37 | func controllerDidChangeContent(_ controller: NSFetchedResultsController) { 38 | collectionView?.performBatchUpdates({ 39 | for operation in self.blockOperations{ 40 | operation.start() 41 | } 42 | }, completion: { (completed) in 43 | let lastItem = (self.fetchedResultsController.sections?[0].numberOfObjects)! - 1 44 | let indexPath = IndexPath(item: lastItem, section: 0) 45 | self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 46 | }) 47 | } 48 | 49 | override func viewWillAppear(_ animated: Bool) { 50 | tabBarController?.tabBar.isHidden = false 51 | } 52 | override func viewDidLoad() { 53 | super.viewDidLoad() 54 | navigationItem.title = "Recent" 55 | collectionView?.backgroundColor = .white 56 | collectionView?.alwaysBounceVertical = true 57 | setupData() 58 | collectionView?.register(MessageCell.self, forCellWithReuseIdentifier: cellId) 59 | 60 | do{ 61 | try fetchedResultsController.performFetch() 62 | }catch let error{ 63 | print(error) 64 | } 65 | 66 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add Mark", style: .plain, target: self, action: #selector(addMark)) 67 | } 68 | 69 | func addMark(){ 70 | guard let delegate = 71 | UIApplication.shared.delegate as? AppDelegate else { 72 | return 73 | } 74 | let context = delegate.persistentContainer.viewContext 75 | let mark = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 76 | mark.name = "Mark Zuckerberg" 77 | mark.profileImageName = "zuckprofile" 78 | _=FriendsController.createMessageWithText(text: "Hey, I am Mark!", friend: mark, minutesAgo: 8*60*36, context: context) 79 | 80 | let bill = NSEntityDescription.insertNewObject(forEntityName: "Friend", into: context) as! Friend 81 | bill.name = "Bill Gates" 82 | mark.profileImageName = "zuckprofile" 83 | _=FriendsController.createMessageWithText(text: "Hey, I am Bill!", friend: bill, minutesAgo: 8*60*24, context: context) 84 | } 85 | 86 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 87 | if let count = fetchedResultsController.sections?[section].numberOfObjects{ 88 | return count 89 | } 90 | return 0 91 | } 92 | 93 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 94 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MessageCell 95 | let friend = fetchedResultsController.object(at: indexPath) as! Friend 96 | cell.message = friend.lastMessage 97 | return cell 98 | } 99 | 100 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 101 | return CGSize(width: view.frame.width, height: 100) 102 | } 103 | 104 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 105 | let layout = UICollectionViewFlowLayout() 106 | let controller = ChatLogController(collectionViewLayout: layout) 107 | let friend = fetchedResultsController.object(at: indexPath) as! Friend 108 | controller.friend = friend 109 | navigationController?.pushViewController(controller, animated: true) 110 | } 111 | } 112 | 113 | class MessageCell:BaseCell{ 114 | 115 | override var isHighlighted: Bool{ 116 | didSet{ 117 | backgroundColor = isHighlighted ? UIColor.returnRGBColor(r: 0, g: 134, b: 249, alpha: 1) : UIColor.white 118 | nameLabel.textColor = isHighlighted ? UIColor.white : UIColor.black 119 | timeLabel.textColor = isHighlighted ? UIColor.white : UIColor.black 120 | messageLabel.textColor = isHighlighted ? UIColor.white : UIColor.black 121 | } 122 | } 123 | var message:Message?{ 124 | didSet{ 125 | nameLabel.text = message?.friend?.name 126 | messageLabel.text = message?.text 127 | 128 | if let profileImageName = message?.friend?.profileImageName{ 129 | profileImageView.image = UIImage(named: profileImageName) 130 | hasReadImageView.image = UIImage(named: profileImageName) 131 | } 132 | 133 | if let date = message?.date{ 134 | let dateFormatter = DateFormatter() 135 | dateFormatter.dateFormat = "hh:mm a" 136 | let elapsedTimeInSeconds = NSDate().timeIntervalSince(date as Date) 137 | let secondsInDay : TimeInterval = 60*60*24 138 | 139 | if(elapsedTimeInSeconds > 7*secondsInDay){ 140 | dateFormatter.dateFormat = "MM/dd/yy" 141 | } else if elapsedTimeInSeconds > secondsInDay{ 142 | dateFormatter.dateFormat = "EEE" 143 | } 144 | 145 | timeLabel.text = dateFormatter.string(from: date as Date) 146 | } 147 | } 148 | } 149 | 150 | let profileImageView:UIImageView = { 151 | let iv = UIImageView() 152 | iv.contentMode = .scaleAspectFill 153 | iv.layer.cornerRadius = 34 154 | iv.layer.masksToBounds = true 155 | return iv 156 | }() 157 | 158 | let nameLabel:UILabel = { 159 | let label = UILabel() 160 | label.text = "Friend's Name" 161 | label.font = UIFont.systemFont(ofSize: 18) 162 | return label 163 | }() 164 | 165 | let messageLabel:UILabel = { 166 | let label = UILabel() 167 | label.text = "Message MessageMessageMessage containerViewcontainerViewcontainerView" 168 | label.textColor = UIColor.darkGray 169 | label.font = UIFont.systemFont(ofSize: 14) 170 | return label 171 | }() 172 | 173 | let timeLabel : UILabel = { 174 | let label = UILabel() 175 | label.text = "09:50 pm" 176 | label.font = UIFont.systemFont(ofSize: 16) 177 | label.textAlignment = .right 178 | return label 179 | }() 180 | 181 | let dividerLineView:UIView = { 182 | let dv = UIView() 183 | dv.backgroundColor = UIColor(white: 0.5, alpha: 0.5) 184 | return dv 185 | }() 186 | 187 | let hasReadImageView : UIImageView = { 188 | let iv = UIImageView() 189 | iv.contentMode = .scaleAspectFill 190 | iv.layer.cornerRadius = 10 191 | iv.layer.masksToBounds = true 192 | return iv 193 | }() 194 | 195 | override func setupViews() { 196 | addSubview(profileImageView) 197 | addSubview(dividerLineView) 198 | 199 | setupContainerView() 200 | profileImageView.image = UIImage(named:"zuckprofile") 201 | hasReadImageView.image = UIImage(named:"zuckprofile") 202 | addConstraintsWithFormat(format: "H:|-12-[v0(68)]", views: profileImageView) 203 | addConstraintsWithFormat(format: "V:[v0(68)]", views: profileImageView) 204 | addConstraint(NSLayoutConstraint(item: profileImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)) 205 | 206 | addConstraintsWithFormat(format: "H:|-82-[v0]|", views: dividerLineView) 207 | addConstraintsWithFormat(format: "V:[v0(1)]|", views: dividerLineView) 208 | 209 | } 210 | 211 | private func setupContainerView() { 212 | let containerView = UIView() 213 | addSubview(containerView) 214 | addConstraintsWithFormat(format: "H:|-90-[v0]|", views: containerView) 215 | addConstraintsWithFormat(format: "V:[v0(50)]", views: containerView) 216 | addConstraint(NSLayoutConstraint(item: containerView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)) 217 | 218 | containerView.addSubview(nameLabel) 219 | containerView.addSubview(messageLabel) 220 | containerView.addSubview(timeLabel) 221 | containerView.addSubview(hasReadImageView) 222 | 223 | containerView.addConstraintsWithFormat(format: "H:|[v0][v1(80)]-12-|", views: nameLabel, timeLabel) 224 | containerView.addConstraintsWithFormat(format: "V:|[v0][v1(24)]|", views: nameLabel,messageLabel) 225 | containerView.addConstraintsWithFormat(format: "H:|[v0]-8-[v1(20)]-12-|", views: messageLabel, hasReadImageView) 226 | containerView.addConstraintsWithFormat(format: "V:|[v0(24)]", views: timeLabel) 227 | containerView.addConstraintsWithFormat(format: "V:[v0(20)]|", views: hasReadImageView) 228 | } 229 | } 230 | 231 | class BaseCell:UICollectionViewCell{ 232 | override init(frame: CGRect) { 233 | super.init(frame: frame) 234 | setupViews() 235 | } 236 | 237 | required init?(coder aDecoder: NSCoder) { 238 | fatalError("init(coder:) has not been implemented") 239 | } 240 | 241 | func setupViews(){ 242 | 243 | } 244 | } 245 | 246 | 247 | -------------------------------------------------------------------------------- /fbMessenger/ChatLogController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChatLogController.swift 3 | // fbMessenger 4 | // 5 | // Created by Vamshi Krishna on 01/06/17. 6 | // Copyright © 2017 VamshiKrishna. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import CoreData 12 | 13 | class ChatLogController: UICollectionViewController , UICollectionViewDelegateFlowLayout, NSFetchedResultsControllerDelegate { 14 | 15 | private let cellId = "cellId" 16 | 17 | var friend:Friend?{ 18 | didSet{ 19 | navigationItem.title = friend?.name 20 | } 21 | } 22 | 23 | let messageInputContainerView:UIView = { 24 | let view = UIView() 25 | view.backgroundColor = .white 26 | return view 27 | }() 28 | 29 | let inputTextField:UITextField = { 30 | let tf = UITextField() 31 | tf.placeholder = "Enter Message Here" 32 | return tf 33 | }() 34 | 35 | let sendButton:UIButton = { 36 | let button = UIButton(type: .system) 37 | button.setTitle("Send", for: .normal) 38 | let titleColor = UIColor.returnRGBColor(r: 0, g: 137, b: 249, alpha: 1) 39 | button.setTitleColor(titleColor, for: .normal) 40 | button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16) 41 | button.addTarget(self, action: #selector(handleSend), for: .touchUpInside) 42 | return button 43 | }() 44 | 45 | func handleSend(){ 46 | guard let delegate = UIApplication.shared.delegate as?AppDelegate else{ 47 | return 48 | } 49 | let context = delegate.persistentContainer.viewContext 50 | _ = FriendsController.createMessageWithText(text: inputTextField.text!, friend: friend!, minutesAgo: 2, context: context, isSender: true) 51 | 52 | do{ 53 | try context.save() 54 | inputTextField.text = nil 55 | 56 | }catch let error{ 57 | print(error) 58 | } 59 | } 60 | 61 | private func setupInputComponents(){ 62 | let topBorderView = UIView() 63 | topBorderView.backgroundColor = UIColor(white: 0.5, alpha: 0.5) 64 | 65 | messageInputContainerView.addSubview(inputTextField) 66 | messageInputContainerView.addSubview(sendButton) 67 | messageInputContainerView.addSubview(topBorderView) 68 | 69 | messageInputContainerView.addConstraintsWithFormat(format: "H:|-8-[v0][v1(60)]|", views: inputTextField ,sendButton) 70 | messageInputContainerView.addConstraintsWithFormat(format: "V:|[v0]|", views: inputTextField) 71 | messageInputContainerView.addConstraintsWithFormat(format: "V:|[v0]|", views: sendButton) 72 | messageInputContainerView.addConstraintsWithFormat(format: "H:|[v0]|", views: topBorderView) 73 | messageInputContainerView.addConstraintsWithFormat(format: "V:|[v0(0.5)]", views: topBorderView) 74 | } 75 | 76 | var bottomConstraint:NSLayoutConstraint? 77 | 78 | lazy var fetchedRequestsController:NSFetchedResultsController = { () -> NSFetchedResultsController in 79 | let fetchRequest = NSFetchRequest(entityName: "Message") 80 | fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)] 81 | fetchRequest.predicate = NSPredicate(format: "friend.name = %@", (self.friend?.name)!) 82 | let delegate = UIApplication.shared.delegate as?AppDelegate; 83 | let context = delegate?.persistentContainer.viewContext 84 | let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context!, sectionNameKeyPath: nil, cacheName: nil) 85 | frc.delegate = self 86 | return frc 87 | }() 88 | 89 | var blockOperations = [BlockOperation]() 90 | 91 | func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 92 | if type == .insert{ 93 | blockOperations.append(BlockOperation(block: { 94 | (self.collectionView?.insertItems(at: [newIndexPath!]))! 95 | })) 96 | } 97 | } 98 | 99 | func controllerDidChangeContent(_ controller: NSFetchedResultsController) { 100 | collectionView?.performBatchUpdates({ 101 | for operation in self.blockOperations{ 102 | operation.start() 103 | } 104 | }, completion: { (completed) in 105 | let lastItem = (self.fetchedRequestsController.sections?[0].numberOfObjects)! - 1 106 | let indexPath = IndexPath(item: lastItem, section: 0) 107 | self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 108 | }) 109 | } 110 | override func viewDidLoad() { 111 | super.viewDidLoad() 112 | 113 | do { 114 | try fetchedRequestsController.performFetch() 115 | }catch let error{ 116 | print(error) 117 | } 118 | 119 | tabBarController?.tabBar.isHidden = true 120 | collectionView?.backgroundColor = UIColor.white 121 | collectionView?.register(ChatlogCell.self, forCellWithReuseIdentifier: cellId) 122 | view.addSubview(messageInputContainerView) 123 | view.addConstraintsWithFormat(format: "H:|[v0]|", views: messageInputContainerView) 124 | view.addConstraintsWithFormat(format: "V:[v0(48)]", views: messageInputContainerView) 125 | bottomConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0) 126 | view.addConstraint(bottomConstraint!) 127 | setupInputComponents() 128 | NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboard), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 129 | NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboard), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 130 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Simulate", style: .plain, target: self, action: #selector(simulateSenderMessages)) 131 | } 132 | 133 | func simulateSenderMessages(){ 134 | guard let delegate = UIApplication.shared.delegate as?AppDelegate else{ 135 | return 136 | } 137 | let context = delegate.persistentContainer.viewContext 138 | _ = FriendsController.createMessageWithText(text: "This message was sent a few minutes ago....", friend: friend!, minutesAgo: 1, context: context) 139 | _ = FriendsController.createMessageWithText(text: "Another message was sent a few seconds ago....", friend: friend!, minutesAgo: 0, context: context) 140 | do{ 141 | try context.save() 142 | 143 | }catch let error{ 144 | print(error) 145 | } 146 | } 147 | 148 | func handleKeyboard(notification:NSNotification){ 149 | if let userInfo = notification.userInfo{ 150 | let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue 151 | let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow 152 | bottomConstraint?.constant = isKeyboardShowing ? -(keyboardFrame?.height)! : 0 153 | UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: { 154 | self.view.layoutIfNeeded() 155 | }, completion: { (completed) in 156 | if (isKeyboardShowing){ 157 | let lastItem = (self.fetchedRequestsController.sections?[0].numberOfObjects)! - 1 158 | let indexPath = IndexPath(item: lastItem, section: 0) 159 | self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true) 160 | } 161 | }) 162 | 163 | } 164 | } 165 | 166 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 167 | inputTextField.endEditing(true) 168 | } 169 | 170 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 171 | if let count = fetchedRequestsController.sections?[0].numberOfObjects{ 172 | return count 173 | } 174 | return 0 175 | } 176 | 177 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 178 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ChatlogCell 179 | let message = fetchedRequestsController.object(at: indexPath) as! Message 180 | cell.messageTextView.text = message.text 181 | 182 | 183 | if let messageText = message.text, let profileImageName = message.friend?.profileImageName{ 184 | 185 | cell.profileImageView.image = UIImage(named: profileImageName) 186 | let size = CGSize(width: 250, height: 1000) 187 | let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) 188 | let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 18)], context: nil) 189 | if !message.isSender{ 190 | cell.messageTextView.frame = CGRect(x: 48+8, y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height+20) 191 | cell.textBubbleView.frame = CGRect(x: 48 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 16, height: estimatedFrame.height+20+6) 192 | cell.profileImageView.isHidden = false 193 | cell.bubbleImageView.image = ChatlogCell.grayBubbleImage 194 | cell.bubbleImageView.tintColor = UIColor(white: 0.95, alpha: 1) 195 | cell.messageTextView.textColor = UIColor.black 196 | } 197 | else{ 198 | 199 | //outgoing sender messages 200 | cell.messageTextView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 16 - 8 , y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height+20) 201 | cell.textBubbleView.frame = CGRect(x: view.frame.width-estimatedFrame.width - 16 - 8 - 16 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 10, height: estimatedFrame.height+20+6) 202 | cell.profileImageView.isHidden = true 203 | cell.bubbleImageView.image = ChatlogCell.blueBubbleImage 204 | cell.bubbleImageView.tintColor = UIColor.returnRGBColor(r: 0, g: 137, b: 249, alpha: 1) 205 | cell.messageTextView.textColor = UIColor.white 206 | } 207 | 208 | } 209 | return cell 210 | } 211 | 212 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 213 | let message = fetchedRequestsController.object(at: indexPath) as! Message 214 | if let messageText = message.text{ 215 | let size = CGSize(width: 250, height: 1000) 216 | let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) 217 | let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: 18)], context: nil) 218 | return CGSize(width: view.frame.width, height: estimatedFrame.height+20) 219 | } 220 | return CGSize(width: view.frame.width, height: 100) 221 | } 222 | 223 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 224 | return UIEdgeInsetsMake(8, 0, 0, 0) 225 | } 226 | } 227 | 228 | class ChatlogCell:BaseCell{ 229 | 230 | static let grayBubbleImage = UIImage(named:"bubble_gray")?.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate) 231 | static let blueBubbleImage = UIImage(named:"bubble_blue")?.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate) 232 | 233 | 234 | let messageTextView : UITextView = { 235 | let textView = UITextView() 236 | textView.text = "Sample Message" 237 | textView.font = UIFont.systemFont(ofSize: 18) 238 | textView.backgroundColor = UIColor.clear 239 | textView.isEditable = false 240 | return textView 241 | }() 242 | 243 | let textBubbleView:UIView = { 244 | let view = UIView() 245 | view.layer.cornerRadius = 15 246 | view.layer.masksToBounds = true 247 | return view 248 | }() 249 | 250 | let profileImageView: UIImageView = { 251 | let iv = UIImageView() 252 | iv.layer.cornerRadius = 15 253 | iv.layer.masksToBounds = true 254 | return iv 255 | }() 256 | 257 | let bubbleImageView : UIImageView = { 258 | let iv = UIImageView() 259 | iv.image = ChatlogCell.grayBubbleImage 260 | iv.tintColor = UIColor(white: 0.90, alpha: 1) 261 | return iv 262 | }() 263 | 264 | override func setupViews() { 265 | super.setupViews() 266 | 267 | addSubview(textBubbleView) 268 | addSubview(messageTextView) 269 | addSubview(profileImageView) 270 | 271 | addConstraintsWithFormat(format: "H:|-8-[v0(30)]|", views: profileImageView) 272 | addConstraintsWithFormat(format: "V:[v0(30)]|", views: profileImageView) 273 | 274 | textBubbleView.addSubview(bubbleImageView) 275 | textBubbleView.addConstraintsWithFormat(format: "H:|[v0]|", views: bubbleImageView) 276 | textBubbleView.addConstraintsWithFormat(format: "V:|[v0]|", views: bubbleImageView) 277 | 278 | } 279 | 280 | } 281 | -------------------------------------------------------------------------------- /fbMessenger.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 967455681EDFC9130010CE2C /* ChatLogController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967455671EDFC9130010CE2C /* ChatLogController.swift */; }; 11 | 9674556A1EDFD5910010CE2C /* CustomTabbarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 967455691EDFD5910010CE2C /* CustomTabbarController.swift */; }; 12 | 96988E9A1EDDD5CA0098F653 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96988E991EDDD5CA0098F653 /* AppDelegate.swift */; }; 13 | 96988E9C1EDDD5CA0098F653 /* FriendsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96988E9B1EDDD5CA0098F653 /* FriendsController.swift */; }; 14 | 96988EA21EDDD5CA0098F653 /* fbMessenger.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 96988EA01EDDD5CA0098F653 /* fbMessenger.xcdatamodeld */; }; 15 | 96988EA41EDDD5CA0098F653 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96988EA31EDDD5CA0098F653 /* Assets.xcassets */; }; 16 | 96988EA71EDDD5CA0098F653 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96988EA51EDDD5CA0098F653 /* LaunchScreen.storyboard */; }; 17 | 96988EAF1EDDD6330098F653 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96988EAE1EDDD6330098F653 /* Extensions.swift */; }; 18 | 96988EB11EDDD6520098F653 /* FriendsControllerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96988EB01EDDD6520098F653 /* FriendsControllerHelper.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 967455671EDFC9130010CE2C /* ChatLogController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatLogController.swift; sourceTree = ""; }; 23 | 967455691EDFD5910010CE2C /* CustomTabbarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomTabbarController.swift; sourceTree = ""; }; 24 | 96988E961EDDD5CA0098F653 /* fbMessenger.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fbMessenger.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 96988E991EDDD5CA0098F653 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 26 | 96988E9B1EDDD5CA0098F653 /* FriendsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsController.swift; sourceTree = ""; }; 27 | 96988EA11EDDD5CA0098F653 /* fbMessenger.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = fbMessenger.xcdatamodel; sourceTree = ""; }; 28 | 96988EA31EDDD5CA0098F653 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | 96988EA61EDDD5CA0098F653 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 30 | 96988EA81EDDD5CA0098F653 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 96988EAE1EDDD6330098F653 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; }; 32 | 96988EB01EDDD6520098F653 /* FriendsControllerHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FriendsControllerHelper.swift; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 96988E931EDDD5CA0098F653 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | 96988E8D1EDDD5CA0098F653 = { 47 | isa = PBXGroup; 48 | children = ( 49 | 96988E981EDDD5CA0098F653 /* fbMessenger */, 50 | 96988E971EDDD5CA0098F653 /* Products */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | 96988E971EDDD5CA0098F653 /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 96988E961EDDD5CA0098F653 /* fbMessenger.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | 96988E981EDDD5CA0098F653 /* fbMessenger */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 96988E991EDDD5CA0098F653 /* AppDelegate.swift */, 66 | 96988E9B1EDDD5CA0098F653 /* FriendsController.swift */, 67 | 967455691EDFD5910010CE2C /* CustomTabbarController.swift */, 68 | 96988EAE1EDDD6330098F653 /* Extensions.swift */, 69 | 967455671EDFC9130010CE2C /* ChatLogController.swift */, 70 | 96988EB01EDDD6520098F653 /* FriendsControllerHelper.swift */, 71 | 96988EA31EDDD5CA0098F653 /* Assets.xcassets */, 72 | 96988EA51EDDD5CA0098F653 /* LaunchScreen.storyboard */, 73 | 96988EA81EDDD5CA0098F653 /* Info.plist */, 74 | 96988EA01EDDD5CA0098F653 /* fbMessenger.xcdatamodeld */, 75 | ); 76 | path = fbMessenger; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 96988E951EDDD5CA0098F653 /* fbMessenger */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 96988EAB1EDDD5CA0098F653 /* Build configuration list for PBXNativeTarget "fbMessenger" */; 85 | buildPhases = ( 86 | 96988E921EDDD5CA0098F653 /* Sources */, 87 | 96988E931EDDD5CA0098F653 /* Frameworks */, 88 | 96988E941EDDD5CA0098F653 /* Resources */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = fbMessenger; 95 | productName = fbMessenger; 96 | productReference = 96988E961EDDD5CA0098F653 /* fbMessenger.app */; 97 | productType = "com.apple.product-type.application"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | 96988E8E1EDDD5CA0098F653 /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastSwiftUpdateCheck = 0830; 106 | LastUpgradeCheck = 0830; 107 | ORGANIZATIONNAME = VamshiKrishna; 108 | TargetAttributes = { 109 | 96988E951EDDD5CA0098F653 = { 110 | CreatedOnToolsVersion = 8.3.2; 111 | DevelopmentTeam = BJBC582Q56; 112 | ProvisioningStyle = Automatic; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = 96988E911EDDD5CA0098F653 /* Build configuration list for PBXProject "fbMessenger" */; 117 | compatibilityVersion = "Xcode 3.2"; 118 | developmentRegion = English; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | Base, 123 | ); 124 | mainGroup = 96988E8D1EDDD5CA0098F653; 125 | productRefGroup = 96988E971EDDD5CA0098F653 /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | 96988E951EDDD5CA0098F653 /* fbMessenger */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXResourcesBuildPhase section */ 135 | 96988E941EDDD5CA0098F653 /* Resources */ = { 136 | isa = PBXResourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | 96988EA71EDDD5CA0098F653 /* LaunchScreen.storyboard in Resources */, 140 | 96988EA41EDDD5CA0098F653 /* Assets.xcassets in Resources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXResourcesBuildPhase section */ 145 | 146 | /* Begin PBXSourcesBuildPhase section */ 147 | 96988E921EDDD5CA0098F653 /* Sources */ = { 148 | isa = PBXSourcesBuildPhase; 149 | buildActionMask = 2147483647; 150 | files = ( 151 | 967455681EDFC9130010CE2C /* ChatLogController.swift in Sources */, 152 | 96988E9C1EDDD5CA0098F653 /* FriendsController.swift in Sources */, 153 | 96988EA21EDDD5CA0098F653 /* fbMessenger.xcdatamodeld in Sources */, 154 | 96988E9A1EDDD5CA0098F653 /* AppDelegate.swift in Sources */, 155 | 9674556A1EDFD5910010CE2C /* CustomTabbarController.swift in Sources */, 156 | 96988EAF1EDDD6330098F653 /* Extensions.swift in Sources */, 157 | 96988EB11EDDD6520098F653 /* FriendsControllerHelper.swift in Sources */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXSourcesBuildPhase section */ 162 | 163 | /* Begin PBXVariantGroup section */ 164 | 96988EA51EDDD5CA0098F653 /* LaunchScreen.storyboard */ = { 165 | isa = PBXVariantGroup; 166 | children = ( 167 | 96988EA61EDDD5CA0098F653 /* Base */, 168 | ); 169 | name = LaunchScreen.storyboard; 170 | sourceTree = ""; 171 | }; 172 | /* End PBXVariantGroup section */ 173 | 174 | /* Begin XCBuildConfiguration section */ 175 | 96988EA91EDDD5CA0098F653 /* Debug */ = { 176 | isa = XCBuildConfiguration; 177 | buildSettings = { 178 | ALWAYS_SEARCH_USER_PATHS = NO; 179 | CLANG_ANALYZER_NONNULL = YES; 180 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 181 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 182 | CLANG_CXX_LIBRARY = "libc++"; 183 | CLANG_ENABLE_MODULES = YES; 184 | CLANG_ENABLE_OBJC_ARC = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_CONSTANT_CONVERSION = YES; 187 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 188 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 189 | CLANG_WARN_EMPTY_BODY = YES; 190 | CLANG_WARN_ENUM_CONVERSION = YES; 191 | CLANG_WARN_INFINITE_RECURSION = YES; 192 | CLANG_WARN_INT_CONVERSION = YES; 193 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 194 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 195 | CLANG_WARN_UNREACHABLE_CODE = YES; 196 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 197 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 198 | COPY_PHASE_STRIP = NO; 199 | DEBUG_INFORMATION_FORMAT = dwarf; 200 | ENABLE_STRICT_OBJC_MSGSEND = YES; 201 | ENABLE_TESTABILITY = YES; 202 | GCC_C_LANGUAGE_STANDARD = gnu99; 203 | GCC_DYNAMIC_NO_PIC = NO; 204 | GCC_NO_COMMON_BLOCKS = YES; 205 | GCC_OPTIMIZATION_LEVEL = 0; 206 | GCC_PREPROCESSOR_DEFINITIONS = ( 207 | "DEBUG=1", 208 | "$(inherited)", 209 | ); 210 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 211 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 212 | GCC_WARN_UNDECLARED_SELECTOR = YES; 213 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 214 | GCC_WARN_UNUSED_FUNCTION = YES; 215 | GCC_WARN_UNUSED_VARIABLE = YES; 216 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 217 | MTL_ENABLE_DEBUG_INFO = YES; 218 | ONLY_ACTIVE_ARCH = YES; 219 | SDKROOT = iphoneos; 220 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 221 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 222 | }; 223 | name = Debug; 224 | }; 225 | 96988EAA1EDDD5CA0098F653 /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ALWAYS_SEARCH_USER_PATHS = NO; 229 | CLANG_ANALYZER_NONNULL = YES; 230 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 231 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 232 | CLANG_CXX_LIBRARY = "libc++"; 233 | CLANG_ENABLE_MODULES = YES; 234 | CLANG_ENABLE_OBJC_ARC = YES; 235 | CLANG_WARN_BOOL_CONVERSION = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 244 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 245 | CLANG_WARN_UNREACHABLE_CODE = YES; 246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 247 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 248 | COPY_PHASE_STRIP = NO; 249 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 250 | ENABLE_NS_ASSERTIONS = NO; 251 | ENABLE_STRICT_OBJC_MSGSEND = YES; 252 | GCC_C_LANGUAGE_STANDARD = gnu99; 253 | GCC_NO_COMMON_BLOCKS = YES; 254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 256 | GCC_WARN_UNDECLARED_SELECTOR = YES; 257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 258 | GCC_WARN_UNUSED_FUNCTION = YES; 259 | GCC_WARN_UNUSED_VARIABLE = YES; 260 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 261 | MTL_ENABLE_DEBUG_INFO = NO; 262 | SDKROOT = iphoneos; 263 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 264 | VALIDATE_PRODUCT = YES; 265 | }; 266 | name = Release; 267 | }; 268 | 96988EAC1EDDD5CA0098F653 /* Debug */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 272 | DEVELOPMENT_TEAM = BJBC582Q56; 273 | INFOPLIST_FILE = fbMessenger/Info.plist; 274 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 275 | PRODUCT_BUNDLE_IDENTIFIER = VamshiKrishna.fbMessenger; 276 | PRODUCT_NAME = "$(TARGET_NAME)"; 277 | SWIFT_VERSION = 3.0; 278 | }; 279 | name = Debug; 280 | }; 281 | 96988EAD1EDDD5CA0098F653 /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | DEVELOPMENT_TEAM = BJBC582Q56; 286 | INFOPLIST_FILE = fbMessenger/Info.plist; 287 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 288 | PRODUCT_BUNDLE_IDENTIFIER = VamshiKrishna.fbMessenger; 289 | PRODUCT_NAME = "$(TARGET_NAME)"; 290 | SWIFT_VERSION = 3.0; 291 | }; 292 | name = Release; 293 | }; 294 | /* End XCBuildConfiguration section */ 295 | 296 | /* Begin XCConfigurationList section */ 297 | 96988E911EDDD5CA0098F653 /* Build configuration list for PBXProject "fbMessenger" */ = { 298 | isa = XCConfigurationList; 299 | buildConfigurations = ( 300 | 96988EA91EDDD5CA0098F653 /* Debug */, 301 | 96988EAA1EDDD5CA0098F653 /* Release */, 302 | ); 303 | defaultConfigurationIsVisible = 0; 304 | defaultConfigurationName = Release; 305 | }; 306 | 96988EAB1EDDD5CA0098F653 /* Build configuration list for PBXNativeTarget "fbMessenger" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 96988EAC1EDDD5CA0098F653 /* Debug */, 310 | 96988EAD1EDDD5CA0098F653 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | /* End XCConfigurationList section */ 316 | 317 | /* Begin XCVersionGroup section */ 318 | 96988EA01EDDD5CA0098F653 /* fbMessenger.xcdatamodeld */ = { 319 | isa = XCVersionGroup; 320 | children = ( 321 | 96988EA11EDDD5CA0098F653 /* fbMessenger.xcdatamodel */, 322 | ); 323 | currentVersion = 96988EA11EDDD5CA0098F653 /* fbMessenger.xcdatamodel */; 324 | path = fbMessenger.xcdatamodeld; 325 | sourceTree = ""; 326 | versionGroupType = wrapper.xcdatamodel; 327 | }; 328 | /* End XCVersionGroup section */ 329 | }; 330 | rootObject = 96988E8E1EDDD5CA0098F653 /* Project object */; 331 | } 332 | --------------------------------------------------------------------------------