Reputation: 2188
First off: Why is dependency management for obj-c projects such a pain?!
I am writing a wrapper for my RESTful service in objective-c. The server is a simple sinatra app running locally on 'http://localhost:4567'.
I've included RestKit by following the steps outlined here.
I know RestKit is 'installed' correctly into my project because when I do #import <RestKit/RestKit.h>
the project builds just fine.
Now, I'm testing my library using SenTesting.Framework. I have a class in my main library that looks like this:
#import "CITWCore.h"
#import <RestKit/RestKit.h>
@implementation CITWCore
- (id)init
{
self = [super init];
if (self) {
RKObjectManager *manager = [RKObjectManager objectManagerWithBaseURL:@"http://localhost:4567"];
// Initialization code here.
}
return self;
}
@end
And my unit test class:
#import "CITWCoreTests.h"
@implementation CITWCoreTests
- (void)testItCreatesAnInstance
{
CITWCore *newCoreObject = [[CITWCore alloc]init];
STAssertNotNil(newCoreObject, @"new object should not be nil");
}
@end
When I run the tests using ⌘U the test fails with this message:
error: testExample (CITWCoreTests) failed: -[__NSCFString isIPAddress]: unrecognized selector sent to instance 0xa115880
The error is being triggered by line 292 in RKClient.m
if ([newBaseURLString isEqualToString:@"localhost"] || [hostName isIPAddress]) {
There is a header file in the RestKit project called "NSString+RestKit.h" which contains the -isIPAddress method declaration, and as far as I can tell it is getting included, so I have no idea why the compiler/run-time does not know about that particular method. Is there something wrong with the way I've configured my testing target? How can I create an instance of RKObjectManager and get this test to pass?
More abstractly: How are people managing dependencies like this? I'm looking at things like VenderKit, but it seems lacking in documentation and I don't think I have the proper understanding of how compilers and linkers work to go to that big of an abstraction. What are some general guidelines when linking static libraries into my project, which is itself a static library?
Upvotes: 3
Views: 2077
Reputation: 99
One simple solution is to use cocoapods, which is good dependency management tool similar to maven in Java world.
CocoaPods is quite a powerful and maturing dependency management tool that can manage libraries, the libraries these depend on (transitive dependencies) as well as compiler and header flags.
It works by linking your project to another workspace that includes the libraries in source form, where the main target emits a static lib. This gives a good compromise between speed and being able to see the source-code.
Upvotes: 0
Reputation: 367
Double check that your project build settings for "Other Linker Flags" has "-all_load" and "-ObjC" on your build target. While you are in there, check that you created the "Header Search Paths" entry ("$(SOURCE_ROOT)/RestKit").
The "Installing-RestKit-in-Xcode-4.x" page that you linked to, is slightly out of date with a) Xcode and b) RestKit HEAD (the build process was simplified recently. FMI see the mailing list.
If you want to see a project correctly setup (I just created it recently, with the newest Xcode and Restkit) take a look at https://github.com/lottadot/lottadot-restkit-ios-rails3-1-advanced
My guess is if you clone that project, edit it's configuration and remove "-all_load" you will see the exact same error, when you run it.
Upvotes: 3
Reputation: 104708
In this case, you need to find the file (or image/library) which defines/exports -[NSString isIPAddress]
. Then you would need to add that file to your compile phase (if it is a source file), or link the library to your final binary (if it is a library or object file). In addition to linking it to your app, you will also need to compile and or link it into your unit test executable.
I know RestKit is 'installed' correctly into my project because when I do #import the project builds just fine.
#import
ing will not necessarily link or compile all of the necessary dependencies. You may have to do this manually. Xc4 may detect the dependency automatically, and build and link it for you if the option is enabled -- but it does not always get it right (it's good for basic dependencies).
Why is dependency management for obj-c projects such a pain?!
It's really not, IMO. Specifying files to compile and libraries to link with is something you'll need to get used to when compiling C family languages. Unless you want to be more specific about this criticism…
How are people managing dependencies like this?
Add the dependent projects to your Xcode projects. Configure them as build dependencies -- this will ensure they build before your app is built, and that the builds are up to date. For static libraries (targeting iOS), save the link stage for the final executables. In more complex scenarios, you will want to use xcconfig files in order to easily define build settings for any/all dependencies.
Upvotes: 1