ObjectiveFlickr, a Flickr API framework for Objective-C

Overview

ObjectiveFlickr

ObjectiveFlickr is a Flickr API framework designed for Mac and iPhone apps.

OAuth Support

ObjectiveFlickr now supports Flickr's new OAuth-based authentication process. I'll post more about it in the coming week. The SnapAndRun sample is updated to reflect the usage. A new Mac sample, OAuthTransitionMac, demonstrates how to use the new OAuth-based API and also how to migrate your existing auth tokens. OAuthTransitionMac uses ARC and therefore also shows how to use ObjectiveFlickr, which is a non-ARC library, with an ARC app.

iOS support in ObjectiveFlickr was developed mostly during the iPhone OS 2.0 days and it shows. More update work will be required to reflect the changes in the iOS development process. Your contribution (like updating this README, submitting new samples or test cases) is greatly welcome -- and it will benefit the iOS open source development community, too!

Update. Please refer to my blog post for the steps you need to take for the transition.

What's New in 2.0

Version 2.0 is a complete rewrite, with design integrity and extensibility in mind. Differences from 0.9.x include:

  • The framework now builds with all major Apple SDKs: Mac OS X 10.4, 10.5, iPhone OS 2.2.x, and other beta version platforms to which I have access. It also builds on both 32-bit and 64-bit platforms.
  • Ordinary request and upload request are now unified into one OFFlickrAPIRequest class
  • 2.0 no longer depends on NSXMLDocument, which is not available in iPhone SDK. It now maps Flickr's XML response into an NSDictionary using only NSXMLParser, which is available on all Apple platforms.
  • Image uploading employs temp file. This allows ObjectiveFlickr to operate in memory-constrained settings.
  • Error reporting now uses NSError to provide more comprehensive information, especially error code and message from Flickr.

If you already use ObjectiveFlickr 0.9.x, the bad news is that 2.0 is not backward compatible. The good news, though, is that it uses a different set of class names. Some migration tips are offered near the end of this document.

What's Not (Yet) There

There are of course quite a few to-do's:

  • In-source API documentation
  • Unit testings
  • Flickr API coverage tests (challenging though—how do you test a moving target?)
  • ObjectiveFlickr 0.9.x has a few convenient methods and tricks to simplify method calling; they are not ported here (yet, or will never be)

Quick Start: Example Apps You Can Use

UPDATE 2.0.4: If you use CocoaPods, you should check out the new sample projects that make use of the tool to manage ObjectiveFlickr for you.

  1. Check out the code from github:
git clone git://github.com/lukhnos/objectiveflickr.git
  1. Supply your own API key and shared secret. You need to copy SampleAPIKey.h.template to SampleAPIKey.h, and fill in the two macros there. If you don't have an API key, apply for yours at: http://www.flickr.com/services/api/keys/apply/ . Make sure you have understood their terms and conditions.

  2. Remember to make your API key a "web app", and set the Callback URL (not the Application URL!) to:

snapnrun://auth?
  1. Build and run SnapAndRun for iPhone. The project is located at Examples/SnapAndRun-iPhone

  2. Build and run RandomPublicPhoto for Mac. The project is at Examples/RandomPublicPhoto

Adding ObjectiveFlickr to Your Project

UPDATE 2.0.4: This section shows its age and needs updating. Pull requests on an up-to-date instruction will be appreciated! Meanwhile, if you use CocoaPods, you can easily add ObjectiveFlickr to your project by adding this one line to you podfile:

pod 'objectiveflickr'

Then just run pod install and start using ObjectiveFlickr.

Adding ObjectiveFlickr to Your Mac App Project

  1. Add ObjectiveFlickr.xcodeproj to your Mac project (from Xcode menu Project > Add to Project...)
  2. On your app target, open the info window (using Get Info on the target), then in the General tab, add ObjectiveFlickr (framework) to Direct Dependencies
  3. Add a new Copy Files phase, and choose Framework for the Destination (in its own info window)
  4. Drag ObjecitveFlickr.framework from the Groups & Files panel in Xcode (under the added ObjectiveFlickr.xcodeproj) to the newly created Copy Files phase
  5. Drag ObjecitveFlickr.framework once again to the target's Linked Binary With Libraries group
  6. Open the Info window of your target again. Set Configuration to All Configurations, then in the Framework Search Paths property, add $(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)
  7. Use #import <ObjectiveFlickr/ObjectiveFlickr.h> in your project

Adding ObjectiveFlickr to Your iPhone App Project

Because iPhone SDK does not allow dynamically linked frameworks and bundles, we need to link against ObjectiveFlickr statically.

  1. Add ObjectiveFlickr.xcodeproj to your Mac project (from Xcode menu Project > Add to Project...)
  2. On your app target, open the info window (using Get Info on the target), then in the General tab, add ObjectiveFlickr (library) to Direct Dependencies
  3. Also, in the same window, add CFNetwork.framework to Linked Libraries
  4. Drag libObjecitveFlickr.a to the target's Linked Binary With Libraries group
  5. Open the Info window of your target again. Set Configuration to All Configurations, then in the Header Search Paths property, add these two paths, separately (<OF root> is where you checked out ObjectiveFlickr):
