Creating an Objective-C API - objective-c

I have never made an API in objective-c, and need to do this now.
The "idea" is that I build an API which can be implemented into other applications. Much like Flurry, only for other purposes.
When starting the API, an username, password and mode should be entered. The mode should either be LIVE or BETA (I guess this should be an NSString(?)), then afterwards is should be fine with [MyAPI doSomething:withThisObject]; ect.
So to start it [MyAPI username:#"Username" password:#"Password" mode:#"BETA"];
Can anyone help me out with some tutorials and pointer on how to learn this best?

It sounds like what you want to do is build a static library. This is a compiled .a file containing object code that you'll distribute to a client along with a header file containing the interface. This post is a little outdated but has some good starting points. Or, if you don't mind giving away your source code, you could just deliver a collection of source files to your client.
In terms of developing the API itself, it should be very similar to the way you'd design interfaces and implementations of Objective-C objects in your own apps. You'll have a MyAPI class with functions for initialization, destruction, and all the functionality you want. You could also have multiple classes with different functionality if the interface is complex. Because you've capitalized MyAPI in your code snippet, it looks like you want to use it by calling the class rather than an instance of the class - which is a great strategy if you think you'll only ever need one instance. To accomplish this you can use the singleton pattern.
Because you've used a username and password, I imagine your API will interface with the web internally. I've found parsing JSON to be very straightforward in Objective-C - it's easy to send requests and get information from a server.
Personally I would use an enum of unsigned ints rather than a NSString just because it simplifies comparisons and such. So you could do something like:
enum {
MYAPI_MODE_BETA,
MYAPI_MODE_LIVE,
NUM_MYAPI_MODES
};
And then call:
[MyAPI username:#"Username" password:#"Password" mode:MYAPI_MODE_BETA];
Also makes it easy to check if they've supplied a valid mode. (Must be less than NUM_MYAPI_MODES.)
Good luck!

Related

How to serialize data like a buffer object in Objective-C for NativeScript to consume

While working to add cross-platform support to a NativeScript plugin, there are areas of the plugin that will need to preserve an Object state. This means that at a given time, the state of the data needs to be preserved and stored within NativeScript (TypesScript/JavaScript) and reinstated without data corruption.
While this seems to be a feat pretty straightforward in many JAVA libraries used for the Android side of the plugin, I am unsure how to replicate this for iOS development.
Researching this topic online can lead to various answers, most of which seem to require the developer to create specific methods on a given Object/Class in order to support serialization.
Option 1 - NSCoding Protocol
The NSCoding protocol — Source (Apple) — declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).
The two methods mentioned are:
- (void) encodeWithCoder:(NSCoder*)encoder;
- (id) initWithCoder:(NSCoder*)decoder;
While this could work in most circumstances, this would require the NativeScript developer to figure out a way to create yet another wrapper for an iOS library (likely to be a pod package). This is more hands on than needs to be and may not be available in most situations.
Option 2 - NSKeyedArchiver/NSKeyedUnarchiver
The NSKeyedArchiver and companion NSKeyedUnarchiver protocols provide a way to encode/decode objects (and scalar values) into an architecture-independent suitable for storage in a file.
This option seems less intrusive and allows for the archived object to be turned into something sharable between environments such as base64:
declare var NSDataBase64EncodingEndLineWithLineFeed;
declare var NSDataBase64DecodingIgnoreUnknownCharacters;
// archive class instance as base64 string
const archivedObject = NSKeyedArchiver.archivedDataWithRootObject(someClassInstance);
const base64Archive = archivedObject.base64EncodedStringWithOptions(NSDataBase64EncodingEndLineWithLineFeed);
// unarchive back into a class instance
const rawData = NSData.alloc().initWithBase64EncodedStringOptions(base64Archive, NSDataBase64DecodingIgnoreUnknownCharacters);
const newClassInstance = NSKeyedUnarchiver.unarchivedObjectOfClassFromDataError(NSObject, rawData);
I was able to learn both of these concepts from an old article lost in time (but thankfully saved due to the WayBackMachine) — CocoaHeads - NSCoding
In addition to the information above, I believe one could also use NativeScript to extend an existing ObjC Class and add the required encodeWithCoder and initWithCoder methods. While I have not needed to do this or try this out, if myself or someone else happens to experiment with this with a good result please let me know and I'll add that example here.
For more information about creating a subclass by extending Objective-C classes in NativeScript, please check out this source:
https://docs.nativescript.org/core-concepts/ios-runtime/how-to/ObjC-Subclassing
For more information about Objective-C classes in NativeScript, please read up here: https://docs.nativescript.org/core-concepts/ios-runtime/types/ObjC-Classes

Is overriding Objective-C framework methods ever a good idea?

ObjC has a very unique way of overriding methods. Specifically, that you can override functions in OSX's own framework. Via "categories" or "Swizzling". You can even override "buried" functions only used internally.
Can someone provide me with an example where there was a good reason to do this? Something you would use in released commercial software and not just some hacked up tool for internal use?
For example, maybe you wanted to improve on some built in method, or maybe there was a bug in a framework method you wanted to fix.
Also, can you explain why this can best be done with features in ObjC, and not in C++ / Java and the like. I mean, I've heard of the ability to load a C library, but allow certain functions to be replaced, with functions of the same name that were previously loaded. How is ObjC better at modifying library behaviour than that?
If you're extending the question from mere swizzling to actual library modification then I can think of useful examples.
As of iOS 5, NSURLConnection provides sendAsynchronousRequest:queue:completionHandler:, which is a block (/closure) driven way to perform an asynchronous load from any resource identifiable with a URL (local or remote). It's a very useful way to be able to proceed as it makes your code cleaner and smaller than the classical delegate alternative and is much more likely to keep the related parts of your code close to one another.
That method isn't supplied in iOS 4. So what I've done in my project is that, when the application is launched (via a suitable + (void)load), I check whether the method is defined. If not I patch an implementation of it onto the class. Henceforth every other part of the program can be written to the iOS 5 specification without performing any sort of version or availability check exactly as if I was targeting iOS 5 only, except that it'll also run on iOS 4.
In Java or C++ I guess the same sort of thing would be achieved by creating your own class to issue URL connections that performs a runtime check each time it is called. That's a worse solution because it's more difficult to step back from. This way around if I decide one day to support iOS 5 only I simply delete the source file that adds my implementation of sendAsynchronousRequest:.... Nothing else changes.
As for method swizzling, the only times I see it suggested are where somebody wants to change the functionality of an existing class and doesn't have access to the code in which the class is created. So you're usually talking about trying to modify logically opaque code from the outside by making assumptions about its implementation. I wouldn't really support that as an idea on any language. I guess it gets recommended more in Objective-C because Apple are more prone to making things opaque (see, e.g. every app that wanted to show a customised camera view prior to iOS 3.1, every app that wanted to perform custom processing on camera input prior to iOS 4.0, etc), rather than because it's a good idea in Objective-C. It isn't.
EDIT: so, in further exposition — I can't post full code because I wrote it as part of my job, but I have a class named NSURLConnectionAsyncForiOS4 with an implementation of sendAsynchronousRequest:queue:completionHandler:. That implementation is actually quite trivial, just dispatching an operation to the nominated queue that does a synchronous load via the old sendSynchronousRequest:... interface and then posts the results from that on to the handler.
That class has a + (void)load, which is the class method you add to a class that will be issued immediately after that class has been loaded into memory, effectively as a global constructor for the metaclass and with all the usual caveats.
In my +load I use the Objective-C runtime directly via its C interface to check whether sendAsynchronousRequest:... is defined on NSURLConnection. If it isn't then I add my implementation to NSURLConnection, so from henceforth it is defined. This explicitly isn't swizzling — I'm not adjusting the existing implementation of anything, I'm just adding a user-supplied implementation of something if Apple's isn't available. Relevant runtime calls are objc_getClass, class_getClassMethod and class_addMethod.
In the rest of the code, whenever I want to perform an asynchronous URL connection I just write e.g.
[NSURLConnection sendAsynchronousRequest:request
queue:[self anyBackgroundOperationQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *blockError)
{
if(blockError)
{
// oh dear; was it fatal?
}
if(data)
{
// hooray! You know, unless this was an HTTP request, in
// which case I should check the response code, etc.
}
/* etc */
}
So the rest of my code is just written to the iOS 5 API and neither knows nor cares that I have a shim somewhere else to provide that one microscopic part of the iOS 5 changes on iOS 4. And, as I say, when I stop supporting iOS 4 I'll just delete the shim from the project and all the rest of my code will continue not to know or to care.
I had similar code to supply an alternative partial implementation of NSJSONSerialization (which dynamically created a new class in the runtime and copied methods to it); the one adjustment you need to make is that references to NSJSONSerialization elsewhere will be resolved once at load time by the linker, which you don't really want. So I added a quick #define of NSJSONSerialization to NSClassFromString(#"NSJSONSerialization") in my precompiled header. Which is less functionally neat but a similar line of action in terms of finding a way to keep iOS 4 support for the time being while just writing the rest of the project to the iOS 5 standards.
There are both good and bad cases. Since you didn't mention anything in particular these examples will be all-over-the-place.
It's perfectly normal (good idea) to override framework methods when subclassing:
When subclassing NSView (from the AppKit.framework), it's expected that you override drawRect:(NSRect). It's the mechanism used for drawing views.
When creating a custom NSMenu, you could override insertItemWithTitle:action:keyEquivalent:atIndex: and any other methods...
The main thing when subclassing is whether or not your behaviour completes re-defines the old behaviour... or extends it (in which case your override eventually calls [super ...];)
That said, however, you should always stand clear of using (and overriding) any private API methods (those normally have an underscore prefix in their name). This is a bad idea.
You also should not override existing methods via categories. That's also bad. It has undefined behaviour.
If you're talking about categories, you don't override methods with them (because there is no way to call original method, like calling super when subclassing), but only completely replace with your own ones, which makes the whole idea mostly pointless. Categories are only useful for safely extending functionality, and that's the only use I have even seen (and which is a very good, an excellent idea), although indeed they can be used for dangerous things.
If you mean overriding by subclassing, that is not unique. But in Obj-C you can override everything, even private undocumented methods, not just what was declared 'overridable' like in other languages. Personally, I think it's nice, as I remember in Delphi and C++ I used to “hack” access to private and protected members to workaround an internal bug in framework. This is not a good idea, but at some moments it can be a life saver.
There is also method swizzling, but that's not standard language feature, that's a hack. Hacking undocumented internals is rarely a good idea.
And regarding “how can you explain why this can best be done with features in ObjC”, the answer is simple — Obj-C is dynamic, and this freedom is common to almost all dynamic languages (Javascript, Python, Ruby, Io, a lot more). Unless artificially disabled, every dynamic language has it.
Refer to the wikipedia page on dynamic languages for longer explanation and more examples. For example, an even more miraculous things possible in Obj-C and other dynamic languages is that an object can change it's type (class) in place, without recreation.

Can I use an application as a library (Mac, Objective-c)?

Is there a way to load classes from a mac app, and use them in a different mac app?
I'd like to make an Automator action that accesses some of the classes in my mac app, and this seems like the sort of way I'd ideally do it (means you have to have bought my app to use the Automator action, etc.)
Depending on what you want to do (I'm not quite clear), a Service might do the trick for you. You make a helper app which can pass data back and forth with your app, using a shared pasteboard. You can get a fairly wide range of action, because you can pass any object that conforms to the NSPasteboardWriting and NSPasteboardReading protocols; as it says there in the docs, NSString, NSAttributedString, NSURL, NSColor, NSSound, and NSImage are already available for you, and of course you can write a custom class that suits your needs exactly.
Have you tried creating a stand-alone Automator plugin project, or tried adding an Automator bundle target to your application's project?
I'm assuming that you want to create Automator actions for your main app, but are unclear how you get these actions to interact with your application (or with the classes present in your application).
There are 3 basic types of Automator actions: AppleScript-based, shell-script based, and Objective-C based. You'll most likely want to make yours Objective-C-based, which will allow you to easily incorporate other Objective-C code from your main application into the action itself (see Implementing an Objective-C Action). (Note that by default, when you add a new target for an automator bundle, it's an AMAppleScriptAction type).
To see how an Objective-C automator action is set up compared to an AppleScript-based action, you might want to try creating a separate standalone project.
Let's say your app is document-based, and uses the KWDocument class, which exposes a method named -duplicateObjects:(NSArray *)objects toDocument:(KWDocument *)destDocument;. You also have a KWRegistrationManager that knows whether your app is registered or not. And let's say you want to create an automator action that's called "Duplicate Objects to Document". The action will be implemented in KWDuplicateObjectsToDocument, which is as a subclass of AMBundleAction. In the Info.plist for Duplicate Objects to Document.action, the NSPrincipalClass will be KWDuplicateObjectsToDocument.
KWDuplicateObjectsToDocument.h will look something like:
#import <Cocoa/Cocoa.h>
#import <Automator/AMBundleAction.h>
#interface KWDuplicateObjectsToDocument : AMBundleAction {
}
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction
error:(NSDictionary **)errorInfo;
#end
And your KWDuplicateObjectsToDocument.m will look something like this:
#import "KWDuplicateObjectsToDocument.h"
#import "KWDocument.h"
#import "KWRegistrationManager.h"
#implementation KWDuplicateObjectsToDocument
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction
error:(NSDictionary **)errorInfo {
if (![[KWRegistrationManager defaultManager] isRegistered]) {
return nil;
}
// eventually you'll call
// duplicateObjects:toDocument:
return input;
}
#end
You'll need to make sure that the necessary classes you use (such as KWRegistrationManager, KWDocument, etc.) are compiled and included as part of the build process for this bundle.
Basically, no: you cannot link with an executable.
An application binary is in a specific format.
And that format is different from the static or shared library format.
It means you won't be able to load any code parts from an application binary, as you would with a library.
Take a look at distributed objects. Your application could vend one or more objects that your Automator action could use. I've never tried it with Automator, but it's a very elegant system that hasn't gotten a lot of attention in recent years. I think it's definitely worth a look.
One cool aspect of distributed objects is that the application could be running on the same computer if you wish, but it could just as easily be running on a different computer, perhaps even one that's very far away.
You could make certain behavior from you app accessible via Applescript, but accessing the the actual classes is not possible in the way I think you mean. I get the impression that you mean accessing the classes loaded into the memory of your running app. This is not possible on OS X (or any UNIX-like system). Applications run at the user level. Processess at the user level are not able to read memory from other processes. The components of the OS that need to do this sort of thing run at kernel level.
If you are just trying to reuse the code, you could build the parts you want to share into a static library, and others could link against it and share your code.
EDIT:
From NSGod's answer it seems that you can use the same approach that makes it accessible via Applescript and make it accessible via Obj-C. That looks pretty cool.

Private and protected methods in Objective-C

What is the recommended way to define private and protected methods in Objective-C? One website suggested using categories in the implementation file for private methods, another suggested trailing underscores, or XX_ where XX is some project-specific code. What does Apple itself use?
And what about protected methods? One solution I read was to use categories in separate files, for example CLASS_protected.h and CLASS_protected.m but this seems like it could get very bloated. What should I do?
There are three issues:
Hiding from compiler.
That is, making it impossible for someone else to #import something and see your method declarations. For that, put your private API into a separate header file, mark that header's role as "Private" in Xcode, and then import it in your project where you need access to said private API.
Use a category or class extension to declare the additional methods.
Preventing collisions
If you are implementing lots of internal goop, do so with a common prefix or something that makes a collision with Apple provided (or third party) provided methods exceedingly unlikely. This is especially critical for categories and not nearly as critical for your leaf node subclasses of existing classes.
Post the link for the site suggesting leading underscores, as they are wrong, wrong, wrong. Leading underscores are used by the system to mark private API and you can run into collisions easily enough.
Hiding from the runtime.
Don't bother. It just makes debugging / crash analysis harder and anyone determined enough to muck around at the runtime will be able to hack your app anyway.
There are no "real" private methods in Objective C, as the run-time will allow, via documented public APIs, access any method in any class by using their string names.
I never do separate interface files for "private" methods, and let the compiler complain if I try to use these any of these methods outside of file scope.
The XX_ seems to be the ad hoc means to create a pseudo namespace. The idea is to read Apple's docs and the docs of any frameworks you might use at any time in the future, and pick an XX prefix that none of these others is ever likely to use.

How can I implement the service locator pattern in Cocoa Touch across multiple projects?

This is a problem which has been bugging me for a while now. I'm still pretty new with some of these patterns so you'll have to forgive me (and correct me) if I use any of the terms incorrectly.
My Methodology
I've created a game engine. All of the objects in my game engine use inversion of control to get dependencies. These dependencies all implement protocols and are never accessed directly in the project, other than during the bootstrapping phase. In order to get these objects, I have the concept of a service locator. The service locator's job is to locate an object which conforms to a specific protocol and return it. It's a lot like a factory, but it should handle the dependencies as well.
In order to provide the services to the service locator, I have what I call service specifiers. The service locator knows about all of the service specifiers in the project, and when an object is requested, attempts to get an instance of an object conforming to the provided protocol from each of them. This object is then returned to the caller. What's cool about this set up is the service specifier also knows about a service locator, so if it has any dependencies, it just asks the service locator for those specific dependencies.
To give an example, I have an object called HighScoreManager. HighScoreManager implements the PHighScoreManager protocol. At any time if an instance of PHighScoreManager is required, it can be retrieved by calling:
id<PHighScoreManager> highScoreManager = [ServiceLocator resolve: #protocol(PHighScoreManager)];
Thus, inversion of control. However, most of the time it isn't even necessary to do this, because most classes are located in a service specifier, if one required PHighScoreManager as a dependency, then it is retrieved through the service locator. Thus, I have a nice flat approach to inversion of control.
My Problem
Because I want the code from my game engine to be shared, I have it compiled as a static library. This works awesome for everything else, but seems to get a little tricky with the service locator. The problem is some services change on a game to game basis. In my above example, a score in one game might be a time and in another it might be points. Thus, HighScoreManager depends on an instance of PHighScoreCreator, which tells it how to create a PScore objecct.
In order to provide PHighScoreCreator to HighScoreManager, I need to have a service specifier for my game. The only way I could think of to accomplish this was to use the Cocoa version of reflections. After digging around, I found out classes were discoverable through NSBundle, but it seems there's no way to get the current bundle. Thus, if I want to be able to search out my service specifiers, I would have to compile my game logic into its own bundle, and then have the engine search out this bundle and load it. In order to do this I'd have to create a third project to house both the engine code and the game logic bundle, when in reality I'd like to just have a game project which used the engine static library.
My Real Question
So after all of that, my question is
Is there a better way to do what I'm trying to accomplish in Cocoa Touch, or
Is there a way to discover classes which conform to my service specifier protocol from the main bundle?
Thanks for the help and taking the time to read the question.
-helixed
Have a look at:
+[NSBundle mainBundle];
+[NSBundle bundleForClass:];
+[NSBundle bundleWithIdentifier:];
+[NSBundle allBundles];
+[NSBundle allFrameworks];
These allow you to interact programmatically with the various bundles at runtime. Once you have a bundle to work with there are a number of strategies you could employ to find the specific class(es) you are looking for. For example:
Retrieve the bundle identifier — this will be an NSString like #"com.example.GameEngineClient".
Transform it into a legal Objective-C class name by stripping everything before the last dot, or replacing all the dots with underscores, or whatever, and then appending a predefined protocol name. Your protocol from above, for instance, might result in a string like #"GameEngineClient_PHighScoreManager".
Get the bundle's designated class for your protocol using NSClassFromString().
Now you can create an instance of the class provided by the bundle author, that implements whatever protocol you have specified.
The Objective-C runtime is a beautiful thing!
Sounds like you need to use the functions of the Objective-C runtime. First you can get a list of all available classes via objc_getClassList. Then you can iterate over all the classes and check if they conform to your protocol with class_conformsToProtocol. You shouldn’t use +conformsToProtocol: messages here, since there are classes in the runtime that don’t support this selector.