GithubHelp home page GithubHelp logo

restkit / restkit Goto Github PK

View Code? Open in Web Editor NEW
10.2K 414.0 2.1K 42.47 MB

RestKit is a framework for consuming and modeling RESTful web resources on iOS and OS X

License: Apache License 2.0

Objective-C 98.88% C 0.22% Ruby 0.85% Objective-C++ 0.04% Shell 0.01%

restkit's Issues

Delete Request Passing Paramaters

When using deleteObject the object manager sends paramaters with the request. I believe this causes rails to raise an InvalidAuthenticityToken error - at least on my development server running Rails 3.0.3.

Are there situations where you would want to pass paramaters with a DELETE request?

Ensure no nil values are mapped by specifying the object class

From the mailing list:


My object properties were also all (null) when I provided an
objectClass to loadObjectsAtResourcePath, but worked fine without it.
This is when I registered the class with the RKObjectMapper. If I
didn't register the class with the ObjectMapper and passed in the
class for objectClass, it still gave me nil values.

On Apr 23, 3:28 pm, Blake Watters <[email protected]> wrote:
> Hi Jon -
>
> Glad that you got things sorted out. The mapping really shouldn't fail out
> if you supply the target class for a registered object. I've opened an issue
> in Github to cover that edge.
>
> On Sat, Apr 23, 2011 at 10:05 AM, Jon Phillips
> <[email protected]>wrote:
>
> > OK, final email ... sorry for the bother, but if it's helpful to
> > anyone else.
>
> > I thought I was doing good things in my loadObjectsAtResourcePath call
> > by including the class to map it to. But I didn't need it because my
> > json includes the key that is the class. Because I included the class,
> > the elements dictionary included the class name key, which messed
> > stuff up.
>
> > Upshot = if you're outputting standard JSON from Rails, RestKit is
> > smart enough to figure out the class you're mapping and you don't have
> > to tell it.  In fact, apparently, you shouldn't tell it?
>
>  *Blake Watters*
> Two Toasters | CTO
> [email protected]
> (919) 926-8537

Crash in RKObjectMapper element comparison (more error handling)

When some objects in JSON have a null property and other objects have a string for that property, they complexify the mapping and our comparison here breaks trying to compare an NSNumber to an NSString ([NSNumber isEqualToString:] unrecognized selector). This addition will evaluate the class and force a property setting if its' different.

