usergrid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mru...@apache.org
Subject [50/51] [partial] usergrid-swift git commit: Initial commit of Usergrid Swift SDK.
Date Thu, 01 Sep 2016 23:52:11 GMT
http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Readme.md
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Readme.md b/Samples/ActivityFeed/Readme.md
new file mode 100644
index 0000000..9fb6555
--- /dev/null
+++ b/Samples/ActivityFeed/Readme.md
@@ -0,0 +1,29 @@
+#ActivityFeed
+
+## Installing dependencies
+
+The `ActivityFeed` sample app utilizes `Cocoapods` and you will need to run the `$ pod install` command from within the root folder of the sample project in order for the sample to run properly.
+
+## Running the Sample
+
+To run the sample app, simply open the `ActivityFeed.xcworkspace` file in Xcode.
+
+Two targets in Xcode specific to this application will be available:
+
+- **ActivityFeed Target**
+
+	This will run the iOS sample application.
+	
+- **Watch Sample Target**
+
+	This will run the watchOS companion app.
+
+##Configuring the Sample Apps
+
+Before running the sample applications you will need to configure each sample application. 
+
+Each sample application should include a source file named `UsergridManager.swift`.  This source file is used to contain interaction with the UsergridSDK within a single source file.  In doing so, the interactions within the sample apps can be easily seen and examined.
+
+Within the `UsergridManager.swift` source there will be at least two different static vars named `ORG_ID` and `APP_ID`.  You will need to configure those values in order to run the applications in your environment.    
+
+Applications which utilize push notifications will require a valid provisioning profile and device for the push services to work correctly.   

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/ActivityEntity.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/ActivityEntity.swift b/Samples/ActivityFeed/Source/ActivityEntity.swift
new file mode 100644
index 0000000..5ddcf12
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/AppDelegate.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/AppDelegate.swift b/Samples/ActivityFeed/Source/AppDelegate.swift
new file mode 100644
index 0000000..cca5c41
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json b/Samples/ActivityFeed/Source/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..118c98f
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json b/Samples/ActivityFeed/Source/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json b/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/Contents.json
new file mode 100644
index 0000000..c19ad83
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png b/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png
new file mode 100644
index 0000000..b8a6844
Binary files /dev/null and b/Samples/ActivityFeed/Source/Assets.xcassets/UsergridGuy.imageset/UsergridGuy.png differ

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard b/Samples/ActivityFeed/Source/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..78686cd
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard b/Samples/ActivityFeed/Source/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..8ec5316
--- /dev/null
+++ b/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="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="0Ca-En-eac">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+        <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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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="ActivityFeed" 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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/FollowViewController.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/FollowViewController.swift b/Samples/ActivityFeed/Source/FollowViewController.swift
new file mode 100644
index 0000000..6362cdb
--- /dev/null
+++ b/Samples/ActivityFeed/Source/FollowViewController.swift
@@ -0,0 +1,50 @@
+//
+//  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 UIKit
+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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/FormTextField.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/FormTextField.swift b/Samples/ActivityFeed/Source/FormTextField.swift
new file mode 100644
index 0000000..fbb9bd6
--- /dev/null
+++ b/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: #selector(FormTextField.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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/Info.plist
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/Info.plist b/Samples/ActivityFeed/Source/Info.plist
new file mode 100644
index 0000000..2ea3512
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/LoginViewController.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/LoginViewController.swift b/Samples/ActivityFeed/Source/LoginViewController.swift
new file mode 100644
index 0000000..0e6c0fa
--- /dev/null
+++ b/Samples/ActivityFeed/Source/LoginViewController.swift
@@ -0,0 +1,77 @@
+//
+//  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 UIKit
+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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/MessageTableViewCell.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/MessageTableViewCell.swift b/Samples/ActivityFeed/Source/MessageTableViewCell.swift
new file mode 100644
index 0000000..a77abd8
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Samples/ActivityFeed/Source/MessageTextView.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/MessageTextView.swift b/Samples/ActivityFeed/Source/MessageTextView.swift
new file mode 100644
index 0000000..135372e
--- /dev/null
+++ b/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
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/MessageViewController.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/MessageViewController.swift b/Samples/ActivityFeed/Source/MessageViewController.swift
new file mode 100644
index 0000000..b2a152c
--- /dev/null
+++ b/Samples/ActivityFeed/Source/MessageViewController.swift
@@ -0,0 +1,224 @@
+//
+//  MessageViewController.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
+import SlackTextViewController
+import WatchConnectivity
+
+class MessageViewController : SLKTextViewController {
+
+    static let MESSAGE_CELL_IDENTIFIER = "MessengerCell"
+
+    private var messageEntities: [ActivityEntity] = []
+
+    init() {
+        super.init(tableViewStyle:.Plain)
+        commonInit()
+    }
+
+    required init(coder decoder: NSCoder) {
+        super.init(coder: decoder)
+        commonInit()
+    }
+
+    override static func tableViewStyleForCoder(decoder: NSCoder) -> UITableViewStyle {
+        return .Plain
+    }
+
+    override func viewWillAppear(animated: Bool) {
+        self.reloadMessages()
+        if let username = Usergrid.currentUser?.name {
+            self.navigationItem.title = "\(username)'s Feed"
+        }
+        super.viewWillAppear(animated)
+    }
+
+    func commonInit() {
+        self.bounces = true
+        self.shakeToClearEnabled = true
+        self.keyboardPanningEnabled = true
+        self.shouldScrollToBottomAfterKeyboardShows = true
+        self.inverted = true
+
+        self.registerClassForTextView(MessageTextView)
+        self.activateWCSession()
+    }
+
+    func reloadMessages() {
+        UsergridManager.getFeedMessages { (response) -> Void in
+            self.messageEntities = response.entities as? [ActivityEntity] ?? []
+            self.tableView!.reloadData()
+        }
+    }
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        self.rightButton.setTitle("Send", forState: .Normal)
+
+        self.textInputbar.autoHideRightButton = true
+        self.textInputbar.maxCharCount = 256
+        self.textInputbar.editorTitle.textColor = UIColor.darkGrayColor()
+
+        self.tableView!.separatorStyle = .None
+        self.tableView!.registerClass(MessageTableViewCell.self, forCellReuseIdentifier:MessageViewController.MESSAGE_CELL_IDENTIFIER)
+    }
+
+    override func didPressRightButton(sender: AnyObject!) {
+        self.textView.refreshFirstResponder()
+
+        UsergridManager.postFeedMessage(self.textView.text) { (response) -> Void in
+            if let messageEntity = response.entity as? ActivityEntity {
+                let indexPath = NSIndexPath(forRow: 0, inSection: 0)
+                let rowAnimation: UITableViewRowAnimation = self.inverted ? .Bottom : .Top
+                let scrollPosition: UITableViewScrollPosition = self.inverted ? .Bottom : .Top
+
+                self.tableView!.beginUpdates()
+                self.messageEntities.insert(messageEntity, atIndex: 0)
+                self.tableView!.insertRowsAtIndexPaths([indexPath], withRowAnimation: rowAnimation)
+                self.tableView!.endUpdates()
+
+                self.tableView!.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: true)
+                self.tableView!.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
+
+                self.sendEntitiesToWatch(self.messageEntities)
+            }
+        }
+        super.didPressRightButton(sender)
+    }
+
+    override func keyForTextCaching() -> String? {
+        return NSBundle.mainBundle().bundleIdentifier
+    }
+
+    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
+        return 1
+    }
+
+    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return self.messageEntities.count
+    }
+
+    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
+        return self.messageCellForRowAtIndexPath(indexPath)
+    }
+
+    @IBAction func unwindToChat(segue: UIStoryboardSegue) {
+
+    }
+
+    func populateCell(cell:MessageTableViewCell,feedEntity:ActivityEntity) {
+
+        cell.titleLabel.text = feedEntity.displayName
+        cell.bodyLabel.text = feedEntity.content
+        cell.thumbnailView.image = nil
+
+        if let imageURLString = feedEntity.imageURL, imageURL = NSURL(string: imageURLString) {
+            NSURLSession.sharedSession().dataTaskWithURL(imageURL) { (data, response, error) in
+                if let imageData = data, image = UIImage(data: imageData) {
+                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                        cell.thumbnailView.image = image
+                    })
+                }
+            }.resume()
+        }
+    }
+
+    func messageCellForRowAtIndexPath(indexPath:NSIndexPath) -> MessageTableViewCell {
+        let cell = self.tableView!.dequeueReusableCellWithIdentifier(MessageViewController.MESSAGE_CELL_IDENTIFIER) as! MessageTableViewCell
+        self.populateCell(cell, feedEntity: self.messageEntities[indexPath.row])
+
+        cell.indexPath = indexPath
+        cell.transform = self.tableView!.transform
+
+        return cell
+    }
+
+    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
+
+        let feedEntity = messageEntities[indexPath.row]
+
+        guard let messageText = feedEntity.content where !messageText.isEmpty
+        else {
+                return 0
+        }
+
+        let messageUsername : NSString = feedEntity.displayName ?? ""
+
+        let paragraphStyle = NSMutableParagraphStyle()
+        paragraphStyle.lineBreakMode = .ByWordWrapping
+        paragraphStyle.alignment = .Left
+
+        let pointSize = MessageTableViewCell.defaultFontSize
+        let attributes = [NSFontAttributeName:UIFont.boldSystemFontOfSize(pointSize),NSParagraphStyleAttributeName:paragraphStyle]
+
+        let width: CGFloat = CGRectGetWidth(self.tableView!.frame) - MessageTableViewCell.kMessageTableViewCellAvatarHeight - 25
+
+        let titleBounds = messageUsername.boundingRectWithSize(CGSize(width: width, height: CGFloat.max), options: .UsesLineFragmentOrigin, attributes: attributes, context: nil)
+        let bodyBounds = messageText.boundingRectWithSize(CGSize(width: width, height: CGFloat.max), options: .UsesLineFragmentOrigin, attributes: attributes, context: nil)
+
+        var height = CGRectGetHeight(titleBounds) + CGRectGetHeight(bodyBounds) + 40
+        if height < MessageTableViewCell.kMessageTableViewCellMinimumHeight {
+            height = MessageTableViewCell.kMessageTableViewCellMinimumHeight
+        }
+
+        return height
+    }
+}
+
+extension MessageViewController : WCSessionDelegate {
+
+    func activateWCSession() {
+        if (WCSession.isSupported()) {
+            let session = WCSession.defaultSession()
+            session.delegate = self
+            session.activateSession()
+        }
+    }
+
+    func sendEntitiesToWatch(messages:[UsergridEntity]) {
+        if WCSession.defaultSession().reachable {
+            NSKeyedArchiver.setClassName("ActivityEntity", forClass: ActivityEntity.self)
+            let data = NSKeyedArchiver.archivedDataWithRootObject(messages)
+            WCSession.defaultSession().sendMessageData(data, replyHandler: nil, errorHandler: { (error) -> Void in
+                self.showAlert(title: "WCSession Unreachable.", message: "\(error)")
+            })
+        }
+    }
+
+    func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {
+        if let action = message["action"] as? String where action == "getMessages" {
+            UsergridManager.getFeedMessages { (response) -> Void in
+                if let entities = response.entities {
+                    self.sendEntitiesToWatch(entities)
+                }
+            }
+        }
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/RegisterViewController.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/RegisterViewController.swift b/Samples/ActivityFeed/Source/RegisterViewController.swift
new file mode 100644
index 0000000..25cad11
--- /dev/null
+++ b/Samples/ActivityFeed/Source/RegisterViewController.swift
@@ -0,0 +1,62 @@
+//
+//  RegisterViewController.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
+import UsergridSDK
+
+class RegisterViewController: UIViewController {
+
+    @IBOutlet weak var nameTextField: UITextField!
+    @IBOutlet weak var usernameTextField: UITextField!
+    @IBOutlet weak var emailTextField: UITextField!
+    @IBOutlet weak var passwordTextField: UITextField!
+
+    @IBAction func registerButtonTouched(sender: AnyObject) {
+        guard let name = nameTextField.text where !name.isEmpty,
+              let username = usernameTextField.text where !username.isEmpty,
+              let email = emailTextField.text where !email.isEmpty,
+              let password = passwordTextField.text where !password.isEmpty
+        else {
+            self.showAlert(title: "Error Registering User", message: "Name, username, email, and password fields must not be empty.")
+            return;
+        }
+
+        self.createUser(name, username: username, email: email, password: password)
+    }
+
+    private func createUser(name:String, username:String, email:String, password:String) {
+        UsergridManager.createUser(name, username: username, email: email, password: password) { (response) -> Void in
+            if let createdUser = response.user {
+                self.showAlert(title: "Registering User Successful", message: "User description: \n \(createdUser.stringValue)") { (action) -> Void in
+                    self.performSegueWithIdentifier("unwindSegue", sender: self)
+                }
+            } else {
+                self.showAlert(title: "Error Registering User", message: response.error?.errorDescription)
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/UsergridManager.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/UsergridManager.swift b/Samples/ActivityFeed/Source/UsergridManager.swift
new file mode 100644
index 0000000..99fe4b5
--- /dev/null
+++ b/Samples/ActivityFeed/Source/UsergridManager.swift
@@ -0,0 +1,78 @@
+//
+//  UsergridManager.swift
+//  ActivityFeed
+//
+//  Created by Robert Walsh on 1/19/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
+
+/// This class handles the primary communications to the UsergirdSDK.
+public class UsergridManager {
+
+    static let ORG_ID = "rwalsh"
+    static let APP_ID = "sandbox"
+    static let NOTIFIER_ID = "usergridsample"
+    static let BASE_URL = "https://api.usergrid.com"
+
+    static func initializeSharedInstance() {
+        Usergrid.initSharedInstance(configuration: UsergridClientConfig(orgId: UsergridManager.ORG_ID, appId: UsergridManager.APP_ID, baseUrl: UsergridManager.BASE_URL))
+        ActivityEntity.registerSubclass()
+    }
+
+    static func loginUser(username:String, password:String, completion:UsergridUserAuthCompletionBlock) {
+        let userAuth = UsergridUserAuth(username: username, password: password)
+        Usergrid.authenticateUser(userAuth, completion: completion)
+    }
+
+    static func createUser(name:String, username:String, email:String, password:String, completion:UsergridResponseCompletion) {
+        let user = UsergridUser(name: name, propertyDict: [UsergridUserProperties.Username.stringValue:username,
+                                                            UsergridUserProperties.Email.stringValue:email,
+                                                            UsergridUserProperties.Password.stringValue:password])
+        user.create(completion)
+    }
+
+    static func getFeedMessages(completion:UsergridResponseCompletion) {
+        Usergrid.GET(UsergridQuery("users/me/feed").desc(UsergridEntityProperties.Created.stringValue), queryCompletion: completion)
+    }
+
+    static func postFeedMessage(text:String,completion:UsergridResponseCompletion) {
+        let currentUser = Usergrid.currentUser!
+
+        let verb = "post"
+        let content = text
+
+        var actorDictionary = [String:AnyObject]()
+        actorDictionary["displayName"] = currentUser.name ?? currentUser.usernameOrEmail ?? ""
+        actorDictionary["email"] = currentUser.email ?? ""
+        if let imageURL = currentUser.picture {
+            actorDictionary["image"] = ["url":imageURL,"height":80,"width":80]
+        }
+
+        Usergrid.POST("users/me/activities", jsonBody: ["actor":actorDictionary,"verb":verb,"content":content], completion: completion)
+    }
+
+    static func followUser(username:String, completion:UsergridResponseCompletion) {
+        Usergrid.connect("users", entityID: "me", relationship: "following", toType: "users", toName: username, completion: completion)
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/Source/ViewControllerExtensions.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/Source/ViewControllerExtensions.swift b/Samples/ActivityFeed/Source/ViewControllerExtensions.swift
new file mode 100644
index 0000000..ad79741
--- /dev/null
+++ b/Samples/ActivityFeed/Source/ViewControllerExtensions.swift
@@ -0,0 +1,36 @@
+//
+//  ViewControllerExtensions.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
+
+extension UIViewController {
+    func showAlert(title title: String, message: String?, handler:((UIAlertAction) -> Void)? = nil) {
+        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
+        alert.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: handler))
+        self.presentViewController(alert, animated: true, completion: nil)
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/WatchSample Extension/Assets.xcassets/README__ignoredByTemplate__
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/WatchSample Extension/Assets.xcassets/README__ignoredByTemplate__ b/Samples/ActivityFeed/WatchSample Extension/Assets.xcassets/README__ignoredByTemplate__
new file mode 100644
index 0000000..b601d38
--- /dev/null
+++ b/Samples/ActivityFeed/WatchSample Extension/Assets.xcassets/README__ignoredByTemplate__	
@@ -0,0 +1 @@
+Did you know that git does not support storing empty directories?

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/WatchSample Extension/ExtensionDelegate.swift
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/WatchSample Extension/ExtensionDelegate.swift b/Samples/ActivityFeed/WatchSample Extension/ExtensionDelegate.swift
new file mode 100644
index 0000000..400495f
--- /dev/null
+++ b/Samples/ActivityFeed/WatchSample Extension/ExtensionDelegate.swift	
@@ -0,0 +1,45 @@
+//
+//  ExtensionDelegate.swift
+//  WatchSample Extension
+//
+//  Created by Robert Walsh on 1/19/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 WatchKit
+
+class ExtensionDelegate: NSObject, WKExtensionDelegate {
+
+    func applicationDidFinishLaunching() {
+        // Perform any final initialization of your application.
+    }
+
+    func applicationDidBecomeActive() {
+        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+    }
+
+    func applicationWillResignActive() {
+        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+        // Use this method to pause ongoing tasks, disable timers, etc.
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Samples/ActivityFeed/WatchSample Extension/Info.plist
----------------------------------------------------------------------
diff --git a/Samples/ActivityFeed/WatchSample Extension/Info.plist b/Samples/ActivityFeed/WatchSample Extension/Info.plist
new file mode 100644
index 0000000..8d0393f
--- /dev/null
+++ b/Samples/ActivityFeed/WatchSample Extension/Info.plist	
@@ -0,0 +1,45 @@
+<?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>CFBundleDisplayName</key>
+	<string>WatchSample Extension</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>XPC!</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+		<key>NSAllowsArbitraryLoads</key>
+		<true/>
+	</dict>
+	<key>NSExtension</key>
+	<dict>
+		<key>NSExtensionAttributes</key>
+		<dict>
+			<key>WKAppBundleIdentifier</key>
+			<string>com.usergrid.activityfeed.watchkitapp</string>
+		</dict>
+		<key>NSExtensionPointIdentifier</key>
+		<string>com.apple.watchkit</string>
+	</dict>
+	<key>RemoteInterfacePrincipalClass</key>
+	<string>$(PRODUCT_MODULE_NAME).InterfaceController</string>
+	<key>WKExtensionDelegateClassName</key>
+	<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
+</dict>
+</plist>


Mime
View raw message