Hello I have been looking around for this answer and I've come across multiple articles but none of them have given me a straight answer. Lets say we have Object Date in objective C if I want to add methods to this object I would create a file similar to this:
obj c:
#interface Date (AdditionDate)
//methods
#end
in swift it seems to be a little different we do the following:
extension Date {
//methods
}
is this correct? Thank you for your help!!
Yep that's correct. What you are looking for is called a category in Objective-C terminology. It is the ability to add on methods to an existing class even if you don't have the original source code for that class. Keep in mind that you can't use categories to store any state on the original object, so instance variables are off the table.
Related
I know in objective c you can not add instance variable in category of interface. that is ok but today i see something i can not figure it out ,(why is this behavior right?)
#interface XXXX:NSObject
#end
#interface XXXX(){
#private
int x;
}
#end
why can i add add instance variable in empty () category , also why no one mention in in the internet.
Thanks All
You can add instance variables to anonymous categories/class extensions (Using just () for the category name), because they are essentially just a private extension of the main interface, and there can only be one.
However you cannot add new instance variables with named categories. You can make use of Associative References to work around this however.
I am getting a warning:
RS232Msg cannot respond to
"-initWithRS232MsgRawEncoded"
Code is
-(void)createMessage
{
RS232Msg* pMsg;
//pMsg = new RS232MsgRawEncoded(static_cast<int>nMessageNumber); in cpp
pMsg = [pMsg initWithRS232MsgRawEncoded:(int)nMessageNumber];
}
initWithRS232MsgRawEncoded is a derived class of RS232Msg.
and pMsg is a pointer to RS232Msg. The createMessage is a method that is declared in RS232Msg How to make it to access ?
If you defined initWithRS232MsgRawEncoded in a class derived from RS232Msg you cannot use that selector with RS232Msg*.
If I understand correctly what you are trying to do, you would like to add one more possibility of creating RS232Msg objects by initializing them with raw encoding.
You can do that in different ways. One is creating a sort of "factory" class (it would not be an orthodox factory as per GoF patterns, but that does not matter). This class can have a static function that is exactly your initWithRS232MsgRawEncoded.
Another option you have is define a category for RS232 and then add the initWithRS232MsgRawEncoded into it. Categories are a way to extend classes without the need of subclassing them. This is a skeleton of how you would go about it in your case:
#interface RS232 (MyRS232Extension)
(id)initWithRS232MsgRawEncoded:....;
#end
#implementationRS232 (MyRS232Extension)
....
#end
I have a custom class in Obj-C called RouteManager which contains an array of NSStrings. Each string is a bus stop name which is used as a key for a dictionary to get the rest of the information for the bus stop (basically, just [busStopDictionary allkeys]). In one of the situations where my app uses this array, I want to return the array sorted by the distance from the user. I've started setting up the code to be able to call sortedArrayUsingSelector on my array with the following method:
- (NSComparisonResult)compareByDistance:(NSString*) otherStop
{
// Return appropriate NSOrdered enum here based on comparison of
// self and otherStop
}
My problem is that in the case where compareByDistance is a method of RouteManager, self refers to the instance of RouteManager. However, I need self to refer to the NSString that the compare is being called on. So, I assumed I needed to setup a category, as such:
#interface NSString (Support)
-(NSComparisonResult) compareByDistance:(NSString*)otherStop;
#end
This got my self reference correct, however this comparison uses values from the RouteManager class. When implemented as seen above, the NSString (Support) implementation obviously complains that those values are undeclared.
That should provide enough background info for my question. How do I go about doing this? I would like my category of NSString, which consists solely of the method compareByDistance, to be able to use values from the current instance of my class, RouteManager, which inherits from NSObject. Ideally, I feel as though the category should somehow be within RouteManager. I feel there has to be some way to accomplish this that is cleaner than passing the necessary values into compareByDistance. Thanks in advance for any and all help.
Your best bet would be to define a custom class for a bus stop, instead of storing them as strings and dictionaries.
Make the BusStop class have properties for Name, Location and whatever else. Implement the compareByDistance: method on the BusStop class.
You can still use a dictionary if you need to look them up by name. Just store them with the name as the dictionary's key, and the BusStop object as the dictionary's value.
What I mean by generic is that you pass a class and a JSON to a method and that method transforms the JSON data in your object based on the class definition.
I'm interested both in conceptual answers and Objective-C approaches.
I assume with generic parser, you mean an implicit JSON-to-object mapper.
In this case, there is one challenge. Which might or might not be solvable depending whether variables are types in Objective-C (it's actually a shame I dont know that). While its quite simple to map setter method names (given Objective-C does provide reflection) to JSON attributes, it is hard to know which object to create for nested JSON objects. So you need a kind of factory that guesses which type nested objects could have. If variables in Objective-C are types, that might be used as a hint, if not you are left on your own.
Getting the data into NSArray and the like is easy, there are plenty of these around, for example json-framework
Try this (untested):
#import <Cocoa/Cocoa.h>
#import "JSON/JSON.h"
int main(int argc, char *argv[])
{
NSLog(#"%#", [#"[ 100, 500, 300, 200, 400 ]" JSONValue]);
return 0;
}
As Adrian says, mapping your data structures to objects is a bit of a challenge, then. It isn't in json-framework, I don't know what else there is. For sure, but I suppose that the project maintainer will accept your code, if you write some :).
You would need to use reflection on the passed in class which is not handled as well as some other languages from what i can see.
Class c = [self class];
Will return a C struct containing a list of variables and methods and then it would be a matter of writing a data mapper style system to reflect the class and assign the JSON variables to it.
E.g. JSON struct of
var x = { prop1: "Test 1",
prop2: "Test 2};
Then have a class
#interface x : NSObject {
NSString* prop1;
NSString* prop2;
}
#property (nonatomic,retain) NSString* prop1;
#property (nonatomic,retain) NSString* prop2;
You'd need to have a concrete implementation but it doesn't need to do anything fancy really.
Your mapper could then use either use reflection to parse the object or just use dumb assignment:
- (NSObject)mapClassFromJSON:(NSObject)class fromJSON:(id)jsonArray
{
//code needs to iterate over the jsonArray (needs to check using isKindOfClass if it's an NSArray or NSDictionary) and assign the class properties to it.
}
Remember if using SBJSON which everyone does, that the types inside the returned JSON can either be NSArray or NSDictionary, it needs to know which. If going down the generic path for nesting then it would need to use variable reflection and some smarts to generate the type mappings as otherwise it needs to be hard coded for each class.
Edit:
Have a look at
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/class_copyPropertyList
Might be useful, might not...
Well, conceptually, this method is known as serialization/deserialization. The difference is that your serialized format will be JSON. Realization: Define basic conventions for your class and JSON and implement them. For example: Every JSON should have uniq-id which will correspond to the class.
I'm not familiar with Objective-C, but if I would do that in other languages, I would assume, that every key in JSON, would represent the attribute of the class. This attribute could be set by function like classInstance.setJsonAttribute(key, value); Then, I would write some JSON parser which would walk through JSON, extracted uniq-id, created class based on this id, and walked through all other key:values parse, setting them with setJsonAttribute function. I think, that would be my begin in implementation.
For others who may come accross this post, it is possible! And there happen to be a few open source projects that already do this very well. Checkout rest kit and
https://github.com/RestKit/RestKit
https://github.com/dchohfi/KeyValueObjectMapping
I dont know objective-c at all but i do know JSON.
Its a uniform data exchange format, with an RFC so you would definately be able to role your own parser. Does objective-c support generic types? If so what your looking for would be achievable, and id also guess that someone else has all ready rolled one.
I am new to Obj-C so forgive me if this is a stupid question:
How do I implement some in the style of Javas enums? Or to be more precise:
I want a class with some known properties which are fix at compile time and unique per instance. Additionally I only want one instance type.
Let me give an example in Java:
public enum MessageTypes {
DEFAULT("white", "standard", 1),
EXPRESS("red", "expressMessage", 2),
BORADCAST("green", "broadcast", 3);
String color; String tagName; int dbId;
MessageTypes(String color, String tagName, int dbId) {
// you get the idea
}
//some methonds like getEnumByTagName
}
How would you do something like this in Objective-C? Am I missing something? Is this a bad pattern at all?
Thanks in advance!
EDIT: I am sorry, if I did not made myself clear. I know, that obj-c enums are not what I am looking for (as they are only marginally more than a typedef to an int).
I would like to create a set of (kind-of-singleton, immutable) instances of a specific class. The singleton pattern in Apples Dev-Docs is of no use as I want multiple distinct instances of a class each with individual values in their properties.
The goal of that is to have multiple Message types (about 20) that can be assigned to a Message as a property. Each of my Message types has a (fix and predefined) color, attribute-value (in an XML-representation) and a numerical ID.
In Java, I would use an enum as in my code sample. But how do I create different MessageTypes and associate them with their properties in Obj-C?
Creating 20 Sublcasses of MessageType (each with a singleton-instance holding the properties) seems like a lot of work for such a simple task and total overkill.
My current approach is to create a class with an NSArray holding the different instances. Up on first access of a method like +(id)messageTypeForId:NSInteger id_ the NSArray is prepopulated. But this feels totally clumsy and not at all elegant...
Is there a more satisfying approach?
There is not much in the way of a "more satisfying approach".
The normal Cocoa pattern would be to create methods like:
+ (MessageTypes*) sharedDefaultMessageType;
+ (MessageTypes*) sharedExpressMessageType;
+ (MessageTypes*) sharedBroadcastMessageType;
etc
and then implement them something like:
+ (MessageTypes*) sharedDefaultMessageType
{
static MessageTypes* thisMessageType = nil;
if ( !thisMessageType ) {
thisMessageType = [[MessageTypes alloc] initWithColor:#"white" tagName:#"standard" dbId:1];
}
return thisMessageType;
}
Alternatively, storing the shared MessageType* in an NSMutableArray or NSMutableDictionary or precalculating them as you are doing are all equally valid approraches.
Note that the above "template" method could be generated via a macro such that you could write in the .m file:
CREATEMESSAGETYPE( Default, #"white", #"standard", 1 )
CREATEMESSAGETYPE( Express, #"red", #"expressMessage", 2 )
CREATEMESSAGETYPE( Broadcast, #"green", #"broadcast", 3 )
which might be "more satisfying" or more ugly, depending on your point of view.
I think I'd just use a standard C enum:
typedef enum { MT_WHITE, MT_RED, MT_GREEN } MessageType;
Then you just use it as you would any other data type:
#interface Blah {}
-(void) setMessageType:(MessageType)newMessageType;
#end
Enums are not objects in C, and thus not in Objective-C either. They're just user-defined scalars that have a limited set of named values that they can take. You can give an object properties that are enum types, which I think is closest to what you're looking for.
If there's something specific you need to accomplish with this functionality, you might want to edit your post to indicate what that is.
I had the same question more or less but find all the above solutions clumsy stylistically.
In particular when simply using a C enum property on an object you lose the singleton semantics of Java enums. The biggest freedom I have found in the use of Java enums is that the instances of an enum are really singleton subclasses, and so participate in method polymorphism. Even more powerful than enums with unique attributes is enums with polymorphic behaviour.
Given that this is the key feature I am after would an Objective-C class cluster with singleton private subclasses be an approach with the desired behaviour, despite being a bit over the top in implementation cost and complexity?