diff ./RKObjectMapper.m ../0.9/RKObjectMapper.m
316,323d315
<       if (![currentValue isKindOfClass:[propertyValue class]])
<       {
<           if (![currentValue isEqual:propertyValue] || ![[currentValue description] isEqualToString:[propertyValue description]]) {
<               [model setValue:propertyValue forKey:propertyName];
<               return;
<           }
<           
<       }
389c381
<         if (!modelClass || [modelClass isKindOfClass: [NSNull class]]) {

---
>         if ([modelClass isKindOfClass: [NSNull class]]) {

RKSpecResponseLoader Returns Control Too Soon

When testing using the RKSpecResponseLoader, if you are using an object loader control is returned to the test case when didLoadResponse: or didFailLoadWithError: is invoked by the framework.

We need to inspect the type of the request and defer returning control if this is an object loader.

Remote Services Expect a File Name to be Set

RKParamsAttachment does not currently initialize a filename for attached parameters. This causes issues as remote services expect one to be set. Initialize it to an empty string instead of nil.

Setup instructions not correct?

I had to check the libRestKitCoreData.a file to get things to compile successfully. That is, it is apparently not optional. The error is:

"_OBJC_CLASS_$_RKManagedObject", referenced from:
objc-class-ref-to-RKManagedObject in libRestKitObjectMapping.a(RKObjectLoader.o)
objc-class-ref-to-RKManagedObject in libRestKitObjectMapping.a(RKObjectMapper.o)
ld: symbol(s) not found

Mapping to Registered Types Fails when Object Class Supplied to Object Loader

From the mailing list:

On Sat, Apr 23, 2011 at 10:05 AM, Jon Phillips [email protected] wrote:
OK, final email ... sorry for the bother, but if it's helpful to anyone else.

I thought I was doing good things in my loadObjectsAtResourcePath call
by including the class to map it to. But I didn't need it because my
json includes the key that is the class. Because I included the class,
the elements dictionary included the class name key, which messed
stuff up.

Upshot = if you're outputting standard JSON from Rails, RestKit is
smart enough to figure out the class you're mapping and you don't have
to tell it. In fact, apparently, you shouldn't tell it?

Support Automatic Submission Tracking

A lot of people would like to be able to automatically track object status (i.e. does it exist local only or on the server). We should architect this into the framework:

Hi there,

Thus far I've got my application working more or less correctly using
Restkit. I've followed some of the examples provided.

In the example given by the discussion app the following occurs. An
instance of a post object is created, assigned some data and then
eventually posted. I.e. Something to the effect of:

       DBPost *post = [DBPost object];
       post.topicID = topic.topicID;
       post.body = bodyTextEditor.text;
       [[RKObjectManager sharedManager] postObject:post delegate:self];

Now should an error occur during transmission we end up with a post
that is stored locally in sqlite but not on the server.

What is the best approach to handle this?

Should all models that get transmitted require some sort of flag to
indicate whether or not they have been sent?  (This could then be
combined with some routine to pick up "unsent" data and resubmit it.)

I've also read some mention of using temporary managedObjectContexts.
Is this a better alternative?

What do you suggest to solve these kinds of problems?

Any help on this would be fantastic.

Thanks in advance,
Matt

Create RKCatalog Example

Create an integrated example application pulling together the code samples from the Advanced MobileTuts article:

  • RKParamsExample
  • RKRequestQueueExample
  • RKReachabilityExample
  • RKBackgroundRequestExample
  • RKAdvancedMappingExample (Better Name??) KeyValueMappingExample???
  • RKRelationshipMappingExample
  • RKCoreDataExample
  • RKRailsExample

Support Supplying Temporary Object Contexts

I have a UI that lets a user create a new object. They can hit Save to
upload the object or Cancel to abandon it. I'm used to the pattern
where you create a temporary managed object context for this purpose.
If the user cancels, you simply get rid of the temporary context and
the object is forgotten. However, I can't seem to do this in RestKit.
If I create a temporary context, RestKit is unaware of that context
and doesn't save my object. The offending code is in
RKManagedObjectLoader handleTargetObject. It performs a save, but on
the default context, not my temporary one. My object actually gets
uploaded, but processLoadModelsInBackground doesn't catch the changes
because my object still has a temporary object ID (since its context
didn't get saved).

I use the same logic for editing an existing object. However, that
path seems to work OK. I guess because even though my temporary
context doesn't get saved, the existing object has a permanent object
ID and hence processLoadModelsInBackground is able to find the object
and update it.

Is there a better pattern for doing this?


Mark -

In most of my UI's we've just had the state set on controls in the UI rather than heading back to the model, save causes the state to be read from the controls, set on the object, and then the put/postObject call is dispatched. Cancel button just pops the view so no write-through occurs. I suspect that what you are doing could be easily supported if we provide a mechanism for supplying the object loader with a managed object context from the main application. It may be enough just to expose a read/write property for the object context and initialize it to a thread-local one if its nil.

  • Blake

RKRequestTTModel does not use core data as authoritative data source

If a programmer is using core data then it should be the authoritative data store for the application.

RKRequestTTModel modelsDidLoad:(NSArray*)models sets the underlying model to the array of objects that has just been received. Instead it should check to see if there is a core data backing and use it if it is available.

This allows the programmer to include their own rules for updating local objects (ie locally created objects or other synchronization strategies)

Something like the following should work:

- (void)modelsDidLoad:(NSArray*)models {
    RKManagedObjectStore* store = [RKObjectManager sharedManager].objectStore;
    NSArray* fetchRequests = nil;
    NSArray* allKnownObjects = nil;
    if (store.managedObjectCache) {
        fetchRequests = [store.managedObjectCache fetchRequestsForResourcePath:self.resourcePath];
        allKnownObjects = [RKManagedObject objectsWithFetchRequests:fetchRequests];
    } else {
        allKnownObjects = models;
    }


    [_objects release];
    _objects = nil;

    _objects = [allKnownObjects retain];
    _isLoaded = YES;

    [self didFinishLoad];
 }

Nested object types must be explicitly registered

Example JSON:


{
  "field1" : "value1",
  "object_field1" : {
   "field2": "value2"
  },
  "object_array" : [
  {"field3":"value3"}
  ]
}

In this case the type of "object_field1" and the type of the objects in "object_array" need to be explicitly registered with registerClass:forElementNamed:, otherwise these types won't be resolved and the instance variables won't be set.

RestKit version: 0.9.1.1
Xcode version: 4.0.1/4A1006

RKObjectMapper removes relationship objects if no relationship property sent in JSON

In the 0.9 branch around line 390, RKObjectMapper attempts to update or create the modelClass from a dictionary of childElements in relationshipElements.

In the case that relationshipElements does not exist, i.e that relationship property wasn't passed in the JSON yet it still exists, relationshipElements will be nil, children will be an empty NSSet or NSArray, and [object setValue:children forKey:propertyName] on line 406 will destroy any currently associated objects.

I believe this is fixed on the core-data-cleanup branch but has not been merged in, but please let me know if my assumptions are incorrect.

RKObjectLoader sends RKRequestDidLoadResponseNotification twice

The call to [super didFinishLoad:response] in the (void)didFinishLoad:(RKResponse*)response implementation on RKObjectLoader results in the RKRequestDidLoadResponseNotification being sent twice for a single RKObjectLoader. This has a side effect of reducing _totalLoading in RKRequestQueue twice for a single request, and thus messing up the enforcement of the RKRequestQueue's max loading count.

It seems that removing to call to super in RKObjectLoader's void)didFinishLoad:(RKResponse*)response method addresses the issue, although I've only tested this fix in a limited number of cases.

Exception in RKManagedObjectStore's deletePersistantStore

Hi,

In deletePersistantStore you are doing this:

NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary];
[threadDictionary setObject:nil forKey:kRKManagedObjectContextKey];

However dictionaries don't allow you to set nil for a key. You should change this to:

NSMutableDictionary* threadDictionary = [[NSThread currentThread] threadDictionary];
[threadDictionary removeObjectForKey:kRKManagedObjectContextKey];

From the NSMutableDictionary documentation:

Raises an NSInvalidArgumentException if aKey or anObject is nil. If you need to represent a nil value in the dictionary, use NSNull.

RKObjectMapper does not support NSURL

Problem

If the model object has a NSURL property that is mapped with RestKit, the RKObjectMapper will not attempt to turn the JSON string into an NSURL object.

Workaround

To work around this problem, we had to create a KVC compliant NSString property that does the NSURL conversion for us. RestKit will set the string property, and our custom setter creates and sets the actual URL property. This is less than ideal

Suggested Fixes

  • Factor out the type conversion in RKObjectMapper into a method that subclasses can easily override. We could have made a custom subclass of the object mapper and included our URL logic there.
  • Make the type conversion more object-oriented and allow third-party code to register new "converters." This is more complicated but may be more correct.

Add Support for Encoding resourcePaths to Avoid Crashes with UTF-8 Characters

Hey guys,

Today I was working with "/places.json?category=Automóviles" as
resourcePath and got EXEC_BAD_ACCESS at RKURL.m

    - (id)initWithBaseURLString:(NSString*)baseURLString resourcePath:
    (NSString*)resourcePath

    and found out that NSURL cannot be initialized with non-ASCII
    characters, so I fixed this using NSUTF8StringEncoding to get a URL
    like this "/places.json?category=Autom%C3%B3viles"

    Here is my code:

    - (id)initWithBaseURLString:(NSString*)baseURLString resourcePath:
    (NSString*)resourcePath {
       NSString *completeURL = [NSString stringWithFormat:@"%@%@",
    baseURLString, resourcePath];

       // If some condition
       completeURL = [completeURL
    stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

           if ((self = [self initWithString:completeURL])) {
                   _baseURLString = [baseURLString copy];
                   _resourcePath = [resourcePath copy];
           }

           return self;
    }

Do you think we should merge this?

deletePersistentStoreReseedUsingSeedDatabaseName:(NSString*)seedFile

I'd like to propose an addition to RKManagedObjectStore that would allow for a deletion and also reseeding of the store. Right now when you delete, it automatically assumes you don't have a seed. Basically the new function has only one change beyond the normal store deletion.

if (seedFile)
    [self createStoreIfNecessaryUsingSeedDatabase:seedFile];
[self createPersistentStoreCoordinator];

RKTTRequestModel does not properly handle bad responses

When a service responds with bad data (or a bad response code) RestKit properly handles the error until it invokes "didFailLoadWithError:" on the RKTTRequestModel in -[RKRequestModel objectLoaderDidLoadUnexpectedResponse:]. RestKit passes a nil error which ultimately is ignored by the Three20 Framework (improperly or not) which means the application is kept in a indeterminate "loading state"

The fix for this would be to provide an error to didFailLoadWirhError:.

Improperly converts time sent in UTC

RestKit currently has special handling (even though the date is ISO 8601) for converting serialized UTC dates from rails. A rails serialized date is interpolated as a date in the local timezone. E.g., if "2010-11-16T21:11:33Z" is sent it will be parsed as "2010-11-16 21:11:33 -0500" for those in the eastern timezone. RestKit copes with this by explicitly subtracting the offset (-18000 seconds in eastern) to get the correct time.

This does not work when a date is serialized as a string in which the nsdateformatter can recognize the timezone offset. "2010-11-16 21:11:33 -0000" (y-M-d HH:mm:ss Z), for instance, would be properly handled by NSDateFormatter. However, RestKit still converts this time even though it properly interpolated which will automatically offset your time incorrectly.

The best solution may be to explicitly check for that permutation of the ISO 8601 format and switch on it. Otherwise it should only support the rails serialization format so that people do not falsely assume it can handle other date formats.

Implement support for the HATEOAS constraint

According to Roy Fielding:

"REST is defined by four interface constraints: identification of resources; manipulation of resources through representations; self-descriptive messages; and, hypermedia as the engine of application state." [1]

The first three are incorporated by RestKit (although it seems to couple REST to HTTP), but the latter one is missing. Namely, there is no built-in support for links representing possible state transitions or resource relationships, but rather the related entities need to be embedded or to be asked for with isolated queries based on id's.

"...if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period. " [2]

I think most people entirely miss the HATEOAS constraint, because most frameworks neither enforce, nor support the usage of them. Changing this for RestKit could improve the quality of and finally enable REST for wannabe-rest-systems.

RKJSONSerialization depends on JSON framework

The readme says that it should be possible to choose either YAJL or SBJSON (JSON Framework). However, RKJSONSerialization explicitly includes "NSObject+SBJSON.h" and calls a method "JSONRepresentation" declared there, so it's not possible to compile this class against YAJL only.

JSONKit Serialization Fails when NSDate Objects are Present

Ok. So I have narrowed it down to the following:

I have subclassed RKDynamicRouter so that I can send my POST requests
as JSON and not URL parameters. This is the method I have overridden
in the router subclass:

  • (NSObject)serializationForObject:
    (NSObject
    )object method:(RKRequestMethod)method {
    return [RKJSONSerialization JSONSerializationWithObject:[object
    propertiesForSerialization]];
    }

[object propertiesForSerializiation] had the dictionary with all the
correct properties, but the JSONSerializationWithObject: method
returns an empty HTTPBody object. So I did a bit more digging and
discovered the culprit is in this bit of code:

  • (NSString*)stringFromObject:(id)object {
    return [object JSONString];
    }

It appears JSONKit is just returning a nil string when we call
JSONString on it. I've used JSONKit a bit for a project before, and I
know it freaks out if it receives objects like NSDate. So I nilled out
the NSDate objects on my object, and bingo, the request body had data
in it.

So my question now is, what is the best way around the date problem.
My app is a scheduling app, so dates are pretty critical. I could
possibly put methods on the managed object that return a formatted
string for a date and map those rather than the dates themselves. The
other solution would be to use a different JSON library to JSONKit
that supports date objects, if this is the best solution, which should
I use? I am leaning towards the former solution rather than the latter
as it gives me the added benefit of having control over how my dates
are formatted in the request and being able to deal with different
date formats in responses.

Clarify setup documentation XCode 4

Just setup RestKit in my XCode 4 project. Have a few gotchas that I think you need to add to the documentation;

  1. I had to add CoreData.framework even if it said it was optional. Yes I had libRestKitCoreData.a in there also. My suggestion is to put those to next to each other so it is very clear that if you add one, you need to add the other.
  2. I had to restart XCode in order for the RestKit.xcodeproj to show up as it should with an indented list.

Other than that - thanks for a great lib. Excited to try it out.

Martin

App build with RestKit and Three20 fails on clean Build directory

When building an app with RestKit and the optional RestKit Three20 library, the build fails when building from a clean RestKit Build/ directory. Build failures in the app cite the absence of <RestKit/Three20/Three20.h>, presumably because the Copy Headers build task(s) on the RestKit target execute(s) prior to the Three20 component being built via inclusion in the app directly. This can likely be solved by adding the Copy Headers build task(s) as part of the RestKit Three20 library.

RKManagedObjectStore should allow for user-supplied NSManagedObjectModel

My project can't have a store that originates with a "mergedModelFromBundles" ... I've actually got two different active models that have to remain separate. So, to accommodate this, I wind up using something like this to retain a passed-in model instead of whipping up one inside the framework.

  • (id)initWithStoreFilename:(NSString*)storeFilename model:(NSManagedObjectModel *)storeModel;

Enable Support for Changing resourcePath for object loaders with a target object

Use case is that you want to support multiple target resource paths with the same HTTP verb:

In my application, I have a User model that contains both information
about the user and his or her login information. I'm using Authlogic
(Rails backend) for user signup and login (done pretty much the same
way as the DiscussionBoard example). I want to allow the user to
update his or her information on the service as well (e.g. contact
information, credentials), which is tied to the User model. Therefore,
it needs to handle two different PUT requests to two different
resource paths on a Rails server (one for /login and one for /users/
<id>). The RKRailsRouter allows for only one resource path for each
method (makes sense), so I'm just wondering, is there a way around
this in RestKit? Is there a way I can have the RKObjectManager
"putObject" to a specific resource path?

Basically, imagine my scenario is the DiscussionBoard example, but you
want to give the user the ability to update their username, email,
password, or any other information.

Object Mapper 2.0

Epic story ticket for the object mapper 2.0 work. This update will simplify and expand the capabilities of the object mapping layer.

Examples Don't Work

Running both example projects I receive the following error:

2010-12-28 10:37:05.404 RKTwitter[20942:207] Hit error: Error
Domain=com.twotoasters.RestKit.ErrorDomain Code=2 "The client is
unable to contact the resource at http://twitter.com/status/user_timeline/twotoasters.json"
UserInfo=0x9218d90 {NSLocalizedDescription=The client is unable to
contact the resource at http://twitter.com/status/user_timeline/twotoasters.json}

This crashes the app. The json is available via web browser so it isn't a connection issue. Any ideas?

Also the examples use globalManager rather than sharedManager.

Make it Easier to Specify Request Body

Simplify this:

NSString* JSON = @"whatever";
RKRequest* request = [[RKRequest alloc] initWithURL:URL];
request.method = RKRequestMethodPOST;
[request.URLRequest setHTTPBody:[JSON dataUsingEncoding: NSASCIIStringEncoding]];
[request send];

RKObjectLoader in ObjectMapping depends on Core Data

Readme says that Core Data framework is optional and only required if you use the Core Data related part of RestKit, but RKObjectLoader class in ObjectMapping module imports RKManagedObjectStore from the CoreData module and Core Data framework itself.

Mapping Fails when Given a Target Object Class and Array of Registered Element Subdictionaries

From the mailing list:

    OK here is the setup:

    Item model object (IIContentObject.h is a RKManagedObject subclass
    that deals with the update dates etc)
    ==============
    #import "IIContentObject.h"

    @interface Item : IIContentObject {
    @private
    }
    @property (nonatomic, retain) NSNumber * parentID;
    @property (nonatomic, retain) NSNumber * categoryID;
    @property (nonatomic, retain) NSNumber * itemID;
    @property (nonatomic, retain) NSString * itemName;
    @property (nonatomic, retain) NSString * imageBaseDir;
    @property (nonatomic, retain) NSString * imageName;

    @end

    #import "Item.h"


    @implementation Item
    @dynamic parentID;
    @dynamic categoryID;
    @dynamic itemID;
    @dynamic itemName;
    @dynamic imageBaseDir;
    @dynamic imageName;

    + (NSDictionary*)elementToPropertyMappings {
           return [NSDictionary dictionaryWithKeysAndObjects:
               @"id", @"itemID",
               @"name", @"itemName",
               @"parent_id", @"parentID",
               @"category_id", @"categoryID",
               @"imageBaseDir", @"imageBaseDir",
               @"imageName", @"imageName",
               @"created_at", @"createdAt",
               @"updated_at", @"updatedAt",
               nil];
    }

    + (NSString*)primaryKeyProperty {
           return @"itemID";
    }
    @end

    App delegate
    ==========
    // Initialize RestKit
    RKObjectManager* objectManager = [RKObjectManager
    objectManagerWithBaseURL:@"http://localhost:3000"];
    RKObjectMapper* mapper = objectManager.mapper;

    // Add our element to object mappings
    [mapper registerClass:[Item class] forElementNamed:@"item"];


    RKRailsRouter* router = [[[RKRailsRouter alloc] init] autorelease];

    [router setModelName:@"item" forClass:[Item class]];
    [router routeClass:[Item class] toResourcePath:@"/items"
    forMethod:RKRequestMethodPOST];
    [router routeClass:[Item class] toResourcePath:@"/items/(itemID)"
    forMethod:RKRequestMethodPUT];
    [router routeClass:[Item class] toResourcePath:@"/items/(itemID)"
    forMethod:RKRequestMethodDELETE];

    objectManager.router = router;

    In my view I call
    ============

    - (void)loadItemData {
           RKObjectManager* objectManager = [RKObjectManager sharedManager];
           [[objectManager loadObjectsAtResourcePath:@"/items.json" objectClass:
    [Item class] delegate:self] retain];
    }

    =======================
    I am probably missing something here and not using the routing
    correctly!
    Every time I call the load item data I end up with blank rows inserted
    into core data. JSON is as follows:

    [{"item":{"category_id":null,"created_at":"2011-04-11T09:32:25Z","id":
    1,"imageBaseDir":"","imageName":"","name":"Inspiration","parent_id":null,"updated_at":"2011-04-11T09:32:25Z"}}]

    Can someone push me in the right direction please.

    Thanks

    David

Merge RKRequestQueue

Picking up Jeff Arena's work from #41. This implements a cache that is capable of responding with previously loaded payloads and headers.

Has Many Mapping

Just wondering how the has many relationship works. Looking through the source I see this
@"[email protected]_many", @"hasMany",

Lets say my managed object models are:
Photo
User

Photo can be "liked" by many users. So liked is the JSON element which contains many users.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.