<OF root>/Source
<OF root>/LFWebAPIKit   
  1. Use #import "ObjectiveFlickr.h" in your project

Key Ideas and Basic Usage

ObjectiveFlickr is an asynchronous API. Because of the nature of GUI app, all ObjectiveFlickr requests are asynchronous. You make a request, then ObjectiveFlickr calls back your delegate methods and tell you if a request succeeds or fails.

ObjectiveFlickr is a minimalist framework. The framework has essentially only two classes you have to deal with: OFFlickrAPIContext and OFFlickrAPIRequest. Unlike many other Flickr API libraries, ObjectiveFlickr does not have classes like FlickrPhoto, FlickrUser, FlickrGroup or whathaveyou. You call a Flickr method, like flickr.photos.getInfo, and get back a dictionary (hash or map in other languages) containing the key-value pairs of the result. The result is directly mapped from Flickr's own XML-formatted response. Because they are already structured data, ObjectiveFlickr does not translate further into other object classes.

Because of the minimalist design, you also need to have basic understanding of how Flickr API works. Refer to http://www.flickr.com/services/api/ for the details. But basically, all you need to know is the methods you want to call, and which XML data (the key-values) Flickr will return.

Typically, to develop a Flickr app for Mac or iPhone, you need to follow the following steps:

  1. Get you Flickr API key at http://www.flickr.com/services/api/keys/apply/
  2. Create an OFFlickrAPIContext object
OFFlickrAPIContext *context = [[OFFlickrAPIContext alloc] initWithAPIKey:YOUR_KEY sharedSecret:YOUR_SHARED_SECRET];
  1. Create an OFFlickrAPIRequest object where appropriate, and set the delegate
OFFlickrAPIRequest *request = [[OFFlickrAPIRequest alloc] initWithAPIContext:context];

// set the delegate, here we assume it's the controller that's creating the request object
[request setDelegate:self];
  1. Implement the delegate methods.
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary;
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didFailWithError:(NSError *)inError;
- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest imageUploadSentBytes:(NSUInteger)inSentBytes totalBytes:(NSUInteger)inTotalBytes;
All three methods are optional ("informal protocol" in old Objective-C 
speak; optional protocol methods in newspeak). *Nota bene*: If you
are using Mac OS X 10.4 SDK, or if you are using 10.5 SDK but targeting
10.4, then the delegate methods are declared as informal protocols.
In all other cases (OS X 10.5 and above or iPhone apps), you need to
specify you are adopting the OFFlickrAPIRequestDelegate protocol. *E.g.*:
@interface MyViewController : UIViewController <OFFlickrAPIRequestDelegate>
  1. Call the Flickr API methods you want to use. Here are a few examples.

    Calling flickr.photos.getRecent with the argument per_page = 1:

[request callAPIMethodWithGET:@"flickr.photos.getRecent" arguments:[NSDictionary dictionaryWithObjectsAndKeys:@"1", @"per_page", nil]]
Quite a few Flickr methods require that you call with HTTP POST
(because those methods write or modify user data):
[request callAPIMethodWithPOST:@"flickr.photos.setMeta" arguments:[NSDictionary dictionaryWithObjectsAndKeys:photoID, @"photo_id", newTitle, @"title", newDescription, @"description", nil]];
  1. Handle the response or error in the delegate methods. If an error occurs, an NSError object is passed to the error-handling delegate method. If the error object's domain is OFFlickrAPIReturnedErrorDomain, then it's a server-side error. You can refer to Flickr's API documentation for the meaning of the error. If the domain is OFFlickrAPIRequestErrorDomain, it's client-side error, usually caused by lost network connection or transfer timeout.

    We will now talk about the response.

How to Upload a Picture

To upload a picture, create an NSInputStream object from a file path or the image data (NSData), then make the request. Here in the example we assume we already have obtained the image data in JPEG, and we set make private the uploaded picture:

NSInputStream *imageStream = [NSInputStream inputStreamWithData:imageData];
[request uploadImageStream:imageStream suggestedFilename:@"Foobar.jpg" MIMEType:@"image/jpeg" arguments:[NSDictionary dictionaryWithObjectsAndKeys:@"0", @"is_public", nil]];

Upload progress will be reported to the delegate method flickrAPIRequest:imageUploadSentBytes:totalBytes:

The reason why ObjectiveFlickr asks for an NSInputStream object as input is that we don't want to read in the whole image into memory for the preparation of upload data. With NSInputStream you have the flexibility of feeding ObjectiveFlickr an in-memory image data, a file, or even a virtualized image byte stream that comes from different (e.g. partitioned) sources.

Make sure you have read Flickr's upload API documentation so that you understand how to pick up the upload result. Please note that between the completion of uploading and the completion of the HTTP POST request itself (the moment at which you receive the response), there can be a long wait. So make sure you have a long timeout interval, especially when you upload a large image, and also design your UI accordingly.

Auth Considerations

Deprecated. The original authentication process is now deprecated by Flickr. Please refer to my blog post for the steps you need to take for the new setup.

