diff --git a/AsyncMessagesViewController.xcodeproj/project.pbxproj b/AsyncMessagesViewController.xcodeproj/project.pbxproj
index 6ab3827..8f5117f 100644
--- a/AsyncMessagesViewController.xcodeproj/project.pbxproj
+++ b/AsyncMessagesViewController.xcodeproj/project.pbxproj
@@ -1,1154 +1,543 @@
-
-
-
-
- archiveVersion
- 1
- classes
-
- objectVersion
- 46
- objects
-
- 080CACC9FA2D9895B6933DAA
-
- children
-
- 1B8A292D9BC7865A434B294B
-
- isa
- PBXGroup
- name
- Frameworks
- sourceTree
- <group>
-
- 1B8A292D9BC7865A434B294B
-
- explicitFileType
- archive.ar
- includeInIndex
- 0
- isa
- PBXFileReference
- path
- libPods.a
- sourceTree
- BUILT_PRODUCTS_DIR
-
- 25F321179298F8B73D192950
-
- children
-
- 94DD265A8EFB33113BE48D46
- BE8CB3D008F5A8DD8B90B1F1
-
- isa
- PBXGroup
- name
- Pods
- sourceTree
- <group>
-
- 3300D7AB49227487C436845B
-
- buildActionMask
- 2147483647
- files
-
- inputPaths
-
- isa
- PBXShellScriptBuildPhase
- name
- Embed Pods Frameworks
- outputPaths
-
- runOnlyForDeploymentPostprocessing
- 0
- shellPath
- /bin/sh
- shellScript
- "${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh"
-
- showEnvVarsInLog
- 0
-
- 67D68737ADC5DFB55D064BB3
-
- buildActionMask
- 2147483647
- files
-
- inputPaths
-
- isa
- PBXShellScriptBuildPhase
- name
- Check Pods Manifest.lock
- outputPaths
-
- runOnlyForDeploymentPostprocessing
- 0
- shellPath
- /bin/sh
- shellScript
- diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
-if [[ $? != 0 ]] ; then
- cat << EOM
-error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
-EOM
- exit 1
-fi
-
- showEnvVarsInLog
- 0
-
- 8A65FC5D0532763D2834849D
-
- buildActionMask
- 2147483647
- files
-
- inputPaths
-
- isa
- PBXShellScriptBuildPhase
- name
- Copy Pods Resources
- outputPaths
-
- runOnlyForDeploymentPostprocessing
- 0
- shellPath
- /bin/sh
- shellScript
- "${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh"
-
- showEnvVarsInLog
- 0
-
- 94DD265A8EFB33113BE48D46
-
- includeInIndex
- 1
- isa
- PBXFileReference
- lastKnownFileType
- text.xcconfig
- name
- Pods.debug.xcconfig
- path
- Pods/Target Support Files/Pods/Pods.debug.xcconfig
- sourceTree
- <group>
-
- AC8B65C41A9373DA00131D84
-
- children
-
- AC8B65CF1A9373DA00131D84
- ACC6EF4A1AA1A870002B76A9
- AC8B65CE1A9373DA00131D84
- 25F321179298F8B73D192950
- 080CACC9FA2D9895B6933DAA
-
- isa
- PBXGroup
- sourceTree
- <group>
-
- AC8B65C51A9373DA00131D84
-
- attributes
-
- LastSwiftMigration
- 0700
- LastSwiftUpdateCheck
- 0700
- LastUpgradeCheck
- 0800
- ORGANIZATIONNAME
- Huy Nguyen
- TargetAttributes
-
- AC8B65CC1A9373DA00131D84
-
- CreatedOnToolsVersion
- 6.1.1
- DevelopmentTeam
- H4EJPVDUSS
- LastSwiftMigration
- 0800
-
-
-
- buildConfigurationList
- AC8B65C81A9373DA00131D84
- compatibilityVersion
- Xcode 3.2
- developmentRegion
- English
- hasScannedForEncodings
- 0
- isa
- PBXProject
- knownRegions
-
- en
- Base
-
- mainGroup
- AC8B65C41A9373DA00131D84
- productRefGroup
- AC8B65CE1A9373DA00131D84
- projectDirPath
-
- projectReferences
-
- projectRoot
-
- targets
-
- AC8B65CC1A9373DA00131D84
-
-
- AC8B65C81A9373DA00131D84
-
- buildConfigurations
-
- AC8B65EA1A9373DA00131D84
- AC8B65EB1A9373DA00131D84
-
- defaultConfigurationIsVisible
- 0
- defaultConfigurationName
- Release
- isa
- XCConfigurationList
-
- AC8B65C91A9373DA00131D84
-
- buildActionMask
- 2147483647
- files
-
- ACC6EF641AA1A870002B76A9
- AC8B65D51A9373DA00131D84
- ACC6EF691AA1A870002B76A9
- AC90D5FF1AA1A68F0042C0D4
- ACC6EF601AA1A870002B76A9
- ACC6EF631AA1A870002B76A9
- ACC6EF5E1AA1A870002B76A9
- ACC6EF611AA1A870002B76A9
- ACC6EF661AA1A870002B76A9
- ACC6EF5F1AA1A870002B76A9
- ACC6EF681AA1A870002B76A9
- AC8B65D31A9373DA00131D84
- AC90D5FE1AA1A68F0042C0D4
- ACCC86871AAB35CB00DB37B7
- ACC6EF621AA1A870002B76A9
- ACC6EF6A1AA1A870002B76A9
-
- isa
- PBXSourcesBuildPhase
- runOnlyForDeploymentPostprocessing
- 0
-
- AC8B65CA1A9373DA00131D84
-
- buildActionMask
- 2147483647
- files
-
- E3FABBFD495008D609A54397
-
- isa
- PBXFrameworksBuildPhase
- runOnlyForDeploymentPostprocessing
- 0
-
- AC8B65CB1A9373DA00131D84
-
- buildActionMask
- 2147483647
- files
-
- ACC6EF5D1AA1A870002B76A9
- AC8B65DD1A9373DA00131D84
- AC8B65DA1A9373DA00131D84
-
- isa
- PBXResourcesBuildPhase
- runOnlyForDeploymentPostprocessing
- 0
-
- AC8B65CC1A9373DA00131D84
-
- buildConfigurationList
- AC8B65EC1A9373DA00131D84
- buildPhases
-
- 67D68737ADC5DFB55D064BB3
- AC8B65C91A9373DA00131D84
- AC8B65CA1A9373DA00131D84
- AC8B65CB1A9373DA00131D84
- 8A65FC5D0532763D2834849D
- 3300D7AB49227487C436845B
-
- buildRules
-
- dependencies
-
- isa
- PBXNativeTarget
- name
- Example
- productName
- Example
- productReference
- AC8B65CD1A9373DA00131D84
- productType
- com.apple.product-type.application
-
- AC8B65CD1A9373DA00131D84
-
- explicitFileType
- wrapper.application
- includeInIndex
- 0
- isa
- PBXFileReference
- path
- Example.app
- sourceTree
- BUILT_PRODUCTS_DIR
-
- AC8B65CE1A9373DA00131D84
-
- children
-
- AC8B65CD1A9373DA00131D84
-
- isa
- PBXGroup
- name
- Products
- sourceTree
- <group>
-
- AC8B65CF1A9373DA00131D84
-
- children
-
- AC90D6001AA1A7380042C0D4
- AC8B65D21A9373DA00131D84
- AC8B66261A9378D500131D84
- AC8B66271A9378DE00131D84
- AC8B65D91A9373DA00131D84
- AC8B65DB1A9373DA00131D84
- AC8B65D01A9373DA00131D84
-
- isa
- PBXGroup
- path
- Example
- sourceTree
- <group>
-
- AC8B65D01A9373DA00131D84
-
- children
-
- AC8B65D11A9373DA00131D84
-
- isa
- PBXGroup
- name
- Supporting Files
- sourceTree
- <group>
-
- AC8B65D11A9373DA00131D84
-
- isa
- PBXFileReference
- lastKnownFileType
- text.plist.xml
- path
- Info.plist
- sourceTree
- <group>
-
- AC8B65D21A9373DA00131D84
-
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- AppDelegate.swift
- sourceTree
- <group>
-
- AC8B65D31A9373DA00131D84
-
- fileRef
- AC8B65D21A9373DA00131D84
- isa
- PBXBuildFile
-
- AC8B65D41A9373DA00131D84
-
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- ViewController.swift
- sourceTree
- <group>
-
- AC8B65D51A9373DA00131D84
-
- fileRef
- AC8B65D41A9373DA00131D84
- isa
- PBXBuildFile
-
- AC8B65D91A9373DA00131D84
-
- isa
- PBXFileReference
- lastKnownFileType
- folder.assetcatalog
- path
- Images.xcassets
- sourceTree
- <group>
-
- AC8B65DA1A9373DA00131D84
-
- fileRef
- AC8B65D91A9373DA00131D84
- isa
- PBXBuildFile
-
- AC8B65DB1A9373DA00131D84
-
- children
-
- AC8B65DC1A9373DA00131D84
-
- isa
- PBXVariantGroup
- name
- LaunchScreen.xib
- sourceTree
- <group>
-
- AC8B65DC1A9373DA00131D84
-
- isa
- PBXFileReference
- lastKnownFileType
- file.xib
- name
- Base
- path
- Base.lproj/LaunchScreen.xib
- sourceTree
- <group>
-
- AC8B65DD1A9373DA00131D84
-
- fileRef
- AC8B65DB1A9373DA00131D84
- isa
- PBXBuildFile
-
- AC8B65EA1A9373DA00131D84
-
- buildSettings
-
- ALWAYS_SEARCH_USER_PATHS
- NO
- CLANG_CXX_LANGUAGE_STANDARD
- gnu++0x
- CLANG_CXX_LIBRARY
- libc++
- CLANG_ENABLE_MODULES
- YES
- CLANG_ENABLE_OBJC_ARC
- YES
- CLANG_WARN_BOOL_CONVERSION
- YES
- CLANG_WARN_CONSTANT_CONVERSION
- YES
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE
- YES_ERROR
- CLANG_WARN_EMPTY_BODY
- YES
- CLANG_WARN_ENUM_CONVERSION
- YES
- CLANG_WARN_INFINITE_RECURSION
- YES
- CLANG_WARN_INT_CONVERSION
- YES
- CLANG_WARN_OBJC_ROOT_CLASS
- YES_ERROR
- CLANG_WARN_SUSPICIOUS_MOVE
- YES
- CLANG_WARN_UNREACHABLE_CODE
- YES
- CLANG_WARN__DUPLICATE_METHOD_MATCH
- YES
- CODE_SIGN_IDENTITY[sdk=iphoneos*]
- iPhone Developer
- COPY_PHASE_STRIP
- NO
- ENABLE_STRICT_OBJC_MSGSEND
- YES
- ENABLE_TESTABILITY
- YES
- GCC_C_LANGUAGE_STANDARD
- gnu99
- GCC_DYNAMIC_NO_PIC
- NO
- GCC_NO_COMMON_BLOCKS
- YES
- GCC_OPTIMIZATION_LEVEL
- 0
- GCC_PREPROCESSOR_DEFINITIONS
-
- DEBUG=1
- $(inherited)
-
- GCC_SYMBOLS_PRIVATE_EXTERN
- NO
- GCC_WARN_64_TO_32_BIT_CONVERSION
- YES
- GCC_WARN_ABOUT_RETURN_TYPE
- YES_ERROR
- GCC_WARN_UNDECLARED_SELECTOR
- YES
- GCC_WARN_UNINITIALIZED_AUTOS
- YES_AGGRESSIVE
- GCC_WARN_UNUSED_FUNCTION
- YES
- GCC_WARN_UNUSED_VARIABLE
- YES
- IPHONEOS_DEPLOYMENT_TARGET
- 8.1
- MTL_ENABLE_DEBUG_INFO
- YES
- ONLY_ACTIVE_ARCH
- YES
- SDKROOT
- iphoneos
- SWIFT_OPTIMIZATION_LEVEL
- -Onone
-
- isa
- XCBuildConfiguration
- name
- Debug
-
- AC8B65EB1A9373DA00131D84
-
- buildSettings
-
- ALWAYS_SEARCH_USER_PATHS
- NO
- CLANG_CXX_LANGUAGE_STANDARD
- gnu++0x
- CLANG_CXX_LIBRARY
- libc++
- CLANG_ENABLE_MODULES
- YES
- CLANG_ENABLE_OBJC_ARC
- YES
- CLANG_WARN_BOOL_CONVERSION
- YES
- CLANG_WARN_CONSTANT_CONVERSION
- YES
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE
- YES_ERROR
- CLANG_WARN_EMPTY_BODY
- YES
- CLANG_WARN_ENUM_CONVERSION
- YES
- CLANG_WARN_INFINITE_RECURSION
- YES
- CLANG_WARN_INT_CONVERSION
- YES
- CLANG_WARN_OBJC_ROOT_CLASS
- YES_ERROR
- CLANG_WARN_SUSPICIOUS_MOVE
- YES
- CLANG_WARN_UNREACHABLE_CODE
- YES
- CLANG_WARN__DUPLICATE_METHOD_MATCH
- YES
- CODE_SIGN_IDENTITY[sdk=iphoneos*]
- iPhone Developer
- COPY_PHASE_STRIP
- YES
- ENABLE_NS_ASSERTIONS
- NO
- ENABLE_STRICT_OBJC_MSGSEND
- YES
- GCC_C_LANGUAGE_STANDARD
- gnu99
- GCC_NO_COMMON_BLOCKS
- YES
- GCC_WARN_64_TO_32_BIT_CONVERSION
- YES
- GCC_WARN_ABOUT_RETURN_TYPE
- YES_ERROR
- GCC_WARN_UNDECLARED_SELECTOR
- YES
- GCC_WARN_UNINITIALIZED_AUTOS
- YES_AGGRESSIVE
- GCC_WARN_UNUSED_FUNCTION
- YES
- GCC_WARN_UNUSED_VARIABLE
- YES
- IPHONEOS_DEPLOYMENT_TARGET
- 8.1
- MTL_ENABLE_DEBUG_INFO
- NO
- SDKROOT
- iphoneos
- SWIFT_OPTIMIZATION_LEVEL
- -Owholemodule
- VALIDATE_PRODUCT
- YES
-
- isa
- XCBuildConfiguration
- name
- Release
-
- AC8B65EC1A9373DA00131D84
-
- buildConfigurations
-
- AC8B65ED1A9373DA00131D84
- AC8B65EE1A9373DA00131D84
-
- defaultConfigurationIsVisible
- 0
- defaultConfigurationName
- Release
- isa
- XCConfigurationList
-
- AC8B65ED1A9373DA00131D84
-
- baseConfigurationReference
- 94DD265A8EFB33113BE48D46
- buildSettings
-
- ASSETCATALOG_COMPILER_APPICON_NAME
- AppIcon
- CLANG_ENABLE_MODULES
- YES
- DEVELOPMENT_TEAM
- H4EJPVDUSS
- INFOPLIST_FILE
- Example/Info.plist
- LD_RUNPATH_SEARCH_PATHS
- $(inherited) @executable_path/Frameworks
- PRODUCT_BUNDLE_IDENTIFIER
- me.huytnguyen.AsyncMessagesViewController.$(PRODUCT_NAME:rfc1034identifier)
- PRODUCT_NAME
- $(TARGET_NAME)
- SWIFT_OBJC_BRIDGING_HEADER
- Example/Example-Bridging-Header.h
- SWIFT_OPTIMIZATION_LEVEL
- -Onone
- SWIFT_VERSION
- 3.0
- TARGETED_DEVICE_FAMILY
- 1,2
-
- isa
- XCBuildConfiguration
- name
- Debug
-
- AC8B65EE1A9373DA00131D84
-
- baseConfigurationReference
- BE8CB3D008F5A8DD8B90B1F1
- buildSettings
-
- ASSETCATALOG_COMPILER_APPICON_NAME
- AppIcon
- CLANG_ENABLE_MODULES
- YES
- DEVELOPMENT_TEAM
- H4EJPVDUSS
- INFOPLIST_FILE
- Example/Info.plist
- LD_RUNPATH_SEARCH_PATHS
- $(inherited) @executable_path/Frameworks
- PRODUCT_BUNDLE_IDENTIFIER
- me.huytnguyen.AsyncMessagesViewController.$(PRODUCT_NAME:rfc1034identifier)
- PRODUCT_NAME
- $(TARGET_NAME)
- SWIFT_OBJC_BRIDGING_HEADER
- Example/Example-Bridging-Header.h
- SWIFT_VERSION
- 3.0
- TARGETED_DEVICE_FAMILY
- 1,2
-
- isa
- XCBuildConfiguration
- name
- Release
-
- AC8B66261A9378D500131D84
-
- children
-
- AC90D5FC1AA1A68F0042C0D4
- AC90D5FD1AA1A68F0042C0D4
-
- isa
- PBXGroup
- name
- Model
- sourceTree
- <group>
-
- AC8B66271A9378DE00131D84
-
- children
-
- AC8B65D41A9373DA00131D84
-
- isa
- PBXGroup
- name
- Controller
- sourceTree
- <group>
-
- AC90D5FC1AA1A68F0042C0D4
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- Message.swift
- sourceTree
- <group>
-
- AC90D5FD1AA1A68F0042C0D4
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- User.swift
- sourceTree
- <group>
-
- AC90D5FE1AA1A68F0042C0D4
-
- fileRef
- AC90D5FC1AA1A68F0042C0D4
- isa
- PBXBuildFile
-
- AC90D5FF1AA1A68F0042C0D4
-
- fileRef
- AC90D5FD1AA1A68F0042C0D4
- isa
- PBXBuildFile
-
- AC90D6001AA1A7380042C0D4
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.c.h
- path
- Example-Bridging-Header.h
- sourceTree
- <group>
-
- ACC6EF4A1AA1A870002B76A9
-
- children
-
- ACC6EF4B1AA1A870002B76A9
- ACC6EF541AA1A870002B76A9
- ACC6EF4D1AA1A870002B76A9
- ACC6EF561AA1A870002B76A9
-
- isa
- PBXGroup
- path
- Source
- sourceTree
- <group>
-
- ACC6EF4B1AA1A870002B76A9
-
- children
-
- ACC6EF4C1AA1A870002B76A9
-
- isa
- PBXGroup
- path
- Assets
- sourceTree
- <group>
-
- ACC6EF4C1AA1A870002B76A9
-
- isa
- PBXFileReference
- lastKnownFileType
- folder.assetcatalog
- path
- AsyncMessagesViewController.xcassets
- sourceTree
- <group>
-
- ACC6EF4D1AA1A870002B76A9
-
- children
-
- ACC6EF4F1AA1A870002B76A9
- ACC6EF4E1AA1A870002B76A9
- ACC6EF501AA1A870002B76A9
- ACC6EF511AA1A870002B76A9
- ACC6EF521AA1A870002B76A9
- ACC6EF531AA1A870002B76A9
-
- isa
- PBXGroup
- path
- Controllers
- sourceTree
- <group>
-
- ACC6EF4E1AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- AsyncMessagesCollectionViewDataSource.swift
- sourceTree
- <group>
-
- ACC6EF4F1AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- AsyncMessagesViewController.swift
- sourceTree
- <group>
-
- ACC6EF501AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- DefaultAsyncMessagesCollectionViewDataSource.swift
- sourceTree
- <group>
-
- ACC6EF511AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageBubbleImageProvider.swift
- sourceTree
- <group>
-
- ACC6EF521AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageCellNodeMetadataFactory.swift
- sourceTree
- <group>
-
- ACC6EF531AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageTimestampFormatter.swift
- sourceTree
- <group>
-
- ACC6EF541AA1A870002B76A9
-
- children
-
- ACC6EF551AA1A870002B76A9
-
- isa
- PBXGroup
- path
- Models
- sourceTree
- <group>
-
- ACC6EF551AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageData.swift
- sourceTree
- <group>
-
- ACC6EF561AA1A870002B76A9
-
- children
-
- ACC6EF581AA1A870002B76A9
- ACCC86861AAB35CB00DB37B7
- ACC6EF5A1AA1A870002B76A9
- ACC6EF5B1AA1A870002B76A9
- ACC6EF5C1AA1A870002B76A9
-
- isa
- PBXGroup
- path
- Views
- sourceTree
- <group>
-
- ACC6EF581AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageCellNode.swift
- sourceTree
- <group>
-
- ACC6EF5A1AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageNetworkImageBubbleNode.swift
- sourceTree
- <group>
-
- ACC6EF5B1AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageTextBubbleNode.swift
- sourceTree
- <group>
-
- ACC6EF5C1AA1A870002B76A9
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- UIImageExtensions.swift
- sourceTree
- <group>
-
- ACC6EF5D1AA1A870002B76A9
-
- fileRef
- ACC6EF4C1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF5E1AA1A870002B76A9
-
- fileRef
- ACC6EF4E1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF5F1AA1A870002B76A9
-
- fileRef
- ACC6EF4F1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF601AA1A870002B76A9
-
- fileRef
- ACC6EF501AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF611AA1A870002B76A9
-
- fileRef
- ACC6EF511AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF621AA1A870002B76A9
-
- fileRef
- ACC6EF521AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF631AA1A870002B76A9
-
- fileRef
- ACC6EF531AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF641AA1A870002B76A9
-
- fileRef
- ACC6EF551AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF661AA1A870002B76A9
-
- fileRef
- ACC6EF581AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF681AA1A870002B76A9
-
- fileRef
- ACC6EF5A1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF691AA1A870002B76A9
-
- fileRef
- ACC6EF5B1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACC6EF6A1AA1A870002B76A9
-
- fileRef
- ACC6EF5C1AA1A870002B76A9
- isa
- PBXBuildFile
-
- ACCC86861AAB35CB00DB37B7
-
- fileEncoding
- 4
- isa
- PBXFileReference
- lastKnownFileType
- sourcecode.swift
- path
- MessageBubbleNodeFactory.swift
- sourceTree
- <group>
-
- ACCC86871AAB35CB00DB37B7
-
- fileRef
- ACCC86861AAB35CB00DB37B7
- isa
- PBXBuildFile
-
- BE8CB3D008F5A8DD8B90B1F1
-
- includeInIndex
- 1
- isa
- PBXFileReference
- lastKnownFileType
- text.xcconfig
- name
- Pods.release.xcconfig
- path
- Pods/Target Support Files/Pods/Pods.release.xcconfig
- sourceTree
- <group>
-
- E3FABBFD495008D609A54397
-
- fileRef
- 1B8A292D9BC7865A434B294B
- isa
- PBXBuildFile
-
-
- rootObject
- AC8B65C51A9373DA00131D84
-
-
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 38A1D758204C3AD700C88828 /* DefaultAsyncMessagesCollectionViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A1D757204C3AD700C88828 /* DefaultAsyncMessagesCollectionViewDelegate.swift */; };
+ AC8B65D31A9373DA00131D84 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC8B65D21A9373DA00131D84 /* AppDelegate.swift */; };
+ AC8B65D51A9373DA00131D84 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC8B65D41A9373DA00131D84 /* ViewController.swift */; };
+ AC8B65DA1A9373DA00131D84 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC8B65D91A9373DA00131D84 /* Images.xcassets */; };
+ AC8B65DD1A9373DA00131D84 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = AC8B65DB1A9373DA00131D84 /* LaunchScreen.xib */; };
+ AC90D5FE1AA1A68F0042C0D4 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC90D5FC1AA1A68F0042C0D4 /* Message.swift */; };
+ AC90D5FF1AA1A68F0042C0D4 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC90D5FD1AA1A68F0042C0D4 /* User.swift */; };
+ ACC6EF5D1AA1A870002B76A9 /* AsyncMessagesViewController.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ACC6EF4C1AA1A870002B76A9 /* AsyncMessagesViewController.xcassets */; };
+ ACC6EF5E1AA1A870002B76A9 /* AsyncMessagesCollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF4E1AA1A870002B76A9 /* AsyncMessagesCollectionViewDataSource.swift */; };
+ ACC6EF5F1AA1A870002B76A9 /* AsyncMessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF4F1AA1A870002B76A9 /* AsyncMessagesViewController.swift */; };
+ ACC6EF601AA1A870002B76A9 /* DefaultAsyncMessagesCollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF501AA1A870002B76A9 /* DefaultAsyncMessagesCollectionViewDataSource.swift */; };
+ ACC6EF611AA1A870002B76A9 /* MessageBubbleImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF511AA1A870002B76A9 /* MessageBubbleImageProvider.swift */; };
+ ACC6EF621AA1A870002B76A9 /* MessageCellNodeMetadataFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF521AA1A870002B76A9 /* MessageCellNodeMetadataFactory.swift */; };
+ ACC6EF631AA1A870002B76A9 /* MessageTimestampFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF531AA1A870002B76A9 /* MessageTimestampFormatter.swift */; };
+ ACC6EF641AA1A870002B76A9 /* MessageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF551AA1A870002B76A9 /* MessageData.swift */; };
+ ACC6EF661AA1A870002B76A9 /* MessageCellNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF581AA1A870002B76A9 /* MessageCellNode.swift */; };
+ ACC6EF681AA1A870002B76A9 /* MessageNetworkImageBubbleNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF5A1AA1A870002B76A9 /* MessageNetworkImageBubbleNode.swift */; };
+ ACC6EF691AA1A870002B76A9 /* MessageTextBubbleNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF5B1AA1A870002B76A9 /* MessageTextBubbleNode.swift */; };
+ ACC6EF6A1AA1A870002B76A9 /* UIImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACC6EF5C1AA1A870002B76A9 /* UIImageExtensions.swift */; };
+ ACCC86871AAB35CB00DB37B7 /* MessageBubbleNodeFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACCC86861AAB35CB00DB37B7 /* MessageBubbleNodeFactory.swift */; };
+ D36B1E0236D676ED9AEEE164 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1002051680E3BA9F22166E5C /* Pods_Example.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1002051680E3BA9F22166E5C /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1B8A292D9BC7865A434B294B /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 356CBFABC1F3EA6E78E6884C /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; };
+ 38A1D757204C3AD700C88828 /* DefaultAsyncMessagesCollectionViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAsyncMessagesCollectionViewDelegate.swift; sourceTree = ""; };
+ 94DD265A8EFB33113BE48D46 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
+ AC8B65CD1A9373DA00131D84 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ AC8B65D11A9373DA00131D84 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ AC8B65D21A9373DA00131D84 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ AC8B65D41A9373DA00131D84 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ AC8B65D91A9373DA00131D84 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
+ AC8B65DC1A9373DA00131D84 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
+ AC90D5FC1AA1A68F0042C0D4 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; };
+ AC90D5FD1AA1A68F0042C0D4 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; };
+ ACC6EF4C1AA1A870002B76A9 /* AsyncMessagesViewController.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = AsyncMessagesViewController.xcassets; sourceTree = ""; };
+ ACC6EF4E1AA1A870002B76A9 /* AsyncMessagesCollectionViewDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMessagesCollectionViewDataSource.swift; sourceTree = ""; };
+ ACC6EF4F1AA1A870002B76A9 /* AsyncMessagesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncMessagesViewController.swift; sourceTree = ""; };
+ ACC6EF501AA1A870002B76A9 /* DefaultAsyncMessagesCollectionViewDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultAsyncMessagesCollectionViewDataSource.swift; sourceTree = ""; };
+ ACC6EF511AA1A870002B76A9 /* MessageBubbleImageProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageBubbleImageProvider.swift; sourceTree = ""; };
+ ACC6EF521AA1A870002B76A9 /* MessageCellNodeMetadataFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellNodeMetadataFactory.swift; sourceTree = ""; };
+ ACC6EF531AA1A870002B76A9 /* MessageTimestampFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTimestampFormatter.swift; sourceTree = ""; };
+ ACC6EF551AA1A870002B76A9 /* MessageData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageData.swift; sourceTree = ""; };
+ ACC6EF581AA1A870002B76A9 /* MessageCellNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellNode.swift; sourceTree = ""; };
+ ACC6EF5A1AA1A870002B76A9 /* MessageNetworkImageBubbleNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageNetworkImageBubbleNode.swift; sourceTree = ""; };
+ ACC6EF5B1AA1A870002B76A9 /* MessageTextBubbleNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTextBubbleNode.swift; sourceTree = ""; };
+ ACC6EF5C1AA1A870002B76A9 /* UIImageExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = ""; };
+ ACCC86861AAB35CB00DB37B7 /* MessageBubbleNodeFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageBubbleNodeFactory.swift; sourceTree = ""; };
+ BE8CB3D008F5A8DD8B90B1F1 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
+ E9324B7353C16801DF96CCCD /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ AC8B65CA1A9373DA00131D84 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D36B1E0236D676ED9AEEE164 /* Pods_Example.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080CACC9FA2D9895B6933DAA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1B8A292D9BC7865A434B294B /* libPods.a */,
+ 1002051680E3BA9F22166E5C /* Pods_Example.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 25F321179298F8B73D192950 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 94DD265A8EFB33113BE48D46 /* Pods.debug.xcconfig */,
+ BE8CB3D008F5A8DD8B90B1F1 /* Pods.release.xcconfig */,
+ E9324B7353C16801DF96CCCD /* Pods-Example.debug.xcconfig */,
+ 356CBFABC1F3EA6E78E6884C /* Pods-Example.release.xcconfig */,
+ );
+ name = Pods;
+ sourceTree = "";
+ };
+ AC8B65C41A9373DA00131D84 = {
+ isa = PBXGroup;
+ children = (
+ AC8B65CF1A9373DA00131D84 /* Example */,
+ ACC6EF4A1AA1A870002B76A9 /* Source */,
+ AC8B65CE1A9373DA00131D84 /* Products */,
+ 25F321179298F8B73D192950 /* Pods */,
+ 080CACC9FA2D9895B6933DAA /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ AC8B65CE1A9373DA00131D84 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ AC8B65CD1A9373DA00131D84 /* Example.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ AC8B65CF1A9373DA00131D84 /* Example */ = {
+ isa = PBXGroup;
+ children = (
+ AC8B65D21A9373DA00131D84 /* AppDelegate.swift */,
+ AC8B66261A9378D500131D84 /* Model */,
+ AC8B66271A9378DE00131D84 /* Controller */,
+ AC8B65D91A9373DA00131D84 /* Images.xcassets */,
+ AC8B65DB1A9373DA00131D84 /* LaunchScreen.xib */,
+ AC8B65D01A9373DA00131D84 /* Supporting Files */,
+ );
+ path = Example;
+ sourceTree = "";
+ };
+ AC8B65D01A9373DA00131D84 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ AC8B65D11A9373DA00131D84 /* Info.plist */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ AC8B66261A9378D500131D84 /* Model */ = {
+ isa = PBXGroup;
+ children = (
+ AC90D5FC1AA1A68F0042C0D4 /* Message.swift */,
+ AC90D5FD1AA1A68F0042C0D4 /* User.swift */,
+ );
+ name = Model;
+ sourceTree = "";
+ };
+ AC8B66271A9378DE00131D84 /* Controller */ = {
+ isa = PBXGroup;
+ children = (
+ AC8B65D41A9373DA00131D84 /* ViewController.swift */,
+ );
+ name = Controller;
+ sourceTree = "";
+ };
+ ACC6EF4A1AA1A870002B76A9 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ ACC6EF4B1AA1A870002B76A9 /* Assets */,
+ ACC6EF541AA1A870002B76A9 /* Models */,
+ ACC6EF4D1AA1A870002B76A9 /* Controllers */,
+ ACC6EF561AA1A870002B76A9 /* Views */,
+ );
+ path = Source;
+ sourceTree = "";
+ };
+ ACC6EF4B1AA1A870002B76A9 /* Assets */ = {
+ isa = PBXGroup;
+ children = (
+ ACC6EF4C1AA1A870002B76A9 /* AsyncMessagesViewController.xcassets */,
+ );
+ path = Assets;
+ sourceTree = "";
+ };
+ ACC6EF4D1AA1A870002B76A9 /* Controllers */ = {
+ isa = PBXGroup;
+ children = (
+ ACC6EF4F1AA1A870002B76A9 /* AsyncMessagesViewController.swift */,
+ ACC6EF4E1AA1A870002B76A9 /* AsyncMessagesCollectionViewDataSource.swift */,
+ ACC6EF501AA1A870002B76A9 /* DefaultAsyncMessagesCollectionViewDataSource.swift */,
+ ACC6EF511AA1A870002B76A9 /* MessageBubbleImageProvider.swift */,
+ ACC6EF521AA1A870002B76A9 /* MessageCellNodeMetadataFactory.swift */,
+ ACC6EF531AA1A870002B76A9 /* MessageTimestampFormatter.swift */,
+ 38A1D757204C3AD700C88828 /* DefaultAsyncMessagesCollectionViewDelegate.swift */,
+ );
+ path = Controllers;
+ sourceTree = "";
+ };
+ ACC6EF541AA1A870002B76A9 /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ ACC6EF551AA1A870002B76A9 /* MessageData.swift */,
+ );
+ path = Models;
+ sourceTree = "";
+ };
+ ACC6EF561AA1A870002B76A9 /* Views */ = {
+ isa = PBXGroup;
+ children = (
+ ACC6EF581AA1A870002B76A9 /* MessageCellNode.swift */,
+ ACCC86861AAB35CB00DB37B7 /* MessageBubbleNodeFactory.swift */,
+ ACC6EF5A1AA1A870002B76A9 /* MessageNetworkImageBubbleNode.swift */,
+ ACC6EF5B1AA1A870002B76A9 /* MessageTextBubbleNode.swift */,
+ ACC6EF5C1AA1A870002B76A9 /* UIImageExtensions.swift */,
+ );
+ path = Views;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ AC8B65CC1A9373DA00131D84 /* Example */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = AC8B65EC1A9373DA00131D84 /* Build configuration list for PBXNativeTarget "Example" */;
+ buildPhases = (
+ 67D68737ADC5DFB55D064BB3 /* [CP] Check Pods Manifest.lock */,
+ AC8B65C91A9373DA00131D84 /* Sources */,
+ AC8B65CA1A9373DA00131D84 /* Frameworks */,
+ AC8B65CB1A9373DA00131D84 /* Resources */,
+ 8A65FC5D0532763D2834849D /* [CP] Copy Pods Resources */,
+ 3300D7AB49227487C436845B /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Example;
+ productName = Example;
+ productReference = AC8B65CD1A9373DA00131D84 /* Example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ AC8B65C51A9373DA00131D84 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftMigration = 0700;
+ LastSwiftUpdateCheck = 0700;
+ LastUpgradeCheck = 0920;
+ ORGANIZATIONNAME = "Huy Nguyen";
+ TargetAttributes = {
+ AC8B65CC1A9373DA00131D84 = {
+ CreatedOnToolsVersion = 6.1.1;
+ DevelopmentTeam = H4EJPVDUSS;
+ LastSwiftMigration = 0920;
+ };
+ };
+ };
+ buildConfigurationList = AC8B65C81A9373DA00131D84 /* Build configuration list for PBXProject "AsyncMessagesViewController" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = AC8B65C41A9373DA00131D84;
+ productRefGroup = AC8B65CE1A9373DA00131D84 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ AC8B65CC1A9373DA00131D84 /* Example */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ AC8B65CB1A9373DA00131D84 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ ACC6EF5D1AA1A870002B76A9 /* AsyncMessagesViewController.xcassets in Resources */,
+ AC8B65DD1A9373DA00131D84 /* LaunchScreen.xib in Resources */,
+ AC8B65DA1A9373DA00131D84 /* Images.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3300D7AB49227487C436845B /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh",
+ "${BUILT_PRODUCTS_DIR}/LoremIpsum/LoremIpsum.framework",
+ "${BUILT_PRODUCTS_DIR}/PINCache/PINCache.framework",
+ "${BUILT_PRODUCTS_DIR}/PINOperation/PINOperation.framework",
+ "${BUILT_PRODUCTS_DIR}/PINRemoteImage/PINRemoteImage.framework",
+ "${BUILT_PRODUCTS_DIR}/SlackTextViewController/SlackTextViewController.framework",
+ "${BUILT_PRODUCTS_DIR}/Texture/AsyncDisplayKit.framework",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LoremIpsum.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINCache.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINOperation.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINRemoteImage.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SlackTextViewController.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AsyncDisplayKit.framework",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 67D68737ADC5DFB55D064BB3 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 8A65FC5D0532763D2834849D /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ AC8B65C91A9373DA00131D84 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ ACC6EF641AA1A870002B76A9 /* MessageData.swift in Sources */,
+ AC8B65D51A9373DA00131D84 /* ViewController.swift in Sources */,
+ ACC6EF691AA1A870002B76A9 /* MessageTextBubbleNode.swift in Sources */,
+ AC90D5FF1AA1A68F0042C0D4 /* User.swift in Sources */,
+ ACC6EF601AA1A870002B76A9 /* DefaultAsyncMessagesCollectionViewDataSource.swift in Sources */,
+ ACC6EF631AA1A870002B76A9 /* MessageTimestampFormatter.swift in Sources */,
+ ACC6EF5E1AA1A870002B76A9 /* AsyncMessagesCollectionViewDataSource.swift in Sources */,
+ ACC6EF611AA1A870002B76A9 /* MessageBubbleImageProvider.swift in Sources */,
+ ACC6EF661AA1A870002B76A9 /* MessageCellNode.swift in Sources */,
+ ACC6EF5F1AA1A870002B76A9 /* AsyncMessagesViewController.swift in Sources */,
+ ACC6EF681AA1A870002B76A9 /* MessageNetworkImageBubbleNode.swift in Sources */,
+ AC8B65D31A9373DA00131D84 /* AppDelegate.swift in Sources */,
+ 38A1D758204C3AD700C88828 /* DefaultAsyncMessagesCollectionViewDelegate.swift in Sources */,
+ AC90D5FE1AA1A68F0042C0D4 /* Message.swift in Sources */,
+ ACCC86871AAB35CB00DB37B7 /* MessageBubbleNodeFactory.swift in Sources */,
+ ACC6EF621AA1A870002B76A9 /* MessageCellNodeMetadataFactory.swift in Sources */,
+ ACC6EF6A1AA1A870002B76A9 /* UIImageExtensions.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ AC8B65DB1A9373DA00131D84 /* LaunchScreen.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ AC8B65DC1A9373DA00131D84 /* Base */,
+ );
+ name = LaunchScreen.xib;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ AC8B65EA1A9373DA00131D84 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ AC8B65EB1A9373DA00131D84 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.1;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ AC8B65ED1A9373DA00131D84 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = E9324B7353C16801DF96CCCD /* Pods-Example.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ DEVELOPMENT_TEAM = H4EJPVDUSS;
+ ENABLE_BITCODE = YES;
+ INFOPLIST_FILE = Example/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "me.huytnguyen.AsyncMessagesViewController.$(PRODUCT_NAME:rfc1034identifier)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ AC8B65EE1A9373DA00131D84 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 356CBFABC1F3EA6E78E6884C /* Pods-Example.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ DEVELOPMENT_TEAM = H4EJPVDUSS;
+ ENABLE_BITCODE = YES;
+ INFOPLIST_FILE = Example/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "me.huytnguyen.AsyncMessagesViewController.$(PRODUCT_NAME:rfc1034identifier)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "";
+ SWIFT_SWIFT3_OBJC_INFERENCE = Default;
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ AC8B65C81A9373DA00131D84 /* Build configuration list for PBXProject "AsyncMessagesViewController" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AC8B65EA1A9373DA00131D84 /* Debug */,
+ AC8B65EB1A9373DA00131D84 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ AC8B65EC1A9373DA00131D84 /* Build configuration list for PBXNativeTarget "Example" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ AC8B65ED1A9373DA00131D84 /* Debug */,
+ AC8B65EE1A9373DA00131D84 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = AC8B65C51A9373DA00131D84 /* Project object */;
+}
diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift
index 130af39..7ec3c81 100644
--- a/Example/AppDelegate.swift
+++ b/Example/AppDelegate.swift
@@ -15,7 +15,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
- window!.rootViewController = UINavigationController(rootViewController: ViewController())
+ window!.rootViewController = UINavigationController(rootViewController: ViewController()!)
window!.makeKeyAndVisible()
return true
diff --git a/Example/Base.lproj/LaunchScreen.xib b/Example/Base.lproj/LaunchScreen.xib
index 4c3740d..dbdb9d2 100644
--- a/Example/Base.lproj/LaunchScreen.xib
+++ b/Example/Base.lproj/LaunchScreen.xib
@@ -1,8 +1,13 @@
-
-
+
+
+
+
+
-
+
+
+
@@ -24,7 +29,7 @@
-
+
diff --git a/Example/Example-Bridging-Header.h b/Example/Example-Bridging-Header.h
deleted file mode 100644
index f23aee1..0000000
--- a/Example/Example-Bridging-Header.h
+++ /dev/null
@@ -1,7 +0,0 @@
-//
-// Use this file to import your target's public headers that you would like to expose to Swift.
-//
-#import
-#import
-#import "SLKTextViewController.h"
-#import "LoremIpsum.h"
diff --git a/Example/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/Images.xcassets/AppIcon.appiconset/Contents.json
index 118c98f..19882d5 100644
--- a/Example/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/Example/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -1,5 +1,15 @@
{
"images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
{
"idiom" : "iphone",
"size" : "29x29",
@@ -29,6 +39,11 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
}
],
"info" : {
diff --git a/Example/ViewController.swift b/Example/ViewController.swift
index 4cb38cf..d820215 100644
--- a/Example/ViewController.swift
+++ b/Example/ViewController.swift
@@ -7,15 +7,17 @@
//
import UIKit
+import AsyncDisplayKit
+import LoremIpsum
-class ViewController: AsyncMessagesViewController, ASCollectionDelegate {
+class ViewController: AsyncMessagesViewController {
private let users: [User]
private var currentUser: User? {
return users.filter({$0.ID == self.dataSource.currentUserID()}).first
}
- init() {
+ init?() {
// Assume the default image size is used for message cell nodes
let avatarImageSize = CGSize(width: kAMMessageCellNodeAvatarImageSize, height: kAMMessageCellNodeAvatarImageSize)
users = (0..<5).map() {
@@ -24,14 +26,13 @@ class ViewController: AsyncMessagesViewController, ASCollectionDelegate {
}
let dataSource = DefaultAsyncMessagesCollectionViewDataSource(currentUserID: users[0].ID)
- super.init(dataSource: dataSource)
-
- collectionView.asyncDelegate = self
+ let delegate = DefaultAsyncMessagesCollectionViewDelegate()
+ super.init(dataSource: dataSource, delegate: delegate)
}
deinit {
// Tell ASCollectionView that this object is being deallocated (Issue #4)
- collectionView.asyncDelegate = nil
+ asyncCollectionNode.delegate = nil
}
required init(coder aDecoder: NSCoder) {
@@ -55,7 +56,7 @@ class ViewController: AsyncMessagesViewController, ASCollectionDelegate {
content: textView.text,
date: Date(),
sender: user)
- dataSource.collectionView(collectionView: collectionView, insertMessages: [message]) {completed in
+ dataSource.collectionNode(collectionNode: asyncCollectionNode, insertMessages: [message]) {completed in
self.scrollCollectionViewToBottom()
}
}
@@ -86,14 +87,13 @@ class ViewController: AsyncMessagesViewController, ASCollectionDelegate {
sender: sender)
messages.append(message)
}
- dataSource.collectionView(collectionView: collectionView, insertMessages: messages, completion: nil)
+ dataSource.collectionNode(collectionNode: asyncCollectionNode, insertMessages: messages, completion: nil)
}
- func changeCurrentUser() {
+ @objc func changeCurrentUser() {
let otherUsers = users.filter({$0.ID != self.dataSource.currentUserID()})
let newUser = otherUsers[Int(arc4random_uniform(UInt32(otherUsers.count)))]
- dataSource.collectionView(collectionView: collectionView, updateCurrentUserID: newUser.ID)
+ dataSource.collectionNode(collectionNode: asyncCollectionNode, updateCurrentUserID: newUser.ID)
}
-
}
diff --git a/Podfile b/Podfile
index 0e2f230..4a61de0 100644
--- a/Podfile
+++ b/Podfile
@@ -1,10 +1,12 @@
source 'https://github.com/CocoaPods/Specs.git'
-platform :ios, '8.0'
+platform :ios, '9.0'
+target 'Example' do
+ use_frameworks!
-pod 'AsyncDisplayKit', '1.9.90'
-pod 'SlackTextViewController', '1.9.5'
-
-# Used by example target
-pod 'LoremIpsum', :git => 'https://github.com/nguyenhuy/LoremIpsum.git', :branch => 'master'
+ pod 'Texture', '2.6'
+ pod 'SlackTextViewController', '1.9.6'
+ # Used by example target
+ pod 'LoremIpsum', :git => 'https://github.com/nguyenhuy/LoremIpsum.git', :branch => 'master'
+end
diff --git a/Source/Controllers/AsyncMessagesCollectionViewDataSource.swift b/Source/Controllers/AsyncMessagesCollectionViewDataSource.swift
index e7b90cb..cd96f90 100644
--- a/Source/Controllers/AsyncMessagesCollectionViewDataSource.swift
+++ b/Source/Controllers/AsyncMessagesCollectionViewDataSource.swift
@@ -7,18 +7,19 @@
//
import Foundation
+import AsyncDisplayKit
//TODO revise method name to adhere to Swift 3 convention
protocol AsyncMessagesCollectionViewDataSource: ASCollectionDataSource {
func currentUserID() -> String?
- func collectionView(collectionView: ASCollectionView, updateCurrentUserID newUserID: String?)
+ func collectionNode(collectionNode: ASCollectionNode, updateCurrentUserID newUserID: String?)
- func collectionView(collectionView: ASCollectionView, messageForItemAtIndexPath indexPath: IndexPath) -> MessageData
+ func collectionNode(collectionNode: ASCollectionNode, messageForItemAtIndexPath indexPath: IndexPath) -> MessageData
- func collectionView(collectionView: ASCollectionView, insertMessages newMessages: [MessageData], completion: ((Bool) -> ())?)
+ func collectionNode(collectionNode: ASCollectionNode, insertMessages newMessages: [MessageData], completion: ((Bool) -> ())?)
- func collectionView(collectionView: ASCollectionView, deleteMessagesAtIndexPaths indexPaths: [IndexPath], completion: ((Bool) -> ())?)
+ func collectionNode(collectionNode: ASCollectionNode, deleteMessagesAtIndexPaths indexPaths: [IndexPath], completion: ((Bool) -> ())?)
}
diff --git a/Source/Controllers/AsyncMessagesViewController.swift b/Source/Controllers/AsyncMessagesViewController.swift
index 1b9dfd7..d3c8d72 100644
--- a/Source/Controllers/AsyncMessagesViewController.swift
+++ b/Source/Controllers/AsyncMessagesViewController.swift
@@ -7,24 +7,31 @@
//
import Foundation
+import AsyncDisplayKit
+import SlackTextViewController
class AsyncMessagesViewController: SLKTextViewController {
let dataSource: AsyncMessagesCollectionViewDataSource
+ let delegate: ASCollectionDelegate
+ let asyncCollectionNode: ASCollectionNode
override var collectionView: ASCollectionView {
return scrollView as! ASCollectionView
}
- init(dataSource: AsyncMessagesCollectionViewDataSource) {
+ init?(dataSource: AsyncMessagesCollectionViewDataSource, delegate: ASCollectionDelegate) {
self.dataSource = dataSource
-
+ self.delegate = delegate
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = UICollectionViewScrollDirection.vertical
- let asyncCollectionView = ASCollectionView(frame: CGRect.zero, collectionViewLayout: layout)
+
+ asyncCollectionNode = ASCollectionNode(collectionViewLayout: layout)
+ let asyncCollectionView = asyncCollectionNode.view
+
asyncCollectionView.backgroundColor = UIColor.white
asyncCollectionView.scrollsToTop = true
- asyncCollectionView.asyncDataSource = dataSource
-
+ asyncCollectionNode.dataSource = dataSource
+ asyncCollectionNode.delegate = delegate
super.init(scrollView: asyncCollectionView)
isInverted = false
@@ -36,17 +43,17 @@ class AsyncMessagesViewController: SLKTextViewController {
override func viewWillLayoutSubviews() {
let insets = UIEdgeInsetsMake(topLayoutGuide.length, 0, 5, 0)
- collectionView.contentInset = insets
+ asyncCollectionNode.contentInset = insets
collectionView.scrollIndicatorInsets = insets
super.viewWillLayoutSubviews()
}
func scrollCollectionViewToBottom() {
- let numberOfItems = dataSource.collectionView(collectionView, numberOfItemsInSection: 0)
+ let numberOfItems = dataSource.collectionNode!(asyncCollectionNode, numberOfItemsInSection: 0)
if numberOfItems > 0 {
let lastItemIndexPath = IndexPath(item: numberOfItems - 1, section: 0)
- collectionView.scrollToItem(at: lastItemIndexPath, at: .bottom, animated: true)
+ asyncCollectionNode.scrollToItem(at: lastItemIndexPath, at: .bottom, animated: true)
}
}
diff --git a/Source/Controllers/DefaultAsyncMessagesCollectionViewDataSource.swift b/Source/Controllers/DefaultAsyncMessagesCollectionViewDataSource.swift
index b02ce0b..5924011 100644
--- a/Source/Controllers/DefaultAsyncMessagesCollectionViewDataSource.swift
+++ b/Source/Controllers/DefaultAsyncMessagesCollectionViewDataSource.swift
@@ -7,6 +7,7 @@
//
import Foundation
+import AsyncDisplayKit
class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesCollectionViewDataSource {
@@ -36,15 +37,14 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
nodeMetadatas = []
}
- //MARK: ASCollectionViewDataSource methods
- func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+ //MARK: ASCollectionDataSource methods
+ func collectionNode(_ collectionNode: ASCollectionNode, numberOfItemsInSection section: Int) -> Int {
assert(nodeMetadatas.count == messages.count, "Node metadata is required for each message.")
return messages.count
}
- //TODO Use node block
- func collectionView(_ collectionView: ASCollectionView, nodeForItemAt indexPath: IndexPath) -> ASCellNode {
- let message = self.collectionView(collectionView: collectionView, messageForItemAtIndexPath: indexPath)
+ func collectionNode(_ collectionNode: ASCollectionNode, nodeBlockForItemAt indexPath: IndexPath) -> ASCellNodeBlock {
+ let message = self.collectionNode(collectionNode: collectionNode, messageForItemAtIndexPath: indexPath)
let metadata = nodeMetadatas[indexPath.item]
let isOutgoing = metadata.isOutgoing
@@ -59,18 +59,20 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
let bubbleImage = bubbleImageProvider.bubbleImage(isOutgoing: isOutgoing, hasTail: metadata.showsTailForBubbleImage)
assert(bubbleNodeFactories.index(forKey: message.contentType()) != nil, "No bubble node factory for content type: \(message.contentType())")
let bubbleNode = bubbleNodeFactories[message.contentType()]!.build(message: message, isOutgoing: isOutgoing, bubbleImage: bubbleImage)
-
- let cellNode = MessageCellNode(
- isOutgoing: isOutgoing,
- topText: messageDate,
- contentTopText: senderDisplayName,
- bottomText: nil,
- senderAvatarURL: senderAvatarURL,
- bubbleNode: bubbleNode)
-
- return cellNode
+
+ let cellNodeBlock:() -> ASCellNode = {
+ let cellNode = MessageCellNode(
+ isOutgoing: isOutgoing,
+ topText: messageDate,
+ contentTopText: senderDisplayName,
+ bottomText: nil,
+ senderAvatarURL: senderAvatarURL,
+ bubbleNode: bubbleNode)
+ return cellNode
+ }
+ return cellNodeBlock
}
-
+
func collectionView(_ collectionView: ASCollectionView, constrainedSizeForNodeAt indexPath: IndexPath) -> ASSizeRange {
let width = collectionView.bounds.width;
// Assume horizontal scroll directions
@@ -82,7 +84,7 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
return _currentUserID
}
- func collectionView(collectionView: ASCollectionView, updateCurrentUserID newUserID: String?) {
+ func collectionNode(collectionNode: ASCollectionNode, updateCurrentUserID newUserID: String?) {
if newUserID == _currentUserID {
return
}
@@ -94,15 +96,14 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
nodeMetadatas = updatedMetadatas
let reloadIndicies = Array.computeDiff(lhs: outdatedMetadatas, rhs: updatedMetadatas)
- collectionView.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
+ collectionNode.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
}
- func collectionView(collectionView: ASCollectionView, messageForItemAtIndexPath indexPath: IndexPath) -> MessageData {
+ func collectionNode(collectionNode: ASCollectionNode, messageForItemAtIndexPath indexPath: IndexPath) -> MessageData {
return messages[indexPath.item]
}
- func collectionView(collectionView: ASCollectionView, insertMessages newMessages: [MessageData], completion: ((Bool) -> ())?) {
-
+ func collectionNode(collectionNode: ASCollectionNode, insertMessages newMessages: [MessageData], completion: ((Bool) -> ())?) {
if newMessages.isEmpty {
return
}
@@ -126,18 +127,17 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
}
let reloadIndicies = Array.computeDiff(lhs: outdatedNodeMetadatas, rhs: updatedNodeMetadatas)
- collectionView.performBatchUpdates(
+ collectionNode.performBatchUpdates(
{
- collectionView.insertItems(at: IndexPath.createIndexPaths(section: 0, items: insertedIndices))
+ collectionNode.insertItems(at: IndexPath.createIndexPaths(section: 0, items: insertedIndices))
if !reloadIndicies.isEmpty {
- collectionView.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
+ collectionNode.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
}
- },
+ },
completion: completion)
}
-
- func collectionView(collectionView: ASCollectionView, deleteMessagesAtIndexPaths indexPaths: [IndexPath], completion: ((Bool) -> ())?) {
+ func collectionNode(collectionNode: ASCollectionNode, deleteMessagesAtIndexPaths indexPaths: [IndexPath], completion: ((Bool) -> ())?) {
if indexPaths.isEmpty {
return
}
@@ -158,13 +158,13 @@ class DefaultAsyncMessagesCollectionViewDataSource: NSObject, AsyncMessagesColle
let reloadIndicies = Array.computeDiff(lhs: outdatedNodesMetadata, rhs: updatedNodeMetadatas)
- collectionView.performBatchUpdates(
+ collectionNode.performBatchUpdates(
{
- collectionView.deleteItems(at: sortedIndexPaths)
+ collectionNode.deleteItems(at: sortedIndexPaths)
if !reloadIndicies.isEmpty {
- collectionView.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
+ collectionNode.reloadItems(at: IndexPath.createIndexPaths(section: 0, items: reloadIndicies))
}
- },
+ },
completion: completion)
}
diff --git a/Source/Controllers/DefaultAsyncMessagesCollectionViewDelegate.swift b/Source/Controllers/DefaultAsyncMessagesCollectionViewDelegate.swift
new file mode 100644
index 0000000..bac3d1e
--- /dev/null
+++ b/Source/Controllers/DefaultAsyncMessagesCollectionViewDelegate.swift
@@ -0,0 +1,17 @@
+//
+// DefaultAsyncMessageDelegate.swift
+// Example
+//
+// Created by Tien Nguyen on 3/4/18.
+// Copyright © 2018 Huy Nguyen. All rights reserved.
+//
+
+import AsyncDisplayKit
+
+class DefaultAsyncMessagesCollectionViewDelegate: NSObject, ASCollectionDelegate {
+
+ func collectionNode(_ collectionNode: ASCollectionNode, constrainedSizeForItemAt indexPath: IndexPath) -> ASSizeRange {
+ let width = collectionNode.bounds.width;
+ return ASSizeRangeMake(CGSize(width: width, height: 0), CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
+ }
+}
diff --git a/Source/Controllers/MessageBubbleImageProvider.swift b/Source/Controllers/MessageBubbleImageProvider.swift
index feef5df..b9df6b4 100644
--- a/Source/Controllers/MessageBubbleImageProvider.swift
+++ b/Source/Controllers/MessageBubbleImageProvider.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2014 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
private struct MessageProperties: Hashable {
let isOutgoing: Bool
diff --git a/Source/Controllers/MessageCellNodeMetadataFactory.swift b/Source/Controllers/MessageCellNodeMetadataFactory.swift
index 381385f..2540aee 100644
--- a/Source/Controllers/MessageCellNodeMetadataFactory.swift
+++ b/Source/Controllers/MessageCellNodeMetadataFactory.swift
@@ -6,8 +6,6 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
-
struct MessageCellNodeMetadata: Hashable {
let isOutgoing: Bool
let showsSenderName: Bool
diff --git a/Source/Controllers/MessageTimestampFormatter.swift b/Source/Controllers/MessageTimestampFormatter.swift
index 78fe92c..12826e7 100644
--- a/Source/Controllers/MessageTimestampFormatter.swift
+++ b/Source/Controllers/MessageTimestampFormatter.swift
@@ -6,13 +6,13 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
class MessageTimestampFormatter {
private let dateFormatter: DateFormatter
- private let dateTextAttributes: [String: AnyObject]
- private let timeTextAttributes: [String: AnyObject]
+ private let dateTextAttributes: [NSAttributedStringKey: AnyObject]
+ private let timeTextAttributes: [NSAttributedStringKey: AnyObject]
init() {
dateFormatter = DateFormatter()
@@ -22,13 +22,13 @@ class MessageTimestampFormatter {
let color = UIColor.lightGray
dateTextAttributes = [
- NSFontAttributeName: UIFont.boldSystemFont(ofSize: 12),
- NSForegroundColorAttributeName: color
+ NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 12),
+ NSAttributedStringKey.foregroundColor: color
]
timeTextAttributes = [
- NSFontAttributeName: UIFont.systemFont(ofSize: 12),
- NSForegroundColorAttributeName: color
+ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 12),
+ NSAttributedStringKey.foregroundColor: color
]
}
diff --git a/Source/Views/MessageBubbleNodeFactory.swift b/Source/Views/MessageBubbleNodeFactory.swift
index 352be76..adbc04f 100644
--- a/Source/Views/MessageBubbleNodeFactory.swift
+++ b/Source/Views/MessageBubbleNodeFactory.swift
@@ -6,7 +6,8 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
+import AsyncDisplayKit
protocol MessageBubbleNodeFactory {
diff --git a/Source/Views/MessageCellNode.swift b/Source/Views/MessageCellNode.swift
index aa4cb5d..3045c71 100644
--- a/Source/Views/MessageCellNode.swift
+++ b/Source/Views/MessageCellNode.swift
@@ -6,16 +6,17 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
+import AsyncDisplayKit
let kAMMessageCellNodeAvatarImageSize: CGFloat = 34
-let kAMMessageCellNodeTopTextAttributes = [NSForegroundColorAttributeName: UIColor.lightGray,
- NSFontAttributeName: UIFont.boldSystemFont(ofSize: 12)]
-let kAMMessageCellNodeContentTopTextAttributes = [NSForegroundColorAttributeName: UIColor.lightGray,
- NSFontAttributeName: UIFont.systemFont(ofSize: 12)]
-let kAMMessageCellNodeBottomTextAttributes = [NSForegroundColorAttributeName: UIColor.lightGray,
- NSFontAttributeName: UIFont.systemFont(ofSize: 11)]
+let kAMMessageCellNodeTopTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.lightGray,
+ NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 12)]
+let kAMMessageCellNodeContentTopTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.lightGray,
+ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 12)]
+let kAMMessageCellNodeBottomTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.lightGray,
+ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 11)]
class MessageCellNode: ASCellNode {
@@ -32,26 +33,26 @@ class MessageCellNode: ASCellNode {
topTextNode = topText != nil ? ASTextNode() : nil
topTextNode?.isLayerBacked = true
- topTextNode?.attributedString = topText
- topTextNode?.alignSelf = .center
+ topTextNode?.attributedText = topText
+ topTextNode?.style.alignSelf = .center
contentTopTextNode = contentTopText != nil ? ASTextNode() : nil
contentTopTextNode?.isLayerBacked = true
- contentTopTextNode?.attributedString = contentTopText
+ contentTopTextNode?.attributedText = contentTopText
avatarImageSize = senderAvatarImageSize
avatarImageNode = avatarImageSize > 0 ? ASNetworkImageNode() : nil
- avatarImageNode?.preferredFrameSize = CGSize(width: avatarImageSize, height: avatarImageSize)
+ avatarImageNode?.style.preferredSize = CGSize(width: avatarImageSize, height: avatarImageSize)
avatarImageNode?.backgroundColor = UIColor.clear
avatarImageNode?.imageModificationBlock = ASImageNodeRoundBorderModificationBlock(0, nil)
avatarImageNode?.url = senderAvatarURL
self.bubbleNode = bubbleNode
- self.bubbleNode.flexShrink = true
+ self.bubbleNode.style.flexShrink = 1
bottomTextNode = bottomText != nil ? ASTextNode() : nil
bottomTextNode?.isLayerBacked = true
- bottomTextNode?.attributedString = bottomText
+ bottomTextNode?.attributedText = bottomText
super.init()
@@ -65,7 +66,7 @@ class MessageCellNode: ASCellNode {
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
- let unfilteredChildren: [ASLayoutable?] = [
+ let unfilteredChildren: [ASLayoutElement?] = [
topTextNode,
(contentTopTextNode != nil)
? ASInsetLayoutSpec(insets: UIEdgeInsetsMake(0, 22 + avatarImageSize, 0, 0), child: contentTopTextNode!)
diff --git a/Source/Views/MessageNetworkImageBubbleNode.swift b/Source/Views/MessageNetworkImageBubbleNode.swift
index bb38cc4..cc63e8b 100644
--- a/Source/Views/MessageNetworkImageBubbleNode.swift
+++ b/Source/Views/MessageNetworkImageBubbleNode.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import AsyncDisplayKit
class MessageNetworkImageBubbleNodeFactory: MessageBubbleNodeFactory {
diff --git a/Source/Views/MessageTextBubbleNode.swift b/Source/Views/MessageTextBubbleNode.swift
index 29b73d8..6b5c24a 100644
--- a/Source/Views/MessageTextBubbleNode.swift
+++ b/Source/Views/MessageTextBubbleNode.swift
@@ -6,12 +6,13 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
+import AsyncDisplayKit
-private let kAMMessageTextBubbleNodeIncomingTextAttributes = [NSForegroundColorAttributeName: UIColor.black,
- NSFontAttributeName: UIFont.systemFont(ofSize: 14)]
-private let kAMMessageTextBubbleNodeOutgoingTextAttributes = [NSForegroundColorAttributeName: UIColor.white,
- NSFontAttributeName: UIFont.systemFont(ofSize: 14)]
+private let kAMMessageTextBubbleNodeIncomingTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black,
+ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)]
+private let kAMMessageTextBubbleNodeOutgoingTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white,
+ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)]
class MessageTextBubbleNodeFactory: MessageBubbleNodeFactory {
@@ -53,7 +54,7 @@ class MessageTextBubbleNode: ASDisplayNode {
bubbleImageNode.image = bubbleImage
textNode = MessageTextNode()
- textNode.attributedString = text
+ textNode.attributedText = text
super.init()
diff --git a/Source/Views/UIImageExtensions.swift b/Source/Views/UIImageExtensions.swift
index 4d99f39..8f590cb 100644
--- a/Source/Views/UIImageExtensions.swift
+++ b/Source/Views/UIImageExtensions.swift
@@ -6,7 +6,7 @@
// Copyright (c) 2015 Huy Nguyen. All rights reserved.
//
-import Foundation
+import UIKit
enum ImageMaskingError: Error {
case insufficientParams