usergrid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From snoopd...@apache.org
Subject [41/89] [partial] usergrid git commit: Initial commit of the Swift SDK.
Date Thu, 18 Feb 2016 15:52:49 GMT
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Pods/UsergridSDK/sdks/swift/Source/UsergridUser.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Pods/UsergridSDK/sdks/swift/Source/UsergridUser.swift b/sdks/swift/Samples/ActivityFeed/Pods/UsergridSDK/sdks/swift/Source/UsergridUser.swift
new file mode 100644
index 0000000..b1eedcc
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Pods/UsergridSDK/sdks/swift/Source/UsergridUser.swift
@@ -0,0 +1,441 @@
+//
+//  User.swift
+//  UsergridSDK
+//
+//  Created by Robert Walsh on 7/21/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/// The completion block used for checking email and/or username availablity for new `UsergridUser` objects.
+public typealias UsergridUserAvailabilityCompletion = (error: UsergridResponseError?, available:Bool) -> Void
+
+/// The completion block used for changing the password of `UsergridUser` objects.
+public typealias UsergridUserResetPasswordCompletion = (error: UsergridResponseError?, didSucceed:Bool) -> Void
+
+/**
+`UsergridUser` is a special subclass of `UsergridEntity` that supports functions and properties unique to users.
+*/
+public class UsergridUser : UsergridEntity {
+
+    static let USER_ENTITY_TYPE = "user"
+
+    // MARK: - Instance Properties -
+
+    /// The `UsergridUserAuth` object if this user was authenticated.
+    public var auth: UsergridUserAuth?
+
+    /** 
+    Property helper method for the `UsergridUser` objects `UsergridUserProperties.Name`.
+    
+    Unlike `UsergridEntity` objects, `UsergridUser`'s can change their name property which is why we provide a getter here.
+    */
+    override public var name: String? {
+        set(name) { self[UsergridUserProperties.Name.stringValue] = name }
+        get{ return super.name }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Username`.
+    public var username: String? {
+        set(username) { self[UsergridUserProperties.Username.stringValue] = username }
+        get { return self.getUserSpecificProperty(.Username) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Password`.
+    public var password: String? {
+        set(password) { self[UsergridUserProperties.Password.stringValue] = password }
+        get { return self.getUserSpecificProperty(.Password) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Email`.
+    public var email: String? {
+        set(email) { self[UsergridUserProperties.Email.stringValue] = email }
+        get { return self.getUserSpecificProperty(.Email) as? String }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Age`.
+    public var age: NSNumber? {
+        set(age) { self[UsergridUserProperties.Age.stringValue] = age }
+        get { return self.getUserSpecificProperty(.Age) as? NSNumber }
+    }
+
+    /// Property helper method to get the username or email of the `UsergridUser`.
+    public var usernameOrEmail: String? { return self.username ?? self.email }
+
+    /** 
+    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Activated`.
+    
+    Indicates whether the user account has been activated or not.
+    */
+    public var activated: Bool {
+        set(activated) { self[UsergridUserProperties.Activated.stringValue] = activated }
+        get { return self.getUserSpecificProperty(.Activated) as? Bool ?? false }
+    }
+
+    /// Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Disabled`.
+    public var disabled: Bool {
+        set(disabled) { self[UsergridUserProperties.Disabled.stringValue] = disabled }
+        get { return self.getUserSpecificProperty(.Disabled) as? Bool ?? false }
+    }
+
+    /**
+    Property getter and setter helpers for the `UsergridUser` objects `UsergridUserProperties.Picture`.
+    
+    URL path to user’s profile picture. Defaults to Gravatar for email address.
+    */
+    public var picture: String? {
+        set(picture) { self[UsergridUserProperties.Picture.stringValue] = picture }
+        get { return self.getUserSpecificProperty(.Picture) as? String }
+    }
+
+    /// The UUID or username property value if found.
+    public var uuidOrUsername: String? { return self.uuid ?? self.username }
+
+    // MARK: - Initialization -
+
+    /**
+    Designated initializer for `UsergridUser` objects.
+
+    - parameter name: The name of the user.  Note this is different from the `username` property.
+
+    - returns: A new instance of `UsergridUser`.
+    */
+    public init(name:String? = nil) {
+        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:nil)
+    }
+
+    /**
+     The required public initializer for `UsergridEntity` subclasses.
+
+     - parameter type:         The type associated with the `UsergridEntity` object.
+     - parameter name:         The optional name associated with the `UsergridEntity` object.
+     - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
+
+     - returns: A new `UsergridUser` object.
+     */
+    required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
+        super.init(type: type, name: name, propertyDict: propertyDict)
+    }
+
+    /**
+    Designated initializer for `UsergridUser` objects.
+
+    - parameter name:         The name of the user.  Note this is different from the `username` property.
+    - parameter propertyDict: The optional property dictionary that the `UsergridEntity` object will start out with.
+
+    - returns: A new instance of `UsergridUser`.
+    */
+    public init(name:String,propertyDict:[String:AnyObject]? = nil) {
+        super.init(type: UsergridUser.USER_ENTITY_TYPE, name:name, propertyDict:propertyDict)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The name of the user.  Note this is different from the `username` property.
+     - parameter email:    The user's email.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String, email:String, password:String? = nil) {
+        self.init(name:name,email:email,username:nil,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter email:    The user's email.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(email:String, password:String? = nil) {
+        self.init(name:nil,email:email,username:nil,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The name of the user.  Note this is different from the `username` property.
+     - parameter username: The username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String, username:String, password:String? = nil) {
+        self.init(name:name,email:nil,username:username,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter username: The username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(username:String, password:String? = nil) {
+        self.init(name:nil,email:nil,username:username,password:password)
+    }
+
+    /**
+     Convenience initializer for `UsergridUser` objects.
+
+     - parameter name:     The optional name of the user.  Note this is different from the `username` property.
+     - parameter email:    The optional user's email.
+     - parameter username: The optional username of the user.
+     - parameter password: The optional user's password.
+
+     - returns: A new instance of `UsergridUser`.
+     */
+    public convenience init(name:String?, email:String?, username:String?, password:String? = nil) {
+        self.init(name:name)
+        self.email = email
+        self.username = username
+        self.password = password
+    }
+
+    // MARK: - NSCoding -
+
+    /**
+    NSCoding protocol initializer.
+
+    - parameter aDecoder: The decoder.
+
+    - returns: A decoded `UsergridUser` object.
+    */
+    required public init?(coder aDecoder: NSCoder) {
+        self.auth = aDecoder.decodeObjectForKey("auth") as? UsergridUserAuth
+        super.init(coder: aDecoder)
+    }
+
+    /**
+     NSCoding protocol encoder.
+
+     - parameter aCoder: The encoder.
+     */
+    public override func encodeWithCoder(aCoder: NSCoder) {
+        aCoder.encodeObject(self.auth, forKey: "auth")
+        super.encodeWithCoder(aCoder)
+    }
+
+    // MARK: - Class Methods -
+
+    /**
+    Checks the given email and/or username availablity for new `UsergridUser` objects using the shared instance of `UsergridClient`.
+
+    - parameter email:      The optional email address.
+    - parameter username:   The optional username.
+    - parameter completion: The completion block.
+    */
+    public static func checkAvailable(email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
+        self.checkAvailable(Usergrid.sharedInstance, email: email, username: username, completion: completion)
+    }
+
+    /**
+     Checks the given email and/or username availablity for new `UsergridUser` objects using with the given `UsergridClient`.
+
+     - parameter client:     The client to use for checking availability.
+     - parameter email:      The optional email address.
+     - parameter username:   The optional username.
+     - parameter completion: The completion block.
+     */
+    public static func checkAvailable(client: UsergridClient, email:String?, username:String?, completion:UsergridUserAvailabilityCompletion) {
+        let query = UsergridQuery(USER_ENTITY_TYPE)
+        if let emailValue = email {
+            query.eq(UsergridUserProperties.Email.stringValue, value: emailValue)
+        }
+        if let usernameValue = username {
+            query.or().eq(UsergridUserProperties.Username.stringValue, value: usernameValue)
+        }
+        client.GET(USER_ENTITY_TYPE, query: query) { (response) -> Void in
+            completion(error: response.error, available: response.entity == nil)
+        }
+    }
+
+    // MARK: - Instance Methods -
+
+    /**
+    Creates the user object in Usergrid if the user does not already exist with the shared instance of `UsergridClient`.
+
+    - parameter completion: The optional completion block.
+    */
+    public func create(completion: UsergridResponseCompletion? = nil) {
+        self.create(Usergrid.sharedInstance, completion: completion)
+    }
+
+    /**
+    Creates the user object in Usergrid if the user does not already exist with the given `UsergridClient`.
+
+    - parameter client:     The client to use for creation.
+    - parameter completion: The optional completion block.
+    */
+    public func create(client: UsergridClient, completion: UsergridResponseCompletion? = nil) {
+        client.POST(self,completion:completion)
+    }
+
+    /**
+    Authenticates the specified user using the provided username and password with the shared instance of `UsergridClient`.
+
+    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
+
+    - parameter username:   The username.
+    - parameter password:   The password.
+    - parameter completion: The optional completion block.
+    */
+    public func login(username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
+        self.login(Usergrid.sharedInstance, username: username, password: password, completion: completion)
+    }
+
+    /**
+    Authenticates the specified user using the provided username and password.
+
+    While functionally similar to `UsergridClient.authenticateUser(auth)`, this method does not automatically assign this user to `UsergridClient.currentUser`:
+
+    - parameter client:     The client to use for login.
+    - parameter username:   The username.
+    - parameter password:   The password.
+    - parameter completion: The optional completion block.
+    */
+    public func login(client: UsergridClient, username:String, password:String, completion: UsergridUserAuthCompletionBlock? = nil) {
+        let userAuth = UsergridUserAuth(username: username, password: password)
+        client.authenticateUser(userAuth,setAsCurrentUser:false) { [weak self] (auth, user, error) -> Void in
+            self?.auth = userAuth
+            completion?(auth: userAuth, user: user, error: error)
+        }
+    }
+
+     /**
+     Changes the User's current password with the shared instance of `UsergridClient`.
+
+     - parameter old:        The old password.
+     - parameter new:        The new password.
+     - parameter completion: The optional completion block.
+     */
+    public func resetPassword(old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
+        self.resetPassword(Usergrid.sharedInstance, old: old, new: new, completion: completion)
+    }
+
+    /**
+     Changes the User's current password with the shared instance of `UsergridClient`.
+
+     - parameter client:     The client to use for resetting the password.
+     - parameter old:        The old password.
+     - parameter new:        The new password.
+     - parameter completion: The optional completion block
+     */
+    public func resetPassword(client: UsergridClient, old:String, new:String, completion:UsergridUserResetPasswordCompletion? = nil) {
+        client.resetPassword(self, old: old, new: new, completion: completion)
+    }
+
+    /**
+     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property with the shared instance of `UsergridClient`.
+
+     - parameter completion: The optional completion block.
+     */
+    public func reauthenticate(completion: UsergridUserAuthCompletionBlock? = nil) {
+        self.reauthenticate(Usergrid.sharedInstance, completion: completion)
+    }
+
+    /**
+     Attmepts to reauthenticate using the user's `UsergridUserAuth` instance property.
+
+     - parameter client:     The client to use for reauthentication.
+     - parameter completion: The optional completion block.
+     */
+    public func reauthenticate(client: UsergridClient, completion: UsergridUserAuthCompletionBlock? = nil) {
+        if let userAuth = self.auth {
+            client.authenticateUser(userAuth, completion: completion)
+        } else {
+            let error = UsergridResponseError(errorName: "Invalid UsergridUserAuth.", errorDescription: "No UsergridUserAuth found on the UsergridUser.")
+            completion?(auth: nil, user: self, error: error)
+        }
+    }
+
+    /**
+    Invalidates the user token locally and remotely.
+
+    - parameter completion: The optional completion block.
+    */
+    public func logout(completion:UsergridResponseCompletion? = nil) {
+        self.logout(Usergrid.sharedInstance,completion:completion)
+    }
+
+    /**
+    Invalidates the user token locally and remotely.
+
+    - parameter client:     The client to use for logout.
+    - parameter completion: The optional completion block.
+    */
+    public func logout(client: UsergridClient, completion:UsergridResponseCompletion? = nil) {
+        if self === client.currentUser {
+            client.logoutCurrentUser(completion)
+        } else if let uuidOrUsername = self.uuidOrUsername, accessToken = self.auth?.accessToken {
+            client.logoutUser(uuidOrUsername, token: accessToken) { (response) in
+                self.auth = nil
+                completion?(response: response)
+            }
+        } else {
+            completion?(response: UsergridResponse(client:client, errorName:"Logout Failed.", errorDescription:"UUID or Access Token not found on UsergridUser object."))
+        }
+    }
+
+    private func getUserSpecificProperty(userProperty: UsergridUserProperties) -> AnyObject? {
+        var propertyValue: AnyObject? = super[userProperty.stringValue]
+        NSJSONReadingOptions.AllowFragments
+        switch userProperty {
+            case .Activated,.Disabled :
+                propertyValue = propertyValue?.boolValue
+            case .Age :
+                propertyValue = propertyValue?.integerValue
+            case .Name,.Username,.Password,.Email,.Picture :
+                break
+        }
+        return propertyValue
+    }
+
+    /**
+    Subscript for the `UsergridUser` class.
+
+    - Warning: When setting a properties value must be a valid JSON object.
+
+    - Example usage:
+    ```
+    let someName = usergridUser["name"]
+    
+    usergridUser["name"] = someName
+    ```
+    */
+    override public subscript(propertyName: String) -> AnyObject? {
+        get {
+            if let userProperty = UsergridUserProperties.fromString(propertyName) {
+                return self.getUserSpecificProperty(userProperty)
+            } else {
+                return super[propertyName]
+            }
+        }
+        set(propertyValue) {
+            super[propertyName] = propertyValue
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/ActivityEntity.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/ActivityEntity.swift b/sdks/swift/Samples/ActivityFeed/Source/ActivityEntity.swift
new file mode 100644
index 0000000..5ddcf12
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/ActivityEntity.swift
@@ -0,0 +1,60 @@
+//
+//  ActivityEntity.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 1/20/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import UsergridSDK
+
+public class ActivityEntity: UsergridEntity {
+
+    public var actor: [String:AnyObject]? { return self["actor"] as? [String:AnyObject] }
+
+    public var content: String? { return self["content"] as? String }
+
+    public var displayName: String? { return self.actor?["displayName"] as? String }
+
+    public var email: String? { return self.actor?["email"] as? String }
+
+    public var imageInfo: [String:AnyObject]? { return self.actor?["image"] as? [String:AnyObject] }
+
+    public var imageURL: String? { return self.imageInfo?["url"] as? String }
+
+    static func registerSubclass() {
+        UsergridEntity.mapCustomType("activity", toSubclass: ActivityEntity.self)
+    }
+
+    required public init(type: String, name: String?, propertyDict: [String : AnyObject]?) {
+        super.init(type: type, name: name, propertyDict: propertyDict)
+    }
+
+    required public init?(coder aDecoder: NSCoder) {
+        super.init(coder: aDecoder)
+    }
+
+    public override func encodeWithCoder(aCoder: NSCoder) {
+        super.encodeWithCoder(aCoder)
+    }
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/AppDelegate.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/AppDelegate.swift b/sdks/swift/Samples/ActivityFeed/Source/AppDelegate.swift
new file mode 100644
index 0000000..cca5c41
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/AppDelegate.swift
@@ -0,0 +1,65 @@
+//
+//  AppDelegate.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 11/19/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+
+import UIKit
+import UsergridSDK
+
+// TODO: Change the values to correspond to your organization, application, and notifier identifiers.
+
+@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    var window: UIWindow?
+
+    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
+
+        UINavigationBar.appearance().tintColor = UIColor.whiteColor()
+        application.registerUserNotificationSettings(UIUserNotificationSettings( forTypes: [.Alert, .Badge, .Sound], categories: nil))
+        application.registerForRemoteNotifications()
+
+        // Initialize the Usergrid shared instance.
+        UsergridManager.initializeSharedInstance()
+
+        // If there is a current user already logged in from the keychain we will skip the login page and go right to the chat screen
+
+        if Usergrid.currentUser != nil {
+            let rootViewController = self.window!.rootViewController as! UINavigationController
+            let loginViewController = rootViewController.viewControllers.first!
+            loginViewController.performSegueWithIdentifier("loginSuccessNonAnimatedSegue", sender: loginViewController)
+        }
+
+        return true
+    }
+
+    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
+        Usergrid.applyPushToken(deviceToken, notifierID: UsergridManager.NOTIFIER_ID, completion: nil)
+    }
+
+    func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
+        print("Application failed to register for remote notifications")
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..118c98f
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json
new file mode 100644
index 0000000..c19ad83
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "UsergridGuy.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png
new file mode 100644
index 0000000..b8a6844
Binary files /dev/null and b/sdks/swift/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png differ

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard b/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..78686cd
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard b/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..5f38e98
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard
@@ -0,0 +1,371 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="0Ca-En-eac">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
+        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+    </dependencies>
+    <scenes>
+        <!--Navigation Controller-->
+        <scene sceneID="b6o-SG-nHZ">
+            <objects>
+                <navigationController id="0Ca-En-eac" sceneMemberID="viewController">
+                    <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="kgZ-6Y-2Hs">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <color key="barTintColor" red="0.10196078431372549" green="0.41176470588235292" blue="0.56862745098039214" alpha="1" colorSpace="calibratedRGB"/>
+                        <textAttributes key="titleTextAttributes">
+                            <color key="textColor" red="0.97647058823529409" green="0.97647058823529409" blue="0.97647058823529409" alpha="1" colorSpace="calibratedRGB"/>
+                        </textAttributes>
+                    </navigationBar>
+                    <connections>
+                        <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="JkM-3e-aQt"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="KGr-0J-SBp" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-191" y="350"/>
+        </scene>
+        <!--Chit-Chat-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController title="Chit-Chat" id="BYZ-38-t0r" customClass="LoginViewController" customModule="SDKSample" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
+                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="64" width="414" height="672"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Password" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="AUv-4K-02z" userLabel="Password Text Field" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="221" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98039215686274506" green="0.98039215686274506" blue="0.98039215686274506" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="ttP-ff-vrA"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="done" secureTextEntry="YES"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="Pj4-c5-WOw" id="ndL-qj-xzY"/>
+                                </connections>
+                            </textField>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Username" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Z6O-sS-NMx" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="54" y="183" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549019602" green="0.98431372549019602" blue="0.98431372549019602" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="Dcr-HX-coh"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="next"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="AUv-4K-02z" id="NLo-pL-jk4"/>
+                                </connections>
+                            </textField>
+                            <button opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Pj4-c5-WOw" userLabel="Sign In ">
+                                <rect key="frame" x="54" y="287" width="305" height="45"/>
+                                <color key="backgroundColor" red="0.10196078431372549" green="0.41568627450980394" blue="0.58039215686274515" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="45" id="iPw-MQ-dMe"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                                <state key="normal" title="Sign In">
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                </state>
+                                <connections>
+                                    <action selector="loginButtonTouched:" destination="BYZ-38-t0r" eventType="touchUpInside" id="I2Z-mw-as5"/>
+                                </connections>
+                            </button>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JLH-ZA-uPM">
+                                <rect key="frame" x="128" y="360" width="157" height="30"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="157" id="Wo1-xd-zeb"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                                <state key="normal" title="Create Account">
+                                    <color key="titleColor" red="0.090196078431372548" green="0.33725490196078434" blue="0.50588235294117645" alpha="1" colorSpace="calibratedRGB"/>
+                                </state>
+                                <connections>
+                                    <segue destination="bnr-oZ-e0h" kind="show" identifier="signUpSegue" id="NXY-Nd-h56"/>
+                                </connections>
+                            </button>
+                            <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="UsergridGuy" translatesAutoresizingMaskIntoConstraints="NO" id="t6Y-SG-C6M">
+                                <rect key="frame" x="128" y="41" width="169" height="105"/>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" red="0.92941176470588238" green="0.94509803921568625" blue="0.94509803921568625" alpha="1" colorSpace="calibratedRGB"/>
+                        <constraints>
+                            <constraint firstItem="Pj4-c5-WOw" firstAttribute="top" secondItem="AUv-4K-02z" secondAttribute="bottom" constant="36" id="0Go-pE-u4p"/>
+                            <constraint firstItem="AUv-4K-02z" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" constant="35" id="2Xa-2C-BzP"/>
+                            <constraint firstAttribute="trailingMargin" secondItem="t6Y-SG-C6M" secondAttribute="trailing" constant="97" id="BQF-rx-fX4"/>
+                            <constraint firstItem="Z6O-sS-NMx" firstAttribute="trailing" secondItem="Pj4-c5-WOw" secondAttribute="trailing" id="CLi-7t-9Bm"/>
+                            <constraint firstItem="Z6O-sS-NMx" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" constant="34" id="H8h-Dc-gGd"/>
+                            <constraint firstItem="AUv-4K-02z" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="ML2-oF-zNc"/>
+                            <constraint firstItem="AUv-4K-02z" firstAttribute="top" secondItem="Z6O-sS-NMx" secondAttribute="bottom" constant="8" symbolic="YES" id="T1u-Ae-7qT"/>
+                            <constraint firstItem="t6Y-SG-C6M" firstAttribute="leading" secondItem="JLH-ZA-uPM" secondAttribute="leading" id="UkI-we-10P"/>
+                            <constraint firstItem="Pj4-c5-WOw" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" constant="287" id="WHX-b2-vXU"/>
+                            <constraint firstItem="JLH-ZA-uPM" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="adR-S0-Zw5"/>
+                            <constraint firstItem="Z6O-sS-NMx" firstAttribute="top" secondItem="t6Y-SG-C6M" secondAttribute="bottom" constant="37" id="cDN-ea-Z7L"/>
+                            <constraint firstItem="t6Y-SG-C6M" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="41" id="ciX-r9-UzJ"/>
+                            <constraint firstItem="JLH-ZA-uPM" firstAttribute="top" secondItem="Pj4-c5-WOw" secondAttribute="bottom" constant="28" id="h7B-Kf-fPS"/>
+                            <constraint firstItem="Z6O-sS-NMx" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="183" id="lIk-q4-Kkm"/>
+                            <constraint firstItem="Z6O-sS-NMx" firstAttribute="leading" secondItem="Pj4-c5-WOw" secondAttribute="leading" id="wi1-xU-x6C"/>
+                            <constraint firstItem="JLH-ZA-uPM" firstAttribute="centerX" secondItem="Pj4-c5-WOw" secondAttribute="centerX" id="xPz-Hj-Iv4"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" id="9X6-oC-0Ku">
+                        <barButtonItem key="backBarButtonItem" title="   " id="saf-1i-WZ7"/>
+                    </navigationItem>
+                    <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
+                    <connections>
+                        <outlet property="passwordTextField" destination="AUv-4K-02z" id="ck2-dw-K3H"/>
+                        <outlet property="usernameTextField" destination="Z6O-sS-NMx" id="jz7-0z-YRA"/>
+                        <segue destination="e2L-gy-keG" kind="show" identifier="loginSuccessSegue" id="yFG-ee-xdi"/>
+                        <segue destination="e2L-gy-keG" kind="show" identifier="loginSuccessNonAnimatedSegue" animates="NO" id="jbi-vT-etg"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="414" y="362"/>
+        </scene>
+        <!--Chat-->
+        <scene sceneID="xKw-pF-1VK">
+            <objects>
+                <viewController storyboardIdentifier="Chat" id="e2L-gy-keG" customClass="MessageViewController" customModule="SDKSample" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="l0J-tj-N8R"/>
+                        <viewControllerLayoutGuide type="bottom" id="aRQ-i9-bBv"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="gFB-Jy-DrN">
+                        <rect key="frame" x="0.0" y="64" width="414" height="672"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="0.90980392156862744" green="0.93333333333333335" blue="0.92941176470588238" alpha="1" colorSpace="calibratedRGB"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" title="Chat" id="A1Z-Fm-fb7" userLabel="Chat">
+                        <barButtonItem key="backBarButtonItem" title="   " id="lTa-eA-MlI"/>
+                        <barButtonItem key="rightBarButtonItem" title="Follow" id="oWz-oN-r0q">
+                            <connections>
+                                <segue destination="dZf-Pa-FEf" kind="show" id="4hi-xR-y7a"/>
+                            </connections>
+                        </barButtonItem>
+                    </navigationItem>
+                    <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="KDg-MX-rlV" userLabel="First Responder" sceneMemberID="firstResponder"/>
+                <exit id="Vtr-ga-m5m" userLabel="Exit" sceneMemberID="exit"/>
+            </objects>
+            <point key="canvasLocation" x="873" y="692"/>
+        </scene>
+        <!--Follow-->
+        <scene sceneID="L1J-vW-kjp">
+            <objects>
+                <viewController id="dZf-Pa-FEf" customClass="FollowViewController" customModule="SDKSample" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="bqC-DA-7jl"/>
+                        <viewControllerLayoutGuide type="bottom" id="WfX-kG-aQR"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="qAg-Dl-t9F">
+                        <rect key="frame" x="0.0" y="64" width="414" height="672"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <button opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dSM-Kh-jtM" userLabel="Sign In ">
+                                <rect key="frame" x="55" y="304" width="305" height="45"/>
+                                <color key="backgroundColor" red="0.090196078431372548" green="0.33333333333333331" blue="0.49411764705882355" alpha="1" colorSpace="calibratedRGB"/>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                                <state key="normal" title="Add Follower">
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                </state>
+                                <connections>
+                                    <action selector="addFollowerButtonTouched:" destination="dZf-Pa-FEf" eventType="touchUpInside" id="yuv-da-ArK"/>
+                                </connections>
+                            </button>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Username" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="30w-Hq-z3n" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="229" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549999996" green="0.98431372549999996" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="VgQ-oU-xSh"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="next"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="dSM-Kh-jtM" id="JKY-WD-0wK"/>
+                                </connections>
+                            </textField>
+                        </subviews>
+                        <color key="backgroundColor" red="0.90980392156862744" green="0.93333333333333335" blue="0.92941176470588238" alpha="1" colorSpace="calibratedRGB"/>
+                        <constraints>
+                            <constraint firstItem="30w-Hq-z3n" firstAttribute="leading" secondItem="qAg-Dl-t9F" secondAttribute="leadingMargin" constant="35" id="ETC-Hj-qu0"/>
+                            <constraint firstItem="dSM-Kh-jtM" firstAttribute="leading" secondItem="30w-Hq-z3n" secondAttribute="leading" id="MrI-EB-S4Q"/>
+                            <constraint firstItem="dSM-Kh-jtM" firstAttribute="centerX" secondItem="qAg-Dl-t9F" secondAttribute="centerX" id="XGA-b6-Kbm"/>
+                            <constraint firstItem="dSM-Kh-jtM" firstAttribute="top" secondItem="30w-Hq-z3n" secondAttribute="bottom" constant="45" id="hYz-y9-k2e"/>
+                            <constraint firstItem="30w-Hq-z3n" firstAttribute="trailing" secondItem="dSM-Kh-jtM" secondAttribute="trailing" id="jBo-UK-A49"/>
+                            <constraint firstItem="WfX-kG-aQR" firstAttribute="top" secondItem="dSM-Kh-jtM" secondAttribute="bottom" constant="323" id="l8c-Ap-E9b"/>
+                            <constraint firstItem="30w-Hq-z3n" firstAttribute="top" secondItem="bqC-DA-7jl" secondAttribute="bottom" constant="229" id="p7k-Gp-8pf"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Follow" id="j5X-9C-znz">
+                        <barButtonItem key="backBarButtonItem" id="HXY-KA-xWY"/>
+                    </navigationItem>
+                    <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
+                    <connections>
+                        <outlet property="usernameTextField" destination="30w-Hq-z3n" id="QcA-z0-XWe"/>
+                        <segue destination="Vtr-ga-m5m" kind="unwind" identifier="unwindToChatSegue" unwindAction="unwindToChat:" id="uwe-tT-3Yl"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="P87-dE-iQW" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1334" y="692"/>
+        </scene>
+        <!--Create Account-->
+        <scene sceneID="KTq-tk-yrN">
+            <objects>
+                <viewController title="Create Account" id="bnr-oZ-e0h" customClass="RegisterViewController" customModule="SDKSample" customModuleProvider="target" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="54e-JK-PBR"/>
+                        <viewControllerLayoutGuide type="bottom" id="JWP-YK-0Zj"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="8bt-vM-LeI">
+                        <rect key="frame" x="0.0" y="64" width="414" height="672"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Name" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="X55-Ni-6OO" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="112" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549999996" green="0.98431372549999996" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="e0c-yJ-CZz"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="next"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="T7U-9G-AS6" id="HUF-el-scZ"/>
+                                </connections>
+                            </textField>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Username" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="T7U-9G-AS6" userLabel="Username Text Field" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="150" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549999996" green="0.98431372549999996" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="AdR-w9-g8s"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="next"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="Fbi-gF-0jQ" id="sjv-Dm-5GL"/>
+                                </connections>
+                            </textField>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Email" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Fbi-gF-0jQ" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="188" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549999996" green="0.98431372549999996" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="BEM-zO-uYG"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" keyboardType="emailAddress" returnKeyType="next"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="3wi-7s-j5P" id="eE7-9Y-L0t"/>
+                                </connections>
+                            </textField>
+                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Password" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="3wi-7s-j5P" userLabel="Password Text Field" customClass="FormTextField" customModule="SDKSample" customModuleProvider="target">
+                                <rect key="frame" x="55" y="226" width="305" height="30"/>
+                                <color key="backgroundColor" red="0.98431372549999996" green="0.98431372549999996" blue="0.98431372549999996" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="30" id="N5y-wK-RFi"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <textInputTraits key="textInputTraits" returnKeyType="done" secureTextEntry="YES"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="inset">
+                                        <real key="value" value="10"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                                <connections>
+                                    <outlet property="nextResponderField" destination="1LM-SB-xON" id="igH-69-KP4"/>
+                                </connections>
+                            </textField>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1LM-SB-xON" userLabel="Create Account Button">
+                                <rect key="frame" x="129" y="311" width="157" height="30"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="157" id="FnB-G6-Riq"/>
+                                    <constraint firstAttribute="height" constant="30" id="q9P-Oj-aoj"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                                <state key="normal" title="Create Account">
+                                    <color key="titleColor" red="0.090196078431372548" green="0.33333333333333331" blue="0.49019607843137253" alpha="1" colorSpace="calibratedRGB"/>
+                                </state>
+                                <connections>
+                                    <action selector="registerButtonTouched:" destination="bnr-oZ-e0h" eventType="touchUpInside" id="GSH-40-K9q"/>
+                                </connections>
+                            </button>
+                        </subviews>
+                        <color key="backgroundColor" red="0.90980392156862744" green="0.93333333333333335" blue="0.92941176470588238" alpha="1" colorSpace="calibratedRGB"/>
+                        <constraints>
+                            <constraint firstItem="Fbi-gF-0jQ" firstAttribute="top" secondItem="T7U-9G-AS6" secondAttribute="bottom" constant="8" symbolic="YES" id="47R-E5-Snv"/>
+                            <constraint firstItem="X55-Ni-6OO" firstAttribute="leading" secondItem="8bt-vM-LeI" secondAttribute="leadingMargin" constant="35" id="4AX-MS-GG7"/>
+                            <constraint firstItem="3wi-7s-j5P" firstAttribute="centerX" secondItem="1LM-SB-xON" secondAttribute="centerX" id="6sW-Fh-Rab"/>
+                            <constraint firstItem="X55-Ni-6OO" firstAttribute="top" secondItem="54e-JK-PBR" secondAttribute="bottom" constant="112" id="8Po-i9-42g"/>
+                            <constraint firstItem="Fbi-gF-0jQ" firstAttribute="leading" secondItem="3wi-7s-j5P" secondAttribute="leading" id="Aun-rI-OR3"/>
+                            <constraint firstItem="T7U-9G-AS6" firstAttribute="leading" secondItem="X55-Ni-6OO" secondAttribute="leading" id="BdL-Nz-LD6"/>
+                            <constraint firstItem="Fbi-gF-0jQ" firstAttribute="trailing" secondItem="3wi-7s-j5P" secondAttribute="trailing" id="KdZ-Tm-Bwx"/>
+                            <constraint firstItem="T7U-9G-AS6" firstAttribute="trailing" secondItem="X55-Ni-6OO" secondAttribute="trailing" id="RYI-tz-VCv"/>
+                            <constraint firstItem="Fbi-gF-0jQ" firstAttribute="trailing" secondItem="T7U-9G-AS6" secondAttribute="trailing" id="fw6-6b-cmI"/>
+                            <constraint firstItem="3wi-7s-j5P" firstAttribute="top" secondItem="Fbi-gF-0jQ" secondAttribute="bottom" constant="8" symbolic="YES" id="geo-x8-ZFP"/>
+                            <constraint firstItem="Fbi-gF-0jQ" firstAttribute="leading" secondItem="T7U-9G-AS6" secondAttribute="leading" id="jQL-Ia-0fq"/>
+                            <constraint firstItem="1LM-SB-xON" firstAttribute="top" secondItem="3wi-7s-j5P" secondAttribute="bottom" constant="55" id="p5i-2x-Yya"/>
+                            <constraint firstItem="X55-Ni-6OO" firstAttribute="centerX" secondItem="8bt-vM-LeI" secondAttribute="centerX" id="qHj-O7-Oze"/>
+                            <constraint firstItem="T7U-9G-AS6" firstAttribute="top" secondItem="X55-Ni-6OO" secondAttribute="bottom" constant="8" symbolic="YES" id="wCb-xG-olD"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Create Account" id="fQg-sg-1cB"/>
+                    <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
+                    <connections>
+                        <outlet property="emailTextField" destination="Fbi-gF-0jQ" id="6Uc-Fs-euO"/>
+                        <outlet property="nameTextField" destination="X55-Ni-6OO" id="6dQ-5q-zzP"/>
+                        <outlet property="passwordTextField" destination="3wi-7s-j5P" id="978-dQ-Xd1"/>
+                        <outlet property="usernameTextField" destination="T7U-9G-AS6" id="K2o-PS-UxH"/>
+                        <segue destination="Zoo-Jg-Iad" kind="unwind" identifier="unwindSegue" unwindAction="unwind:" id="gdP-wh-1Zx"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="VBd-vg-SN9" userLabel="First Responder" sceneMemberID="firstResponder"/>
+                <exit id="Zoo-Jg-Iad" userLabel="Exit" sceneMemberID="exit"/>
+            </objects>
+            <point key="canvasLocation" x="873" y="-128"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="UsergridGuy" width="162" height="161"/>
+    </resources>
+    <inferredMetricsTieBreakers>
+        <segue reference="yFG-ee-xdi"/>
+    </inferredMetricsTieBreakers>
+</document>

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/FollowViewController.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/FollowViewController.swift b/sdks/swift/Samples/ActivityFeed/Source/FollowViewController.swift
new file mode 100644
index 0000000..1f33fb5
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/FollowViewController.swift
@@ -0,0 +1,49 @@
+//
+//  FollowViewController.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 1/21/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import UsergridSDK
+
+class FollowViewController : UIViewController {
+
+    @IBOutlet weak var usernameTextField: UITextField!
+
+    @IBAction func addFollowerButtonTouched(sender:AnyObject?) {
+        guard let username = usernameTextField.text where !username.isEmpty
+        else {
+            self.showAlert(title: "Follow failed.", message: "Please enter a valid username.")
+            return
+        }
+
+        UsergridManager.followUser(username) { (response) -> Void in
+            if response.ok {
+                self.performSegueWithIdentifier("unwindToChatSegue", sender: self)
+            } else {
+                self.showAlert(title: "Follow failed.", message: "No user with the username \"\(username)\" found.")
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/FormTextField.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/FormTextField.swift b/sdks/swift/Samples/ActivityFeed/Source/FormTextField.swift
new file mode 100644
index 0000000..9a79022
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/FormTextField.swift
@@ -0,0 +1,71 @@
+//
+//  FormTextField.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 1/21/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import UIKit
+
+@IBDesignable class FormTextField: UITextField {
+
+    @IBInspectable var inset: CGFloat = 0
+    @IBOutlet weak var nextResponderField: UIResponder?
+
+    required init?(coder aDecoder: NSCoder) {
+        super.init(coder: aDecoder)
+        setUp()
+    }
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setUp()
+    }
+
+    func setUp() {
+        addTarget(self, action: "actionKeyboardButtonTapped:", forControlEvents: .EditingDidEndOnExit)
+    }
+
+    func actionKeyboardButtonTapped(sender: UITextField) {
+        switch nextResponderField {
+        case let button as UIButton:
+            if button.enabled {
+                button.sendActionsForControlEvents(.TouchUpInside)
+            } else {
+                resignFirstResponder()
+            }
+        case .Some(let responder):
+            responder.becomeFirstResponder()
+        default:
+            resignFirstResponder()
+        }
+    }
+
+    override func textRectForBounds(bounds: CGRect) -> CGRect {
+        return CGRectInset(bounds, inset, 0)
+    }
+
+    override func editingRectForBounds(bounds: CGRect) -> CGRect {
+        return textRectForBounds(bounds)
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/Info.plist
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/Info.plist b/sdks/swift/Samples/ActivityFeed/Source/Info.plist
new file mode 100644
index 0000000..2ea3512
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/Info.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
+	</dict>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/LoginViewController.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/LoginViewController.swift b/sdks/swift/Samples/ActivityFeed/Source/LoginViewController.swift
new file mode 100644
index 0000000..76f8d8b
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/LoginViewController.swift
@@ -0,0 +1,76 @@
+//
+//  LoginViewController.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 1/21/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import UsergridSDK
+
+class LoginViewController: UIViewController {
+
+    @IBOutlet weak var usernameTextField: UITextField!
+    @IBOutlet weak var passwordTextField: UITextField!
+
+    override func viewWillAppear(animated: Bool) {
+        super.viewWillAppear(animated)
+        self.passwordTextField.text = nil
+    }
+
+    override func viewDidAppear(animated: Bool) {
+        Usergrid.logoutCurrentUser()
+        super.viewDidAppear(animated)
+    }
+
+    override func viewWillDisappear(animated: Bool) {
+        super.viewWillDisappear(animated)
+        self.view.endEditing(true)
+    }
+
+    @IBAction func loginButtonTouched(sender: AnyObject) {
+        guard let username = usernameTextField.text where !username.isEmpty,
+              let password = passwordTextField.text where !password.isEmpty
+        else {
+            self.showAlert(title: "Error Authenticating User", message: "Username and password must not be empty.")
+            return;
+        }
+
+        self.loginUser(username, password: password)
+    }
+
+    func loginUser(username:String, password:String) {
+        UsergridManager.loginUser(username,password: password) { (auth, user, error) -> Void in
+            if let authErrorDescription = error {
+                self.showAlert(title: "Error Authenticating User", message: authErrorDescription.errorDescription)
+            } else if let authenticatedUser = user {
+                self.showAlert(title: "Authenticated User Successful", message: "User description: \n \(authenticatedUser.stringValue)") { (action) -> Void in
+                    self.performSegueWithIdentifier("loginSuccessSegue", sender: self)
+                }
+            }
+        }
+    }
+
+    @IBAction func unwind(segue: UIStoryboardSegue) {
+        // Used for unwind segues back to this view controller.
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/MessageTableViewCell.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/MessageTableViewCell.swift b/sdks/swift/Samples/ActivityFeed/Source/MessageTableViewCell.swift
new file mode 100644
index 0000000..a77abd8
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/MessageTableViewCell.swift
@@ -0,0 +1,101 @@
+//
+//  MessageTableViewCell.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 11/24/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import UIKit
+
+public class MessageTableViewCell : UITableViewCell {
+
+    var titleLabel : UILabel
+    var bodyLabel  : UILabel
+    var thumbnailView : UIImageView
+    var indexPath : NSIndexPath?
+
+    public static let kMessageTableViewCellMinimumHeight: CGFloat = 50.0;
+    public static let kMessageTableViewCellAvatarHeight: CGFloat = 30.0;
+
+    static var defaultFontSize: CGFloat {
+        return 16.0
+    }
+
+    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
+        self.titleLabel = UILabel(frame: CGRect.zero)
+        self.bodyLabel = UILabel(frame: CGRect.zero)
+        self.thumbnailView = UIImageView(frame: CGRect.zero)
+
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+
+        self.selectionStyle = UITableViewCellSelectionStyle.None
+        self.backgroundColor = UIColor.whiteColor()
+        self.configureSubviews()
+    }
+
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    override public func prepareForReuse() {
+        self.selectionStyle = UITableViewCellSelectionStyle.None
+        self.titleLabel.font = UIFont.boldSystemFontOfSize(MessageTableViewCell.defaultFontSize)
+        self.bodyLabel.font = UIFont.boldSystemFontOfSize(13)
+        self.titleLabel.text = ""
+        self.bodyLabel.text = ""
+    }
+
+    func configureSubviews() {
+        self.titleLabel.translatesAutoresizingMaskIntoConstraints = false
+        self.titleLabel.backgroundColor = UIColor.clearColor()
+        self.titleLabel.userInteractionEnabled = false
+        self.titleLabel.numberOfLines = 0
+        self.titleLabel.textColor = UIColor.grayColor()
+        self.titleLabel.font = UIFont.boldSystemFontOfSize(MessageTableViewCell.defaultFontSize)
+
+        self.bodyLabel.translatesAutoresizingMaskIntoConstraints = false
+        self.bodyLabel.backgroundColor = UIColor.clearColor()
+        self.bodyLabel.userInteractionEnabled = false
+        self.bodyLabel.numberOfLines = 0
+        self.bodyLabel.textColor = UIColor.grayColor()
+        self.bodyLabel.font = UIFont.boldSystemFontOfSize(13)
+
+        self.thumbnailView.translatesAutoresizingMaskIntoConstraints = false
+        self.thumbnailView.userInteractionEnabled = false
+        self.thumbnailView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
+        self.thumbnailView.layer.cornerRadius = 15
+        self.thumbnailView.layer.masksToBounds = true
+
+        self.contentView.addSubview(self.thumbnailView)
+        self.contentView.addSubview(self.titleLabel)
+        self.contentView.addSubview(self.bodyLabel)
+
+        let views = ["thumbnailView":self.thumbnailView, "titleLabel":self.titleLabel, "bodyLabel":self.bodyLabel]
+        let metrics = ["thumbSize":MessageTableViewCell.kMessageTableViewCellAvatarHeight, "padding":15, "right":10, "left":5]
+
+        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-left-[thumbnailView(thumbSize)]-right-[titleLabel(>=0)]-right-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views))
+        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-left-[thumbnailView(thumbSize)]-right-[bodyLabel(>=0)]-right-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views))
+        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-right-[titleLabel(20)]-left-[bodyLabel(>=0@999)]-left-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views))
+        self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-right-[thumbnailView(thumbSize)]-(>=0)-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views))
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Samples/ActivityFeed/Source/MessageTextView.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Samples/ActivityFeed/Source/MessageTextView.swift b/sdks/swift/Samples/ActivityFeed/Source/MessageTextView.swift
new file mode 100644
index 0000000..135372e
--- /dev/null
+++ b/sdks/swift/Samples/ActivityFeed/Source/MessageTextView.swift
@@ -0,0 +1,39 @@
+//
+//  MessageTextView.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 11/24/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+import SlackTextViewController
+
+class MessageTextView : SLKTextView {
+    override func willMoveToSuperview(newSuperview: UIView?) {
+        super.willMoveToSuperview(newSuperview)
+        self.backgroundColor = UIColor.whiteColor()
+        self.placeholderColor = UIColor.lightGrayColor()
+        self.placeholder = "Message"
+        self.pastableMediaTypes = .None
+        self.layer.borderColor = UIColor(red: 217/255, green: 217/255, blue: 217/255, alpha: 1.0).CGColor
+    }
+}


Mime
View raw message