If your app does not just read public photos, your app will need to get user permission for accessing their photos. You need to use Flickr's authentication/authorization mechanism (hereafter "auth" to cover both steps) to get the authToken for your later access.

This is, frankly, the most difficult part in using the whole Flickr API; anything that comes after that is easy and (usually) smooth. That alone is worth a whole tutorial, but I'll try to explain the essentials.

Before that, get to know Flickr's own doc here: http://www.flickr.com/services/api/misc.userauth.html.

There are two types of app auth:

There is actually a "mobile app" auth, designed for feature phones or smart phones that aren't, well, not really smart, if you buy what Apple says. But since we are talking about Mac and iPhone apps, and they aren't any ye olde mobile platform, we'll skip that one and go straight into the two major types of app auth.

Desktop App Auth, the Old Way (Deprecated)

Deprecated. The original authentication process is now deprecated by Flickr. Please refer to my blog post for the steps you need to take for the new setup.

Before, Mac developers were only interested in Desktop app auth. If you have used any Mac Flickr app before (FlickrExport, HoudahGeo, Posterino, and many others), you know how it works:

  1. Open the app
  2. The app presents a dialog box, telling you it's going to open the web browser. You log into Flickr, Flickr asks you if you grant permission to the app currently asking for your permission (read, write, or delete access).
  3. After you grant the permission, you switch back to the app, hit some "Continue" button on the app the dialog box.
  4. The app fetches the auth token from Flickr, and completes the process.

To map that into your app's internal workings, you need to do these:

  1. Call flickr.auth.getFrob
  2. After you receive the frob, pass the whole inResponseDictionary to -[OFFlickrAPIContext loginURLFromFrobDictionary:requestedPermission:] and get the returned NSURL object.
  3. Tell user that you're going to open the browser for them, prompt for action.
  4. Open the browser with the URL you just got, then wait
  5. After user completes the auth, she will click on the "Continue" button (or something like that).
  6. Your app then calls flickr.auth.getToken to get the auth token
  7. Assign the auth token to your current Flickr API context with -[OFFlickrAPIContext setAuthToken:]
  8. That's it. ObjectiveFlickr will add the auth_token argument to all your subsequent API calls, and you now have the access to all the APIs to which the user has grant you permission.

iPhone App Auth and the New Way (Deprecated)

Deprecated. The original authentication process is now deprecated by Flickr. Please refer to my blog post for the steps you need to take for the new setup.

iPhone and iPod Touch posed a challenge to the auth model above: Opening up Mobile Safari then ask the forgetful user to come back is a bad idea.

So many iPhone developers have come up with this brilliant idea: Use URL scheme to launch your app. It turns out that Flickr's web app auth serves the idea well. Here is how it works:

  1. The app prompts user that it's going to open up browser to ask for permission.
  2. The user taps some "Open" button, and the app closes, Mobile Safari pops up with Flickr's login (and then app auth) page.
  3. Then magically, Mobile Safari closes, and the app is launched again.
  4. There's no Step 4.

What's behind the scene is that the iPhone app in question has registered a URL scheme, for example someapp:// in its Info.plist and the app developer has configured their Flickr API key, so that when the user grants the app permission, Flickr will redirect the web page to that URL the app developer has previously designated. Mobile Safari opens that URL, and then the app is launched.

In fact, Mac app can do that, too!

Here's what you need to do:

  1. Register the URL scheme. Take a look at my own SnapAndRun-iPhone example app's SnapAndRun-Info.plist and this CocoaDev article for details.
  2. Configure your Flickr API key so that the callback URL is set to that URL scheme.
  3. Get a login URL by calling -[OFFlickrAPIContext loginURLFromFrobDictionary:requestedPermission:], note that you don't need to have a frob dictionary for getting web app login (auth) URL, so just pass nil. You still need to pass the permission argument, of course.
  4. Now, in your app launch URL handler (Mac and iPhone apps do it differently, see Apple doc for details), get the frob that Flickr has passed to you with the URL.
  5. Your app then calls flickr.auth.getToken to get the auth token
  6. Assign the auth token to your current Flickr API context with -[OFFlickrAPIContext setAuthToken:]
  7. That's it. ObjectiveFlickr will add the auth_token argument to all your subsequent API calls, and you know have the access to all the APIs to which the user has grant you permission.

Now you have done the most difficult part of using the Flickr API.

How Flickr's XML Responses Are Mapped Back

Flickr's default response format is XML. You can opt for JSON. Whichever format you choose, the gist is that they are already structured data. When I first started designing ObjectiveFlickr, I found it unnecessary to create another layer of code that maps those data to and from "native" objects. So we don't have things like OFFlickrPhoto or OFFlickrGroup. In essence, when an request object receives a response, it maps the XML into a data structure consisting of NSDictionary's, NSArray's and NSString's. In Apple speak, this is known as "property list". And we'll use that term to describe the mapped result. You then read out in the property list the key-value pairs you're interested in.

