Subclassing NSString - nsstring

Using WSDL2ObjC I am getting lot of classes which are subclasses of NSString.
I am finding it troublesome to initialize the NSString value of any object of those classes.
Say my class looks like this :
#interface mClass ; NSString {
int value;
}
Now in my code I would like to use objects of mClass as both NSString and also want to use its attribute value which is an integer.
How can I do that?
I am trying to use code like this
mClass *obj = [[mClass alloc] initWithString:#"Hello"];
But it's showing me an error saying I am using an abstract object of a class , I should use concrete instance instead.

If you really need make NSString subclass you should override 3 methods:
- (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer;
- (NSUInteger)length;
- (unichar)characterAtIndex:(NSUInteger)index;
For example:
MyString.h
#interface MyString : NSString
#property (nonatomic, strong) id myProperty;
#end
MyString.m
#interface MyString ()
#property (nonatomic, strong) NSString *stringHolder;
#end
#implemenation MyString
- (instancetype)initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)freeBuffer {
self = [super init];
if (self) {
self.stringHolder = [[NSString alloc] initWithCharactersNoCopy:characters length:length freeWhenDone:freeBuffer];
}
return self;
}
- (NSUInteger)length {
return self.stringHolder.length;
}
- (unichar)characterAtIndex:(NSUInteger)index {
return [self.stringHolder characterAtIndex:index];
}
#end

It might be smarter to use a wrapper class that internally uses NSStrings to do whatever operations or manipulations you are trying to do. However this will cause you to need to overload any functionality of NSString you want (such as getting the length of the string).
Or, you could create a category of NSString (found right next to Objective-C class in the new file window). This allows you to add any properties or methods that you wish to be "added" to the NSString class. Now just import this category wherever you wish to use it and you will have all of your custom functions available on any NSStrings objects.

Do you really need to subclass NSString? It’s a class cluster, which (apart from other things) means it’s hard to subclass. There’s a good post by Mike Ash on subclassing class clusters. If you didn’t know that class clusters existed you are probably new to Cocoa and in that case the best short answer is don’t try to subclass class clusters.
There’s also previous questions about subclassing NSString here on Stack Overflow. Next time you might want to search a bit before asking a new question.

Related

Realm and indexes on properties

CONTEXT
Realm does not support indices on relationship properties (objects). https://realm.io/docs/objc/latest/#indexed-properties
If you try, it'll throw an error.
We have a situation, where we need to query a model's relationship and another property.
Typically you would do this by having a covering index across (foreign_id, property), but this does not appear to be possible in Realm (yet?)
For example
#interface Book : RLMObject
#property NSNumber<RLMInt> * page;
#end
#interface Page : RLMObject
#property Book * book;
#property NSNumber<RLMInt> * line;
#end
[Page objectsInRealm:realm where:#"book.uuid = %# AND page.line = %#", uuid, #1];
QUESTION
What is the best way to set up indices so that the query above is optimal?
Are relationships already indexed?
Or Do I create another property on Page, called book_uuid, and index on that?
Cheers
Realm doesn't really cater to the foreign key mechanism of relational databases, so it's easier to get out of that mindset when designing your data model.
In this case, I think it would be more appropriate that your Book model stores an array of all of your pages (sort of an inverse to the foreign key concept), which you can use to initially filter the pages to just that book, and to then query for the specific page line:
#interface Page : RLMObject
#property NSInteger line;
#end
RLM_ARRAY_TYPE(Page)
#interface Book : RLMObject
#property RLMArray<Page *><Page> *pages;
#end
Book *book = [[Book allObjects] firstObject];
Page *page = [[book.pages objectsWhere:#"line = %#", #1] firstObject];
As long as you've marked line as an indexed property, this should work very quickly in theory. But since you've mentioned you've got thousands of page lines, I'd be curious to see what the real-world performance of this would be.

Realm Objective C: No visible #interface for 'RLMObject' declares the selector 'createOrUpdateInRealm:withValue:'

Cannot figure out why I get this error.
No visible #interface for 'RLMObject' declares the selector 'createOrUpdateInRealm:withValue:'
I have included the Realm/Realm.h header
Define my RLMObject in this manner
Class aClass = NSClassFromString(modelName);
RLMObject *m = [[aClass alloc] init];
Then I create a NSMutableDictionary to contain values which I want to partially update on the RLMObject.
NSMutableDictionary *updateValues = [[NSMutableDictionary alloc] init];
And then I call createOrUpdateInRealm:withValue: on m
[m createOrUpdateInRealm:realm withValue:updateValues];
But I get the error. I have no idea why this happens?
createOrUpdateInRealm:withValue: should be called on your subclass, not on an instance.
You should use it like this:
CustomObject *myCustomObject = [CustomObject createOrUpdateInRealm:realm withValue:dictionary];
where CustomObject is a subclass of RLMObject.
+createOrUpdateInRealm:withValue: is a class method of RLMObject, not an instance method. This means you need to call it on your subclass directly, not on an instance of your subclass:
[MyClass createOrUpdateInRealm:realm withValue:dictionary];

NSSrring lost value

I can`t figure out why my NSString lost its value in a IBAction.
I have in my .m the variable declaration :
#implementation myfile.m
NSString *text2=nil;
In (void)viewDidLoad I assign the value to text2 correctly, but when I fired the IBAction the debugger tells me the and text2 has lost the value.
The IBAction routine is placed in the .m file.
Please, anyone can tell me what I doing wrong ?
Advanced thanks
I know this is old, but just if anyone else stumbles upon it.
if you use ARC the nil value you assign basicly tells the compiler to dealloc when possible.
just do
#implementation myfile.m {
NSString *stringName;
}
- (void)viewDidLoad {
stringName = #"some-value";
}

KVC valueForKey return a __NSCFConstantString instead a __NSCFString

I use KVC in my projects.
And, in one of my classes, I wrote the property :
#property ( nonatomic, strong ) NSString *notes;
I want to put a NSString object in that property :
And before setting the value, I want to test the class name of the destination.
a = [ newContainer valueForKey:#"notes"];
if( a != nil && ![ b isKindOfClass:[ a class ] ] )
// here b is the new NSString value
The result is that xcode indicates that the classes aren't the same !
(gdb) po [ b class ]
__NSCFString
(gdb) po [ a class ]
__NSCFConstantString
I read that is not very important and that __NSCFConstantString is a private subclass of NSString.
But, in my case, I need to check all properties of my object before updating it.
And I don't want to had in my code :
// OK, classes aren't the same ...
// ---- BUT WE MUST test it again to know if a is a NSString and b a subclass of NSString or anything else ...
beurk !
Is anyone have the same problem ?
Thanks a lot for your help !
Three points:
1- You should check against [NSString class], the publicly exposed class of your property, not against the class of the current value of your property.
Imagine what happens when you check against the value class, instead of the property class: after setting your property to a NSMutableString, which is a perfect instance of NSString, you could not any longer set it to a regular NSString (since NSString is not a subclass of NSMutableString). Your current problem is a variant of the one described in this paragraph, which may be easier to understand.
2- The test should be done in the class that owns the property, not outside as you are doing now. Because only that class is entitled to know about the type of object it accepts.
3- So. Use the standard validateValue:forKey:error: method, which is your friend here. This method would be implemented by the class, and it would make sure notes is a NSString. Outside of the class, you would not check the type of the value directly, but ask the container class to validate it.
And voilà !

Synchronizing arbitrary properties in an object transparently in D

Let's say I have a class like so:
class Gerbil{
int id;
float x,y,z;
}
Let's further say this is part of a real-time simulation where I have a server/client setup and I change a property on the server-side:
//...
gerbil.x = 9.0;
//...
Now I want to send over this change to the client to synchronize the world state. However, the problem is I have potentially vast amounts of gerbils, and these gerbils also potentially have long lists of properties—not just x,y,z as depicted here.
My question is: Is there a way we can intercept these property assignments, transparently, and compile a diff from them?
From reading the D reference I got the impression opAssign might be the right thing, only there's actually no examples of how to use it? (D Ref. / opAssign) I suppose it would look something like this, but I'm just shooting from the hip:
void opAssign(string name)(float val){ //Just guessing here
if(name in floatProps){
if(isServer){
changedProps.push(this.id, name, val);
}
floatProps[name] = val;
}
}
And then opAssign would be called when we do:
gerbil.x = 9.0; //Same as gerbil.opAssign!("x")(9.0) ??
Apart from possibly wrong syntax, is this a step in the right direction? What is the right syntax? What about performance? It looks like it could be quite slow? Is there a faster, more "direct" way of this?
What I'd really like to avoid here are elaborate setups like:
gerbil.incProp(Prop.X, 9.0);
Thanks for your time.
Building on Jonathan's answer, I use code like this in a number of my libraries:
public template property(string name, T) {
mixin(`protected T _`~name~`;` ~
propertyGetter!(name, T) ~ propertySetter!(name, T));
}
public template property(string name, T, T def)
{
mixin(`protected T _`~name~` = `~def.stringof~`;` ~
propertyGetter!(name, T) ~ propertySetter!(name, T));
}
template propertyGetter(string name, T) {
enum propertyGetter = `public T `~name~`(){ return _`~name~`; }`;
}
template propertySetter(string name, T) {
enum propertySetter = `public typeof(this) `~name~`(T value){ _`~name~` = value;`~
`/* notify somebody that I've changed here */`~
`return this; }`;
}
The mixin strings are a bit ugly, but they preserve the proper line count.
I add properties to my classes like this:
class Gerbil {
mixin property!("id", int);
mixin property!("x", float);
mixin property!("y", float, 11.0); // give this one a default value
}
If you wanted, you could add some code to the propertySetter template that notified some sort of monitor that it had changed (passing id, property name, and new value). Then the monitor could transmit this info to a corresponding monitor on the server side who would find the object with proper id and set the specified property to the new value.
Overloading opAssign() is like overloading the assignment operator in C++. It's for assigning to the object itself, not one of its members. It's really not going to do what you want. I believe that the closest that you're going to get is properties:
class Gerbil
{
public:
#property int id()
{
return _id;
}
#property id(int newID)
{
//... Do whatever interception you want.
_id = newID;
}
#property float x()
{
return _x;
}
#property x(float newX)
{
//... Do whatever interception you want.
_x = newX;
}
#property float y()
{
return _y;
}
#property y(float newY)
{
//... Do whatever interception you want.
_y = newY;
}
#property float z()
{
return _z;
}
#property z(float newZ)
{
//... Do whatever interception zou want.
_z = newZ;
}
private:
int _id;
float _x, _y, _z;
}
#property enables property syntax so that you can use the function as if it were a variable. So,
//...
auto copyOfGerbilX = gerbil.x; //translates to gerbil.x()
gerbil.x = 9.0; //translates to gerbile.x(9.0)
//...
is now legal even though x is a function rather than a variable. You can insert whatever special handling code you want in the functions. And because the syntax used to access the variables is just as if they were public member variables, you can freely refactor your code to switch between having them be properties or public member variables in your class definition (assuming that you haven't tried to do something like take their address, since that doesn't mean the same thing for a variable as a function).
However, if what you're looking for is a generic way to not have to do all of those functions yourself, there is no direct construct for it. I believe that you could do it with compile-time reflection and string mixins or template mixins which would look at the list of your variables and then generate each of the property functions for you. However, then the extra handling code would have to be essentially the same for each function, and you'd have to be careful that the generated code was really what you wanted. I'm sure that it's feasible, but I'd have to work on the problem for a bit to produce a workable solution.
To generate such code, you'd need to look at __traits and std.traits for the compile-time reflection and at template mixins and string mixins for the code generation. I'd think twice about generating the code like that though rather than writing it by hand. It should be quite doable, but it won't necessarily be easy, debugging it could be entertaining, and if you're going to have to be fairly good with D templates and mixins to get it right.
But essentially, what you're looking for is to use #property functions so that you can add your handler code and then possibly use compile-time reflection along with mixins to generate the code for you, but generating code like that is a fairly advanced technique, so you may want to wait to try that until you're more experienced with D.

Resources