Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,3 @@ platform :ios, '8.0'

pod 'AFNetworking'
pod 'BDBOAuth1Manager'

14 changes: 7 additions & 7 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
PODS:
- AFNetworking (2.4.1):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/UIKit
- AFNetworking/NSURLConnection (= 2.4.1)
- AFNetworking/NSURLSession (= 2.4.1)
- AFNetworking/Reachability (= 2.4.1)
- AFNetworking/Security (= 2.4.1)
- AFNetworking/Serialization (= 2.4.1)
- AFNetworking/UIKit (= 2.4.1)
- AFNetworking/NSURLConnection (2.4.1):
- AFNetworking/Reachability
- AFNetworking/Security
Expand All @@ -32,4 +32,4 @@ SPEC CHECKSUMS:
AFNetworking: 0aabc6fae66d6e5d039eeb21c315843c7aae51ab
BDBOAuth1Manager: 4f0967110286edd4c7961cf48a4eb242c64137a1

COCOAPODS: 0.33.1
COCOAPODS: 0.35.0
110 changes: 35 additions & 75 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,45 @@
### Basic Yelp client
## Yelp

This is a headless example of how to implement an OAuth 1.0a Yelp API client. The Yelp API provides an application token that allows applications to make unauthenticated requests to their search API.
This is a Yelp search app using the [Yelp API](http://developer.rottentomatoes.com/docs/read/JSON).

### Next steps
Time spent: 12

- Check out `MainViewController.swift` to see how to use the `YelpClient`.
- Augment the search method in the `YelpClient` with whatever search parameters you want to support.
### Features

### Sample request
#### Required

```
client = YelpClient(consumerKey: yelpConsumerKey, consumerSecret: yelpConsumerSecret, accessToken: yelpToken, accessSecret: yelpTokenSecret)
- [X] Search results page
- [X] Table rows should be dynamic height according to the content height
- [X] Custom cells should have the proper Auto Layout constraints
- [X] Search bar should be in the navigation bar (doesn't have to expand to show location like the real Yelp app does). (Please see notes.)
- [X] Filter page. Unfortunately, not all the filters are supported in the Yelp API.
- [X] The filters you should actually have are: category, sort (best match, distance, highest rated), radius (meters), deals (on/off).
- [X] The filters table should be organized into sections as in the mock.
- [X] You can use the default UISwitch for on/off states. Optional: implement a custom switch
- [X] Clicking on the "Search" button should dismiss the filters page and trigger the search w/ the new filter settings.
- [X] Display some of the available Yelp categories (choose any 3-4 that you want). (Please see notes.)

client.searchWithTerm("Thai", success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
println(response)
}) { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
println(error)
}
Notes:

```
* The categories search field is implemented as a text field. The user enters a comma-separated list of category codes.
* I couldn't get the sort field to work. Selecting on a table cell does not select the cell. I think it has to do with the tap gesture that I created in that same view.
* I've added a search bar, but didn't get it to work.

### Sample response
#### Optional

```
businesses = (
{
categories = (
(
Thai,
thai
)
);
"display_phone" = "+1-415-931-6917";
id = "lers-ros-thai-san-francisco";
"image_url" = "http://s3-media2.ak.yelpcdn.com/bphoto/IStxUNVdfuPR2ddDAIPk_A/ms.jpg";
"is_claimed" = 1;
"is_closed" = 0;
location = {
address = (
"730 Larkin St"
);
city = "San Francisco";
"country_code" = US;
"cross_streets" = "Olive St & Ellis St";
"display_address" = (
"730 Larkin St",
"(b/t Olive St & Ellis St)",
Tenderloin,
"San Francisco, CA 94109"
);
neighborhoods = (
Tenderloin
);
"postal_code" = 94109;
"state_code" = CA;
};
"menu_date_updated" = 1387658025;
"menu_provider" = "single_platform";
"mobile_url" = "http://m.yelp.com/biz/lers-ros-thai-san-francisco";
name = "Lers Ros Thai";
phone = 4159316917;
rating = 4;
"rating_img_url" = "http://s3-media4.ak.yelpcdn.com/assets/2/www/img/c2f3dd9799a5/ico/stars/v1/stars_4.png";
"rating_img_url_large" = "http://s3-media2.ak.yelpcdn.com/assets/2/www/img/ccf2b76faa2c/ico/stars/v1/stars_large_4.png";
"rating_img_url_small" = "http://s3-media4.ak.yelpcdn.com/assets/2/www/img/f62a5be2f902/ico/stars/v1/stars_small_4.png";
"review_count" = 1154;
"snippet_image_url" = "http://s3-media4.ak.yelpcdn.com/photo/D40HpcJt-O6Ll654S_--6w/ms.jpg";
"snippet_text" = "Fantastic pad-see-ew. Super rich, flavorful sauce and plenty of ginormous prawns, especially for a $12 price tag in San Francisco. I went through a pretty...";
url = "http://www.yelp.com/biz/lers-ros-thai-san-francisco";
}
);
region = {
center = {
latitude = "37.7703124";
longitude = "-122.43647245575";
};
span = {
"latitude_delta" = "0.06424638000000016";
"longitude_delta" = "0.07145348265001417";
};
};
total = 760;
```
- [ ] Search results page
- [ ] Infinite scroll for restaurant results
- [ ] Implement map view of restaurant results
- [ ] Filter page
- [ ] Radius filter should expand as in the real Yelp app
- [ ] Categories should show a subset of the full list with a "See All" row to expand. Category list is here: http://www.yelp.com/developers/documentation/category_list (Links to an external site.)
- [ ] Implement the restaurant detail page.

### Walkthrough
![Video Walkthrough](yelp_demo.gif)

Credits
---------
* [Yelp API](http://www.yelp.com/developers/documentation)
* [AFNetworking](https://github.com/AFNetworking/AFNetworking)
* [LiceCap](http://www.cockos.com/licecap/)
56 changes: 51 additions & 5 deletions Yelp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

/* Begin PBXBuildFile section */
03D1A025B413415787AD3DF3 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C56EF0CE844A4EE5819C72AF /* libPods.a */; };
1848E35F1A917BA1003A1402 /* FiltersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1848E35D1A917BA1003A1402 /* FiltersViewController.swift */; };
1848E3621A91A889003A1402 /* SearchOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1848E3611A91A889003A1402 /* SearchOptions.swift */; };
1861678A1A8F158300E9ADBA /* Business.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186167891A8F158300E9ADBA /* Business.swift */; };
1861678E1A8F1D5C00E9ADBA /* BusinessCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1861678C1A8F1D5C00E9ADBA /* BusinessCell.swift */; };
1861678F1A8F1D5C00E9ADBA /* BusinessCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1861678D1A8F1D5C00E9ADBA /* BusinessCell.xib */; };
222D8A5B19CCF9F900D2DB53 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 222D8A5A19CCF9F900D2DB53 /* AppDelegate.swift */; };
222D8A5D19CCF9F900D2DB53 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 222D8A5C19CCF9F900D2DB53 /* ViewController.swift */; };
222D8A6019CCF9F900D2DB53 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 222D8A5E19CCF9F900D2DB53 /* Main.storyboard */; };
Expand All @@ -28,6 +33,11 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
1848E35D1A917BA1003A1402 /* FiltersViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FiltersViewController.swift; sourceTree = "<group>"; };
1848E3611A91A889003A1402 /* SearchOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchOptions.swift; sourceTree = "<group>"; };
186167891A8F158300E9ADBA /* Business.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Business.swift; sourceTree = "<group>"; };
1861678C1A8F1D5C00E9ADBA /* BusinessCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BusinessCell.swift; sourceTree = "<group>"; };
1861678D1A8F1D5C00E9ADBA /* BusinessCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BusinessCell.xib; sourceTree = "<group>"; };
222D8A5519CCF9F900D2DB53 /* Yelp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Yelp.app; sourceTree = BUILT_PRODUCTS_DIR; };
222D8A5919CCF9F900D2DB53 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
222D8A5A19CCF9F900D2DB53 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand All @@ -41,7 +51,8 @@
222D8A7C19CCFAE000D2DB53 /* YelpClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YelpClient.swift; sourceTree = "<group>"; };
222D8A7E19CCFAEF00D2DB53 /* Yelp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Yelp-Bridging-Header.h"; sourceTree = "<group>"; };
C56EF0CE844A4EE5819C72AF /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
D4E76156B42F474DB4157657 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = "<group>"; };
D5732CD97E4DF7DC274FB59C /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
E00CFE4A3AA1AD81E1F85AD8 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -63,14 +74,31 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
186167881A8F154700E9ADBA /* Models */ = {
isa = PBXGroup;
children = (
186167891A8F158300E9ADBA /* Business.swift */,
);
name = Models;
sourceTree = "<group>";
};
1861678B1A8F1D1B00E9ADBA /* Views */ = {
isa = PBXGroup;
children = (
1861678C1A8F1D5C00E9ADBA /* BusinessCell.swift */,
1861678D1A8F1D5C00E9ADBA /* BusinessCell.xib */,
);
name = Views;
sourceTree = "<group>";
};
222D8A4C19CCF9F900D2DB53 = {
isa = PBXGroup;
children = (
222D8A5719CCF9F900D2DB53 /* Yelp */,
222D8A6D19CCF9F900D2DB53 /* YelpTests */,
222D8A5619CCF9F900D2DB53 /* Products */,
D4E76156B42F474DB4157657 /* Pods.xcconfig */,
4A7CA25ACD374CA0AC966A24 /* Frameworks */,
F745A2A08ABC6842A9E4C8D2 /* Pods */,
);
sourceTree = "<group>";
};
Expand All @@ -86,6 +114,8 @@
222D8A5719CCF9F900D2DB53 /* Yelp */ = {
isa = PBXGroup;
children = (
1861678B1A8F1D1B00E9ADBA /* Views */,
186167881A8F154700E9ADBA /* Models */,
222D8A7A19CCFAAA00D2DB53 /* API */,
222D8A7B19CCFAB600D2DB53 /* View Controllers */,
222D8A5A19CCF9F900D2DB53 /* AppDelegate.swift */,
Expand Down Expand Up @@ -127,6 +157,7 @@
isa = PBXGroup;
children = (
222D8A7C19CCFAE000D2DB53 /* YelpClient.swift */,
1848E3611A91A889003A1402 /* SearchOptions.swift */,
);
name = API;
sourceTree = "<group>";
Expand All @@ -135,6 +166,7 @@
isa = PBXGroup;
children = (
222D8A5C19CCF9F900D2DB53 /* ViewController.swift */,
1848E35D1A917BA1003A1402 /* FiltersViewController.swift */,
);
name = "View Controllers";
sourceTree = "<group>";
Expand All @@ -147,6 +179,15 @@
name = Frameworks;
sourceTree = "<group>";
};
F745A2A08ABC6842A9E4C8D2 /* Pods */ = {
isa = PBXGroup;
children = (
E00CFE4A3AA1AD81E1F85AD8 /* Pods.debug.xcconfig */,
D5732CD97E4DF7DC274FB59C /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -230,6 +271,7 @@
buildActionMask = 2147483647;
files = (
222D8A6019CCF9F900D2DB53 /* Main.storyboard in Resources */,
1861678F1A8F1D5C00E9ADBA /* BusinessCell.xib in Resources */,
222D8A6519CCF9F900D2DB53 /* LaunchScreen.xib in Resources */,
222D8A6219CCF9F900D2DB53 /* Images.xcassets in Resources */,
);
Expand Down Expand Up @@ -257,7 +299,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
4817EA46FAD24F44BB24E6FB /* Check Pods Manifest.lock */ = {
Expand All @@ -282,8 +324,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1861678E1A8F1D5C00E9ADBA /* BusinessCell.swift in Sources */,
222D8A5D19CCF9F900D2DB53 /* ViewController.swift in Sources */,
1861678A1A8F158300E9ADBA /* Business.swift in Sources */,
222D8A7D19CCFAE000D2DB53 /* YelpClient.swift in Sources */,
1848E35F1A917BA1003A1402 /* FiltersViewController.swift in Sources */,
1848E3621A91A889003A1402 /* SearchOptions.swift in Sources */,
222D8A5B19CCF9F900D2DB53 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -405,7 +451,7 @@
};
222D8A7519CCF9F900D2DB53 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D4E76156B42F474DB4157657 /* Pods.xcconfig */;
baseConfigurationReference = E00CFE4A3AA1AD81E1F85AD8 /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
Expand All @@ -419,7 +465,7 @@
};
222D8A7619CCF9F900D2DB53 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D4E76156B42F474DB4157657 /* Pods.xcconfig */;
baseConfigurationReference = D5732CD97E4DF7DC274FB59C /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
Expand Down
Loading