ObjectiveFlickr uses the XML format to minimize dependency. It parses the XML with NSXMLParser, which is available on all Apple platforms. It maps XML to property list following the three simple rules:

  1. All XML tag properties are mapped to NSDictionary key-value pairs
  2. Text node (e.g. <photoid>12345</photoid>) is mapped as a dictionary containing the key OFXMLTextContentKey (a string const) with its value being the text content.
  3. ObjectiveFlickr knows when to translate arrays. We'll see how this is done now.

So, for example, this is a sample response from flickr.auth.checkToken

<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
<auth>
	<token>aaaabbbb123456789-1234567812345678</token>
	<perms>write</perms>
	<user nsid="00000000@N00" username="foobar" fullname="blah" />
</auth>
</rsp>

Then in your flickrAPIRequest:didCompleteWithResponse: delegate method, if you dump the received response (an NSDictionary object) with NSLog, you'll see something like (extraneous parts omitted):

{
    auth ={
        perms = { "_text" = write };
        token = { "_text" = "aaaabbbb123456789-1234567812345678"; };
        user = {
            fullname = "blah";
            nsid = "00000000@N00";
            username = foobar;
        };
    };
    stat = ok;
}

So, say, if we are interested in the retrieved auth token, we can do this:

NSString *authToken = [[inResponseDictionary valueForKeyPath:@"auth.token"] textContent];

Here, our own -[NSDictionary textContent] is simply a convenient method that is equivalent to calling [authToken objectForKey:OFXMLTextContentKey] in our example.

Here is another example returned by flickr.photos.getRecent:

<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
<photos page="1" pages="334" perpage="3" total="1000">
	<photo id="3444583634" owner="37096380@N08" secret="7bbc902132" server="3306" farm="4" title="studio_53_1" ispublic="1" isfriend="0" isfamily="0" />
	<photo id="3444583618" owner="27122598@N06" secret="cc76db8cf8" server="3327" farm="4" title="IMG_6830" ispublic="1" isfriend="0" isfamily="0" />
	<photo id="3444583616" owner="26073312@N08" secret="e132988dc3" server="3376" farm="4" title="Cidade Baixa" ispublic="1" isfriend="0" isfamily="0" />
</photos>
</rsp>

And the mapped property list looks like:

{
    photos = {
        page = 1;
        pages = 334;
        perpage = 3;
        photo = (
            {
                farm = 4;
                id = 3444583634;
                isfamily = 0;
                isfriend = 0;
                ispublic = 1;
                owner = "37096380@N08";
                secret = 7bbc902132;
                server = 3306;
                title = "studio_53_1";
            },
            {
                farm = 4;
                id = 3444583618;
                /* ... */
            },
            {
                farm = 4;
                id = 3444583616;
                /* ... */
            }
        );
        total = 1000;
    };
    stat = ok;
}

ObjectiveFlickr knows to translate the enclosed tags in the plural tag into an NSArray. So if you want to retrieve the second photo in the array, you can do this:

NSDictionary *photoDict = [[inResponseDictionary valueForKeyPath:@"photos.photo"] objectAtIndex:1];

Then, with two helper methods from OFFlickrAPIContext, you can get the static photo source URL and the photo's original web page URL:

NSURL *staticPhotoURL = [flickrContext photoSourceURLFromDictionary:photoDict size:OFFlickrSmallSize];
NSURL *photoSourcePage = [flickrContext photoWebPageURLFromDictionary:photoDict];

Do remember that Flickr requires you present a link to the photo's web page wherever you show the photo in your app. So design your UI accordingly.

Wacky XML Mappings

Unfortunately, there are some Flickr responses that don't rigorously follow the "plural tag == array" rule. Consider the following snippet (tag attributes removed to highlight the issue at hand), from the API method flickr.activity.userPhotos:

<rsp stat="ok">
<items page="1" pages="1" perpage="50" total="3">
	<item type="photo">
		<title>Snap and Run Demo</title>
		<activity>
			<event type="comment">double comment 1</event>
			<event type="comment">double comment 2</event>
		</activity>
	</item>
	<item type="photo">
		<title>Snap and Run Demo</title>
		<activity>
			<event type="comment">test comment 1</event>
		</activity>
	</item>
</items>
</rsp>

Note how the <activity> tag can enclose either one or more <event> tags. This is actually a gray area of Flickr API and I'm not entirely sure if I should write that exception into the book (i.e. the logic of OFXMLMapper, which handles the job). The list of exceptions could never be comprehensive.

We can make good use of Objective-C's dynamic nature to work around the problem. We can tell if it's an array:

// get the first element in the items
NSArray *itemArray = [responseDict valueForKeyPath:@"items.item"];
NSDictionary *firstItem = [itemArray objectAtIndex:0];

// get the "event" element and see if it's an array
id event = [firstItem valueForKeyPath:@"activity.event"];
    
if ([event isKindOfClass:[NSArray class]]) {
    // it has more than one elements
    NSDictionary *someEvent = [event objectAtIndex:0];
}
else {
    // that's the only element
    NSDictionary *someEvent = event;
}

On the other hand, the reason why we build the plural tag rule in OFXMLMapper is that writing the boilerplate above for frequently-used tags again and again is very tedious. Since OFXMLMapper already handles the plural tags, the borderline cases are easier to tackle.

Design Patterns and Tidbits

Design Your Own Trampolines

OFFlickrAPIRequest has a sessionInfo property that you can use to provide state information of your app. However, it will soon become tedious to write tons of if-elses in the delegate methods. My experience is that I design a customized "session" object with three properties: delegate (that doesn't have to be the originator of the request), selector to call on completion, selector to call on error. Then the delegate methods for OFFlickrAPIRequest simply dispatches the callbacks according to the session object.

If your controller calls a number of Flickr methods or involves multiple stages/states, this design pattern will be helpful.

Thread-Safety

Each OFFlickrAPIRequest object can be used in the thread on which it is created. Do not pass them across threads. Delegate methods are also called in the thread in which the request object is running.

CFNetwork-Based

ObjectiveFlickr uses LFHTTPRequest, which uses only the CFNetwork stack. NSURLConnection is reported to have its own headaches. On the other hand, LFHTTPRequest does not handle non-HTTP URLs (it does handle HTTPS with a catch: on iPhone you cannot use untrusted root certs) and does not do HTTP authentication. It also does not manage caching. For web API integration, however, LFHTTPRequest provides a lean way of making and managing requests.

One side note: LFHTTPRequest will use your system's shared proxy settings on your Mac or iPhone. This is how it requires SystemConfiguration.framework on Mac when being built alone.

Possible Migration Path from ObjectiveFlickr 0.9.x

I didn't really seriously investigate this, but here are some thoughts:

  • In theory 0.9.x and 2.0 should co-exist as there is no class name clashes.
  • OFFlickrContext becomes OFFlickrAPIContext
  • OFFlickrInvocation becomes OFFlickrAPIRequest
  • OFFlickrUploader is now merged into OFFlickrAPIRequest
  • Delegate methods are greatly simplified and redesigned

History

ObjectiveFlickr was first released in late 2006. The previous version, 0.9.x, has undergone one rewrite and is hosted on Google Code. It also has a Ruby version available as a Ruby gem.

The present rewrite derives from the experiences that I have had in developing Mac and iPhone products (I run my own company, Lithoglyph). It's a great learning process.

Acknowledgements

Many people have given kind suggestions and directions to the development of ObjectiveFlickr. And there are a number of Mac apps that use it. I'd like to thank Mathieu Tozer, Tristan O'Tierney, Christoph Priebe, Yung-Lun Lan, and Pierre Bernard for the feedbacks that eventually lead to the framework's present design and shape.

Copyright and Software License

ObjectiveFlickr Copyright (c) 2006-2009 Lukhnos D. Liu.

LFWebAPIKit Copyright (c) 2007-2009 Lukhnos D. Liu and Lithoglyph Inc.

One test in LFWebAPIKit (Tests/StreamedBodySendingTest) makes use of Google Toolbox for Mac, Copyright (c) 2008 Google Inc. Refer to COPYING.txt in the directory for the full text of the Apache License, Version 2.0, under which the said software is licensed.

Both ObjectiveFlickr and LFWebAPIKit are released under the MIT license, the full text of which is printed here as follows. You can also find the text at: https://opensource.org/licenses/mit-license.php

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Contact

  • lukhnos {at} lukhnos {dot} org

Links

Comments
  • Authentication issue with snapandrun

    Authentication issue with snapandrun

    Hi,

    I am trying to execute iphone snapandrun, its taking me to the login page but after that its not passing teh access token. It still at the authenticating message.

    Any help is appreciated.

    Thanks, Swetha.

    opened by sweetie85 33
  • how to upload image in flickr

    how to upload image in flickr

            var context :OFFlickrAPIContext = OFFlickrAPIContext(APIKey:  Flickr["consumerKey"], sharedSecret:  Flickr["consumerKey"])
    
            var request : OFFlickrAPIRequest  = OFFlickrAPIRequest(APIContext: context)
    
            request.delegate = self
    
            var imagedta = UIImageJPEGRepresentation(self.m_ShareImage, 0.5)
            var imageStream : NSInputStream = NSInputStream(data: imagedta)
            request.uploadImageStream(imageStream, suggestedFilename: "footer.jpg", MIMEType: "image/jpeg", arguments: NSDictionary(objectsAndKeys:"1","is_public") as [NSObject : AnyObject])
    

    i am using this but not working not posted

    opened by ArjunSa786 16
  • added compiler flag to get project to compile with xcode 3.2.4

    added compiler flag to get project to compile with xcode 3.2.4

    I added the following to Other C Flags in your project's build settings: -D__IPHONE_OS_VERSION_MIN_REQUIRED=040100

    This addresses a bug in LLVM. See

    See http://stackoverflow.com/questions/3677879/strange-issue-after-upgrading-to-ios-4-1-sdk

    opened by boxerab 5
  • Multiple crashes are happening  in LFHTTPRequest.m

    Multiple crashes are happening in LFHTTPRequest.m

    I am getting multiple crash reports from users, that are confined inside LFHTTPRequest.

    One of them is below at line 191 of LFHTTPRequest.m file. This is related to a request timing out.

    0 libobjc.A.dylib objc_msgSend + 15 1 My App LFHTTPRequest.m line 191 -[LFHTTPRequest(PrivateMethods) handleRequestMessageBodyTrackerTick:] + 191 2 ... Foundation NSFireTimer + 62 3 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION + 14 4 CoreFoundation __CFRunLoopDoTimer + 272 5 CoreFoundation __CFRunLoopRun + 1232 6 CoreFoundation CFRunLoopRunSpecific + 356 7 CoreFoundation CFRunLoopRunInMode + 104 8 GraphicsServices GSEventRunModal + 74 9 UIKit UIApplicationMain + 1120 10 My App main.m line 13 main + 13

    Another one is happening at line 772 of LFHTTPRequest.m file. This seems to happen when errors occurred on read input stream.

    0 libobjc.A.dylib objc_msgSend + 15 1 My App LFHTTPRequest.m line 772 LFHRReadStreamClientCallBack + 772 2 CoreFoundation _signalEventSync + 74 3 CoreFoundation _cfstream_solo_signalEventSync + 74 4 CoreFoundation _CFStreamSignalEvent + 326 5 CFNetwork CoreReadStreamCFStreamSupport::coreStreamReadEvent(_CoreReadStream, unsigned long) + 98 6 CFNetwork CoreReadStreamClient::coreStreamEventsAvailable(unsigned long) + 34 7 CFNetwork CoreStreamBase::_callClientNow() + 46 8 CFNetwork CoreStreamBase::_streamSetEventAndScheduleDelivery(unsigned long, unsigned char) + 84 9 CFNetwork CoreStreamBase::streamInterface_SignalEvent(unsigned long, CFStreamError const) + 34 10 CFNetwork HTTPReadStream::selfSignalEvent(unsigned long, CFStreamError const*) + 324 11 CFNetwork HTTPReadStream::streamEvent(unsigned long) + 156 12 CFNetwork CoreReadStreamClient::coreStreamEventsAvailable(unsigned long) + 34 13 CFNetwork CoreStreamBase::_callClientNow() + 46 14 ... CoreFoundation CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 14 15 CoreFoundation __CFRunLoopDoSources0 + 212 16 CoreFoundation __CFRunLoopRun + 646 17 CoreFoundation CFRunLoopRunSpecific + 356 18 CoreFoundation CFRunLoopRunInMode + 104 19 GraphicsServices GSEventRunModal + 74 20 UIKit UIApplicationMain + 1120 21 My App main.m line 13 main + 13

    opened by tmandal 4
  • changed OFGenerateUUIDString to take void arguments for ios compilation

    changed OFGenerateUUIDString to take void arguments for ios compilation

    Using XCode 4.3.1 (LLVM 3.1) for ios was generating warnings as noted below. passing void as the argument removed that warning.

    Submodules/ShareKit/Classes/ShareKit/Sharers/Services/Flickr/../../../../../Submodules/objectiveflickr/Source/OFUtilities.m:68:11: warning: no previous prototype for function 'OFGenerateUUIDString' [-Wmissing-prototypes] NSString *OFGenerateUUIDString() ^ 1 warning generated.

    opened by matthewchung 4
  • Crashes in readStreamHasBytesAvailable, when quickly sent multi-requests

    Crashes in readStreamHasBytesAvailable, when quickly sent multi-requests

    This happened to me every time, I sent multi-requests during testing user double tapping or crazy-tapping.

    It crashes in readStreamHasBytesAvailable, when quickly sent multi-requests.

    Does any one has or know a solution about this?

    Thank you for your helping.

    opened by bigdreamkid 4
  • Problems building on XCode 4?

    Problems building on XCode 4?

    Hi, this could well be a noob question, but I would appreciate any help.
    I've got a clean install on XCode 4 and clean download of example projects but simply cannot seem to get SnapAndRun to build. ( I've tried all sorts of Project / Target settings etc but only succeeded in confusing myself.

    Should I need to do/change anything from a clean install for it to work? I'd appreciate any advice. cheers

    opened by itsalldoable 4
  • Builds in Xcode 3, 2 errors in Xcode 4...

    Builds in Xcode 3, 2 errors in Xcode 4...

    Hi,

    I have tried many times to add Objectiveflickr to my iPhone project in Xcode 4, but finally decides to go back to Xcode 3 to do it. And it compiled just fine the first time !

    So I decided to open it with Xcode 4, and tried to build there, but guess what... 2 compile errors... however, everything seems to be setup.

    So here are the errors :

    ld: warning: ignoring file /Users/Moi/_Yamm/developpement/Projets/Photo_Library/Photo Library/DerivedData/Photo Library/Build/Products/Debug-iphonesimulator/libObjectiveFlickr.a, file was built for archive which is not the architecture being linked (i386)
    Undefined symbols for architecture i386:
      "_OFFlickrWritePermission", referenced from:
          -[AuthenticationViewController authorizeAction] in AuthenticationViewController.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    And here is a screenshot of my project configuration :

    http://grab.by/a7ma

    Did anybody experience such errors and finally find a solution ? I have already tried to look at the SnapAndRun project (which builds correct in Xcode 4) but it still fails...

    In the meanwhile I will stick in Xcode 3....

    Best regards,

    opened by rogmabi 3
  • Set Configuration to All Configurations

    Set Configuration to All Configurations

    I am not able to understand this line. Kindly elaborate. Header Path is fine.

    1. Open the Info window of your target again. "Set Configuration to All Configurations", then in the Header Search Paths property.....
    opened by grisleyb 2
  • Invalid signature error

    Invalid signature error

    On the third step of authorization, I get this error:

    OAuthError = "oauth_problem=signature_invalid&debug_sbs=GET&https%3A%2F%2Fwww.flickr.com%2Fservices%2Foauth%2Faccess_token&oauth_consumer_key%3De2134b851206e39ddf4557ca0f26f884%26oauth_nonce%3D250C6C6F%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1411473474%26oauth_token%3D72157647926673261-49fc322682ce1b7a%26oauth_verifier%3Df93c576d4c4b50a1%26oauth_version%3D1.0";

    At the third step, I am doing this:

    • (void)flickrDidLoginWithCredentials:(NSURL *)url { NSString *token = nil; NSString *verifier = nil;

      BOOL result = OFExtractOAuthCallback(url, [NSURL URLWithString:@"flickrtesturl://auth"], &token, &verifier);

      if (!result) { NSLog(@"Cannot obtain token/secret from URL: %@", [url absoluteString]); }

      [self.flickrRequest fetchOAuthAccessTokenWithRequestToken:token verifier:verifier]; }

    Also, I checked my URL is "flickrtesturl://auth?oauth_token=72157647926673261-49fc322682ce1b7a&oauth_verifier=f93c576d4c4b50a1"

    and token and verifier variables have values too. Kindly suggest something...

    opened by grisleyb 2
  • Https support

    Https support

    As we know. Flickr just required developer to use https to access all their API.(6 days ago)

    all my application stopped working. And I was a bit busy because of family issues this months

    Is there anyone working on this?, or please can someone working on this.

    Thanks

    opened by rheza 2
  •  Flickr authentication fails in second time

    Flickr authentication fails in second time

    I need to authenticate the flickr in my project. I have integrate the "Snap And Run" in my project. I am trying to run my project on Device. Its working fine..the first time onwards the flickr login screen will follow the gmail and yahoo credentials. But, when I am deleting the instance of my app or again re-installed the app my flickr authentication is not showing for using the gmail credentials. What should I do to get gmail login details in second attempt?

    opened by vasuippili 0
  • Why the delegate for OS X but the category for iOS?

    Why the delegate for OS X but the category for iOS?

    I would love to have this explained? Why not simply use a delegate in iOS?

    if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4

    @protocol OFFlickrAPIRequestDelegate @optional

    else

    @interface NSObject (OFFlickrAPIRequestDelegateCategory)

    Note that it now breaks building for simulator with Xocde 4.5.

    opened by postmechanical 0
  • uploading an album

    uploading an album

    I have understood the snap and run sample project code and how it works, however, how can I use the same code to upload a folder that contains 3 images to Flickr ?

    thank you in advance.

    opened by murad1981 0
  • Arguments to didObtainOAuthAccessToken are not URL decoded

    Arguments to didObtainOAuthAccessToken are not URL decoded

    I've noticed that the args (token, username, nsid, etc.) passed to the didObtainOAuthAccessToken delegate method still need URL decoding as they contain percent escaped characters.

    opened by mwaterfall 0
  • Crash in readStreamHasBytesAvailable in arc project following set up instruction

    Crash in readStreamHasBytesAvailable in arc project following set up instruction

    I created a brand new projection Xcode 4.3.2 set type to iphone arc project set project type to single view in the controller:

    in .h file @property (nonatomic, strong) OFFlickrAPIContext *context;

    in .m file

    • (void) viewWillAppear:(BOOL)animated {

      // Do any additional setup after loading the view, typically from a nib.

      self.context = [[OFFlickrAPIContext alloc] initWithAPIKey:@"6903cd1cb6a4bc92e906b76d60c34f63" sharedSecret:@"4055df0dfc06e60f"];

      OFFlickrAPIRequest *request = [[OFFlickrAPIRequest alloc] initWithAPIContext:_context];

      // set the delegate, here we assume it's the controller that's creating the request object [request setDelegate:self];

      NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity: 5]; [params setObject:@"2000-01-01 00:00:00" forKey:@"max_taken_date"]; [params setObject:@"47.60569" forKey:@"lat"]; [params setObject:@"-122.338561" forKey:@"lon"]; [params setObject:@"date_taken" forKey:@"date_taken"];

      [request callAPIMethodWithGET:@"flickr.photos.search" }

    run the app in simulator => app crash, in LFHTTPrequest::readStreamHasBytesAvailable on line 215 _delegate is pointing to a dead pointer

    opened by otusweb 5
Owner
Lukhnos Liu
Lukhnos Liu
Giphy API client for iOS in Objective-C

Giphy-iOS Giphy-iOS is a Giphy API client for iOS in Objective-C. Usage To run the example project, clone the repo, and run pod install from the Examp

alex choi 52 Jul 11, 2019
An easy-to-use Objective-C wrapper for the Uber API (no longer supported)

UberKit UberKit is a simple Objective-C wrapper for the new Uber API . Installation Cocoapods UberKit is available through Cocoapods. To install it, s

Sachin Kesiraju 95 Jun 30, 2022
A Dropbox v2 client library written in Objective-C

TJDropbox TJDropbox is a Dropbox v2 client library written in Objective-C. When Dropbox originally announced their v2 API they included only a Swift c

Tim Johnsen 61 Dec 21, 2022
A Slack API Client for the Perfect Server-Side Swift Framework

PerfectSlackAPIClient is an API Client to access the Slack API from your Perfect Server Side Swift application. It is build on top of PerfectAPIClient

Cap.雪ノ下八幡 2 Dec 1, 2019
Twitter API for Cocoa developers

FHSTwitterEngine Twitter API for Cocoa developers Created by Nathaniel Symer FHSTwitterEngine can: Authenticate using OAuth and/or xAuth. Make a reque

Nathaniel Symer 213 Jul 8, 2022
Unofficial Dribbble iOS wrapper allows you to integrate Dribble API into iOS application (Designer, Shot, Comment, User Story, Like, Follow)

DribbbleSDK DribbbleSDK is easy-to-use iOS wrapper for Dribbble SDK. We're working hard to complete the full coverage of available methods and make th

Agilie Team 74 Dec 2, 2020
A Swift wrapper for Foursquare API. iOS and OSX.

Das Quadrat Das Quadrat is Foursquare API wrapper written in Swift. Features Supports iOS and OSX. Covers all API endpoints. Authorization process imp

Constantine Fry 171 Jun 18, 2022
Unofficial GitHub API client in Swift

Github.swift ❤️ Support my apps ❤️ Push Hero - pure Swift native macOS application to test push notifications PastePal - Pasteboard, note and shortcut

Khoa 184 Nov 25, 2022
Unified API Library for: Cloud Storage, Social Log-In, Social Interaction, Payment, Email, SMS, POIs, Video & Messaging.

Unified API Library for: Cloud Storage, Social Log-In, Social Interaction, Payment, Email, SMS, POIs, Video & Messaging. Included services are Dropbox, Google Drive, OneDrive, OneDrive for Business, Box, Egnyte, PayPal, Stripe, Google Places, Foursquare, Yelp, YouTube, Vimeo, Twitch, Facebook Messenger, Telegram, Line, Viber, Facebook, GitHub, Google+, LinkedIn, Slack, Twitter, Windows Live, Yahoo, Mailjet, Sendgrid, Twilio, Nexmo, Twizo.

CloudRail 195 Nov 29, 2021
A swift SDK for Medium's OAuth2 API

Medium SDK - Swift A library to allow access to Medium API for any Swift iOS application. Features Medium.com authorization & token handling Login sta

null 11 Jan 22, 2022
An Elegant Spotify Web API Library Written in Swift for iOS and macOS

Written in Swift 4.2 Spartan is a lightweight, elegant, and easy to use Spotify Web API wrapper library for iOS and macOS written in Swift 3. Under th

Dalton Hinterscher 107 Nov 8, 2022
Swift Wrapper For Bittrex API

BittrexApiKit Swift client for Bittrex api. It support all APIs with most recent changes. more info here let api = Bittrex(apikey: "api key", secretke

Saeid 8 Apr 5, 2021
Easy and powerful way to interact with VK API for iOS and macOS

Easy and powerful way to interact with VK API for iOS and macOS. Key features ?? It's not ios-vk-sdk ?? ?? One library for iOS and mac OS ?? ?? Fully

null 260 Dec 22, 2022
Instagram API client written in Swift

SwiftInstagram is a wrapper for the Instagram API written in Swift. It allows you to authenticate users and request data from Instagram effortlessly.

Ander Goig 579 Dec 31, 2022
An API wrapper for bitFlyer.

SwiftFlyer An API wrapper for bitFlyer that supports all providing API. API Document https://lightning.bitflyer.jp/docs Usage Public API Fetch a marke

Ryo Ishikawa 39 Nov 3, 2022
A Swift library for the Forecast.io Dark Sky API

Requirements To use ForecastIO, all you need is an API key for the Dark Sky API. ForecastIO supports iOS (≥9.0), macOS (≥10.10), watchOS (≥2.0), and t

Satyam Ghodasara 163 Jul 26, 2022
A clima based app with use of API

Clima Our Goal It’s time to take our app development skills to the next level. We’re going to introduce you to the wonderful world of Application Prog

null 0 Nov 28, 2021
Questrade API written in Swift.

QuestradeAPI Getting Started The QuestAPI is made up of two main concepts: ResponseProviders API ResponseProviders The job of the provider is to retur

Eli Slade 2 Mar 15, 2022
Make API Calls using SwiftUI

SwiftUIApICall Make API Calls using SwiftUI This is a simple app for maing API C

Abdulaziz M. Ghaleb 0 Dec 18, 2021