Why does UITextView use string rather than mutable string for its text property? - iphone

Any idea from a code design standpoint why does the internal implementation of UITextView uses an NSString but not an NSMutableString when its content is meant to change often?

From a general coding point of view:
When setting a property the property setter method is called. That way the control is able to notice when the property is changed, so that it can redraw the control with the new content.
If the property is a mutable object, you can change its contents and the control will not get any notification that this has happened, so it doesn't know that the control needs to be redrawn.

It's a general pattern in Cocoa to pass around immutable objects instead of allowing outside classes access private mutable variables. You'll see the same thing with collections classes like NSArray and NSDictionary.

Of course, there's no reason you can't change what it points to! Because the member is just a pointer, you can replace the string with an NSMutableString yourself if you want.
This might be a more efficient approach if you want to append a lot of text to the view.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[myTextView setText:[[NSMutableString alloc] init]];
}
return self;
}
Just be sure to still call setText to because as #Guffa explained in his answer, otherwise the view won't know to redraw itself.
- (void)appendText:(NSString*)text
{
NSMutableString *dispText = (NSMutableString*)[myTextView text];
[dispText appendString:text];
[myTextView setText:dispText]; // notify myTextView of text change!
}

Related

Making Xcode complain about a missing parameter

I am designing a new application by modernizing code I wrote in the past. This old code uses the class/delegate model and I am trying to transform them to use blocks as callbacks, not the delegate stuff.
What I do is to create a property like
#property (nonatomic, copy) void (^onTouch)(NSInteger index);
That would pass to the object using that class a block where code can be inserted and in this case executed on touch.
But my problem is this. When you use delegates and you have a method on the delegate protocol, Xcode will warn if you use that class and forget to implement the delegate protocols. Is that a way to do that with blocks? Or in other words: is there a way to make Xcode complain if a callback block is not defined by the caller?
I mean this would be the correct:
MyClass *obj = [[MyClass alloc] init];
obj.onTouch = ^(NSInteger *index){ //call back code to be executed };
This would be OK too
MyClass *obj = [[MyClass alloc] init];
obj.onTouch = nil;
but this would generate a message
MyClass *obj = [[MyClass alloc] init];
// no callback block defined.
Is this possible?
If you want to enforce setting a certain parameter, I would include it in the initializer.
MyClass *obj = [[MyClass alloc] initWithBlock:^(NSInteger *index) { /* code*/ }];
Then, in MyClass:
- (id)init {
// This will result in a runtime error if you use the wrong initializer.
NSAssert(NO, #"Use initWithBlock instead.");
}
- (id)initWithBlock(initWithBlock:^(NSInteger *)block) {
self = [super init];
if (self) {
self.onTouch = block;
}
return self;
}
Also note, attempting to execute a NULL block results in a crash, so make sure to do:
if (self.onTouch) { self.onTouch(); }
Wherever you run the block.
First, I strongly recommend defining types to represent your blocks - makes them a lot easier to work with, especially if you need to refactor the parameters.
You can't write code that distinguishes between "I set this property to nil" or "the runtime initialized this property to nil", at least not without some crazy runtime code to check the stack. Only option I can think of would be to use the null object pattern. Before I elaborate, bear in mind that I haven't actually tried to test this, but it should work. Define a block that means 'has no value' and set your property to point to that block on init. Then you can compare to that NullBlock at runtime to identify if someone explicitly set the property to nil (because it would be nil at that point) or gave it a real non-nil value.
Alternatively, if you don't mind manually writing your set accessors, you could have a BOOL that tracks if someone set the property explicitly. Then when you call the block just check if someone actually set the value or not.
#synthesize onTouchBlock=_onTouchBlock;
MyBlock _onTouchBlock;
BOOL _onTouchBlockWasSet;
- (void)setOnTouchBlock:(MyBlock)block {
_onTouchBlockWasSet = YES;
_onTouchBlock = block;
}
I would not recommend passing the value in the initializer because that makes it tied to the creation of that object type. If you wanted to change the block in code based on some condition, you'd be back to square one. Also, it prevents you from using storyboards which create that object.

REAL DIFFERENCE between self.text and _text [duplicate]

This question already has an answer here:
What's the difference between _variable & self.variable in Objective-C? [duplicate]
(1 answer)
Closed 9 years ago.
i read a lot of post about this subject, yet i can't understand everything completely.
Ok, it's clear that
self.text = #"MyText" will call the accessory method setText (autogenerated)
_text = #"MyText" will still assign the value but will not call the setText
This is clear.
But this can be useful when we are not using ARC beacuse setText will take care of the memory management. But what happen when we are using ARC?
Sometimes if i am using _text everything works fine, some other time my application won't work if i wont use "self.text".
So what is the the real difference? There must be something more than memory management.
let's say i have this
#interface MyClass:NSObject {
NSMutableString *text;
}
#property (nonatomic ) NSMutableString *text;
in this case isn't it the same calling
self.text = #"ok"
or
text = #"ok" ?
what's the difference?
The underlying instance variable for that property is in fact _text. That is how auto synthesised properties work.
However you should consider using the accessors to set the property (using self. text = instead). See this link for more info on Reason to use ivars vs properties in objective c
self.text is syntactic sugar for [self text] (or [self setText:...], if on the left side of the assignment), and is a message; when it is autogenerated ("synthesised"), it will return the value of the connected instance variable. _text is this instance variable.
You can only access an instance variable within the class. You can send a message from anywhere. This distinction is important in case that one day you wish to modify the inner working of the text attribute so that it does not simply return the value of the local variable.
the answer is here really Do I need variable and property at the same time?
When you #property you're actually creating methods for accessing and mutating as well as an instance variable.
So when you have #property (nonatomic, strong) NSString *text; you create an iVar _text and two methods:
self.text; //will call -(NSString *)text;
self.text = #"text here"; //is calling -(void)setText:(NSString *)text;
#property is used to strip down boiler plate code, it reduces the number of lines of code required for you to write your classes.
Sure sometimes calling self.text = #"ok" and _text = #"ok" is alright in an ARC environment nowdays, but you don't get the -(NSString *)text; and -(void)setText:(NSString *)text; in your public header file.
Also, its often good practise to call self.text and self.text = or their equivalents [self text] [self setText:] as you might have overridden the text implementations:
-(NSString *)text{
return [NSString stringWithFormat#"%#.jpg", _text];
}
-(void)setText:(NSString *)text{
_text = [NSString stringWithFormat:#"DW%#", text];
}
So when you do this:
self.text = #"HelloThere";
NSLog (#"%#", self.text); //This will return DWHelloThere.jpg
NSLog (#"%#", _text); //Will return DWHelloThere
//whereas
_text = #"HelloThere";
NSLog (#"%#", _text); //Will return HelloThere
So #property can save you about 8 lines of code, keeps your own classes nice and tidy, and if need be you can override the accessors and mutators. But because of the latter point its good practise to call self.text and self.text = #"so and so" rather than just accessing the iVar by itself.
Conceptually, the difference is only that in one case a message is sent to the object or a single ivar is changed in the other. The memory management story is just a necessary house keeping that is handled for you by ARC if you use it.
If you are interested in the moral story, then read Jon Reid's post here: Dot Notation in Objective-C: 100% Pure Evil http://qualitycoding.org/dot-notation/
Side note: Whenever you can, use ARC. It will take care of the retain-release cycle automatically in most cases correctly (accessing self in blocks should be handled with care, though.) If you use ARC there is no difference between the two methods, the retain count will be handled correctly. And as you described, without ARC, you must make sure that after the property setting, the object must be released, while this is not necessary when the ivar is accessed. More on some practices is described in this post: Properties and Memory Management in Objective-C http://www.whilethis.com/2011/04/properties-and-memory-management-in-objective-c/
the real difference is that:
when you create your instance in your code you have a variable called text.
when instead you use the property on text, it will create an iVar called _text.
as you can imagine, calling one or another, will be a big difference since they are 2 totally different variables
self.text = #"Something" accesses to you private variable _text using accessor method [self setText:#"Something"]. The dot notation is just a syntactic sugar. This method can have its own implementation adding extra functionality to just setting value of private variable _text.
_text = #"Something" sets the value to the private variable itself directly.
Also, when setting text property's value outside the class implementation, the accessor [instance setText:#"Something"] is called automatically to set the value of private variable
Let me show you simple example what could be difference. The method implementation is simple just for educational purposes, so it may not make sense in real code :-)
Imagine you want to log a message to the console every time the value of text property changes. You can accomplish this by overriding the accessor method - (void)setText:(NSString *)text like this for example:
- (void)setText:(NSString *)text
{
// You can do whatever you want with the input "text" value, validate the value for example
// Here we just log the text was changed
// In the log message, we still have the old value of the "text" in the private variable "_text"
// so we can log it together with the new value
NSLog(#"Value of \"text\" property changed from \"%#\" to \"%#\"", _text, text);
// Set the new value of the private variable
_text = text;
// From here on, the private variable already has new value and the log line above
// would give the same values between from and to quotes
NSLog(#"Value of \"text\" property is now \"%#\"", _text);
}
So when you set the _text directly, none of the log messages above would be performed, because you access the variable directly.
On the other hand, setting using accessor method self.text = #"Something" would cause following to be printed out to the console:
Value of "text" property changed from "(null)" to "Something"
Value of "text" property is now "Something"

How exactly to subclass CALayer and use a custom property?

I am trying to create a subclass of CALayer with a custom index property that I can both animate and change directly in order to display a different picture based on the index.
In the header, I declared:
#property NSUInteger index;
In the implementation, I overrode needDisplayForKey:
+ (BOOL)needsDisplayForKey:(NSString *)key
{
if ([key isEqualToString:#"index"])
return YES;
else
return [super needsDisplayForKey:key];
}
Now, in the display method, I want to display a picture based on the index. However, during an animation, the value of self.index never changes, so I have to query the value of the presentation layer, contrary to the example on Providing CALayer Content by Subclassing:
- (void)display
{
NSUInteger presentationIndex = [(CustomLayer *)[self presentationLayer] index];
self.contents = (id)[[images objectAtIndex:presentationIndex] CGImage];
}
The problem is, if I do that, I cannot set the index value directly outside of an animation, because it will only change the model layer, and the display method explicitly queries the presentation layer.
If I add an initialization method that copies the value of index, it works:
- (id)initWithLayer:(id)layer
{
self = [super initWithLayer:layer];
if (self) {
if ([layer isKindOfClass:[CustomLayer class]])
self.index = [(CustomLayer *)layer index];
}
return self;
}
However, after or before an animation, there is always a 1 image glitch because the presentation or the model value don't match (depending if I set index to the destination value or not).
Surprisingly, it seems like the drawInContext: method always has
the right value for [self index], but it is not the method I want to use since I just set the content property with an image.
I get different behaviors depending on the way I implement the index property. If I use #dynamic index (which works, even though the documentation doesn't say that custom property getters/setters would be dynamically implemented), display is called every time the value of index is changed. If I use #synthesize or implement a setter, display is not called, so I would need to change content in the setter too.
Should I use an instance variable? Should I use the dynamic implementation? Or should I use setValue:forKey: instead?
As you can see, I am a bit confused about how to get the result I want, and how to correctly implement a subclass of CALayer with a custom property. Any help, and explanations, would be appreciated!
There is an excellent tutorial on the web that explains how to create a custom CALayer subclass with animatable properties. I haven't had occasion to try it yet, but I bookmarked it. Here is the link:
Animating Pie Slices Using a Custom CALayer
It looks like the main tricks are:
Use #dynamic, not #synthesize for the animatable properties of your custom CALayer.
Override actionForKey:, initWithLayer:, and needsDisplayForKey:, and perhaps drawInContext:

custom setter for NSString

I have a NSString called fontType
and I am trying to have a custom setter for it:
- (void) setFontType:(NSString *) fType
{
if (self.fontType != fType){
[fontType release];
self.fontType = [fType retain];
//some more custom code
}
}
Is there any issue with this?
A few things that stand out for me:
do not use self. inside of custom accessors. access the variable directly
it's better use copy semantics for properties of a type that has a
mutable subtype
be careful with whatever is // some more custom code
My personal style preferences are like so:
-(void)setFontType:(NSString *)fontType_ {
if (fontType == fontType_) return; // get out quick, flatten the code
[fontType release];
fontType = [fontType_ copy];
// some more code
}
Cocoa with Love has a good article on this topic. It's worth a read.
When you do self.fontType = newFontType, you are doing [self setFontType:newFontType] (just with a different syntax), this means you are calling the method inside itself.
This is called recursion, but in this case, you don't have a base case in which the method will stop calling itself, so my guess is that this method will call itself until the app crashes. In short, recursion is not something you want here.
Just replace self.fontType = [fType retain] with fontType = [fType retain] (Assuming the var linked to the fontType property is called fontType as well).
PS. At the end of the question you asked
Is there any issue with this?
If you didn't try this, then you shouldn't even be asking that here on StackOverflow, and if you did try it, then you should have realized that this method didn't work, so that last line is pretty meaningless. Just saying.

Initialize a class only once

I have a class that contains a few instance methods which need to be called from another class. I know how to do that -
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
[myTimeFormatter formatTime:time];
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I tried putting
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
"by itself", or not in any blocks, but when I compile, I get an "initializer element is not constant" error.
Any input is greatly appreciated!
You can use the singleton pattern. You can read more about it here.
Specifically, you'd do something like:
static TimeFormatter* gSharedTimeFormatter = nil;
#implementation TimeFormatter
+ (TimeFormatter*)sharedTimeFormatter {
if (!gSharedTimeFormatter) {
#synchronized(self) {
if (!gSharedTimeFormatter) {
gSharedTimeFormatter = [[TimeFormatter alloc] init];
}
}
}
return gSharedTimeFormatter;
}
...
#end
Notice that we check if the variable is null, and if it is, we take a lock, and check again. This way, we incur the locking cost only on the allocation path, which happens only once in the program. This pattern is known as double-checked locking.
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I think it's worth clarifying some OOP terminology here.
The reason you need to alloc and init TimeFormatter is because your methods are instance methods. Because they're instance methods, you need an instance, and that's what alloc and init provide. Then you call your methods on (send messages to) the instance ([myTimeFormatter formatTimeString:…]).
The advantage of allowing instances is that you can keep state and settings in each instance, in instance variables, and make the latter into publicly-visible properties. Then you can deliberately have multiple instances, each having its own settings configured by whatever's using that instance.
If you don't need that functionality, you don't need to make these instance methods. You can make them class methods or even C functions, and then you don't need a TimeFormatter instance. With class methods, you send messages directly to the class ([TimeFormatter formatTimeString:…]).
And if you do want settings shared among all instances (and you don't have any state to keep), then you're right that you can just have one instance—a singleton.
The reason for that parenthesis is that shared state is bad, especially if two threads may use the time formatter concurrently. (For that matter, you could say that about settings, too. What if one thread wants seconds and the other doesn't? What if one wants 24-hour and the other wants 12-hour?) Better to have each thread use its own time formatter, so that they don't get tripped up by each other's state.
(BTW, if TimeFormatter is the actual name of your class: You are aware of NSDateFormatter, right? It does let you only format/parse the time.)
Here's a detail example of a sharedMethod. Credit goes here
#implementation SearchData
#synthesize searchDict;
#synthesize searchArray;
- (id)init {
if (self = [super init]) {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"searches.plist"];
searchDict = [[NSDictionary alloc] initWithContentsOfFile:finalPath];
searchArray = [[searchDict allKeys] retain];
}
return self;
}
- (void)dealloc {
[searchDict release];
[searchArray release];
[super dealloc];
}
static SearchData *sharedSingleton = NULL;
+ (SearchData *)sharedSearchData {
#synchronized(self) {
if (sharedSingleton == NULL)
sharedSingleton = [[self alloc] init];
}
return(sharedSingleton);
}
#end
A very nice, and easy, way to setup a Singleton is to use Matt Gallager's SYNTHESIZE_SINGLETON_FOR_CLASS.
It sounds like you want to make TimeFormatter a singleton, where only one instance can be created. Objective-C doesn't make this super easy, but basically you can expose a static method that returns a pointer to TimeFormatter. This pointer will be allocated and initialized the first time in, and every time after that same pointer can be used. This question has some examples of creating a singleton in Objective-C.
You are trying to declare your variable outside the class? If to do it the way you want to do it you gotta declare it as static so
static TimeFormatter *myFormatter=...
From the name of the class though i dont see why you would wnat to keep one instance of your class... you can also do this with a singleton as described above, that is if you want to keep one instance of your class for the app as a whole.