This fork's main purpose is to make the library build on WatchOS. It incorporates ChenJian345's patches to work with AFNetworking 3, which is a necessity. -- grahamparks
FRDStravaClient is an objective-C iOS library to the Strava v3 API.
It supports read operations for most of the API endpoints and activity upload.
This project is forked from https://github.com/sebastienwindal/FRDStravaClient, recogmend by Strava, but this version only support AFNetworking v2.0+.
So, I made some changes to support AFNetworking v3.0+. Thank the original author.
If you want to use different AFNetworking version support, you can change different branch.
Mark C.J.
BeiJing, China.
- AFNetworking for networking
- Mantle to convert the JSON NSDictionary responses into usable model objects.
It consists of a bunch of model objects StravaXXX
(e.g. StravaActivity
,
StravaAthlete
, etc...) and a client class FRDStravaClient
that encapsulates the AFHTTPRequestOperationManager calls.
Model objects are all subclasses of MTLModel
, and they closely follow the structure of the Strava API response objects.
FRDStravaClient is a singleton object (use [FRDStravaClient sharedInstance]
) with fetch request methods that match
the Rest API endpoints. FRDStravaClient fetch calls are grouped into 9 categories FRDStravaClient+XXX
e.g. FRDStravaClient+Activity
,
FRDStravaClient+Athlete
, etc... They all follow the same pattern:
-(void) fetchActivitiesForCurrentAthleteWithPageSize:(NSInteger)pageSize
pageIndex:(NSInteger)pageIndex
success:(void (^)(NSArray *activities))success
failure:(void (^)(NSError *error))failure;
-(void) fetchAthleteWithId:(NSInteger)athleteId
success:(void (^)(StravaAthlete *athlete))success
failure:(void (^)(NSError *error))failure;
To get started, just initialize with:
[[FRDStravaClient sharedInstance] initializeWithClientId:clientID
clientSecret:clientSecret];
clientID and clientSecret should match: your app configuration on Strava: https://www.strava.com/settings/api
and then implement the OAUTH workflow described below.
Using cocoapods: Only for AFNetworking v2.0
pod "FRDStravaClient", "~> 1.0.2"
And #import FRDStravaClientImports.h
in your source files.
By hand: For use AFNetworking v2.0 and v3.0+
You need all the stuff in the Classes/
folder, AFNetworking
version x.x and Mantle
version x.x.x.
Or copy all stuff in the Classes/
folder and add below content into Podfile of your project.
pod "AFNetworking", "~> 3.0"
pod "Mantle", "1.5"
pod 'SDWebImage', '~>3.4'
pod 'JBChartView', '~> 2.5.0'
pod 'EDColor'
The library header files have appledoc comments with appropriate links to the API section, you can check them in the
code or in the
FRDStravaClient Cocoadocs page.
The typical authorization/OAUTH flow in your app should look like this:
iOS app calls authorizeWithCallbackURL:stateInfo:
. This method will launch Safari at the Strava OAUTH web page where users will be prompted to login and grant Strava access to your app. The domain of the callback URL must match the Authorization Callback Domain you configured with Strava (at this location: https://www.strava.com/settings/api ). The URL scheme should be one you configured in your app plist as Custom URL Scheme, so your app can be launched back by Safari upon success.
NSString *strURL = @"yourAppURLScheme://domain.registered.with.strava";
[[FRDStravaClient sharedInstance] authorizeWithCallbackURL:[NSURL URLWithString:strURL]
stateInfo:nil];
Upon success your app is launched back by Safari. In your AppDelegate application:handleOpenURL:
, call parseStravaAuthCallback:withSuccess:failure:
to parse the callback URL.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
[[FRDStravaClient sharedInstance] parseStravaAuthCallback:url
withSuccess:^(NSString *stateInfo, NSString *code) {
// load appropriate view controller/view and
// make it initiate the token exchange using "code"
}
failure:^(NSString *stateInfo, NSString *error) {
// show error
}];
return YES;
}
Whatever you do in the success block of parseStravaAuthCallback:withSuccess:failure:
should
end up calling exchangeTokenForCode:success:failure:
with the code we just got back:
[[FRDStravaClient sharedInstance] exchangeTokenForCode:code
success:^(StravaAccessTokenResponse *response) {
// we are all good,
// save response.accessToken somewhere safe in persistent storage
// response.athlete is the curently logged in user btw...
} failure:^(NSError *error) {
// show error
}];
Upon success you are now good to go for this session... The accessToken
in the shared instance of FRDStravaClient was automatically set and all REST calls issued by the FRDStravaClient sharedInstance will be sent with the required token.
At this point your should save the access token somewhere safely in your app persistent storage (like the keychain), for future run of your app, to be able to bypass that whole painful OAuth dance. Next time your app is run just call the setAccessToken:
method of the [FRDStravaClient sharedInstance]
with your saved access token:
// check if we already went through the OAUTH dance before
NSString *previousToken = .... fetch your token from persistent storage
if ([previousToken length] > 0) {
// this is the important part, configure the client with that token.
[[FRDStravaClient sharedInstance] setAccessToken:previousToken];
// let's make a simple call to check our token is still valid:
[[FRDStravaClient sharedInstance] fetchCurrentAthleteWithSuccess:^(StravaAthlete *athlete) {
// all good
}
failure:^(NSError *error) {
// the token is expired
[[FRDStravaClient sharedInstance] setAccessToken:nil];
// we need to request access again, by going to 1.
}];
This is a quick and dirty app done for testing purpose only. Copy and paste at your own risk.
To run it:
- run
pod update
in the FRDStravaClientDemo folder and openFRDStravaClientDemo.xcworkspace
in XCode. - register an app with Strava
- run the demo app, it will install its settings bundle to the system settings.
- open the demo app settings from the iPhone/Simulator global settings and configure client ID, secret and callback domain of your Strava app:
- alternatively, you can also hardcode that stuff in the demo app
AuthViewController.m
viewDidLoad:
.
Once you do that, re-launch the app, it should work. Sample screenshots: