How do we implement selectionRectsForRange: from UITextInput Protocol? - objective-c

How do we implement selectionRectsForRange: from UITextInput Protocol ?
Has anybody figured out this one?
Is it just very dependent upon specific use-case needs? Or is there something in the frameworks that will call this method?
To silence the compiler it is of course appropriate to stub out the method, but will returning nil or an empty NSArray cause any harm?

According to session 220 at WWDC12 this method was added to support subclassing of UITextView where the implementation renders its own text. Sadly their sample code from that session isn't available, would love to peek at it to see if I've missed anything in my implementation.
It's fairly similar to how you'd implement -firstRectForRange: except you'd return all rects which covers the current selection.
Furthermore you'd have to subclass UITextSelectionRect (it's an abstract class like UITextPosition/UITextRange) which you'd return an array of from this method. Make sure to calculate the containsStart and containsEnd properties correctly and only return YES for one of each once across all the selection rects you return. These properties are used by UITextView to decide on where to place the selection resize "paddles".
Returning an empty array (or nil I suppose) would indicate that UITextView shouldn't draw any selection rects for the current selection.

Related

What type of parameters should be in a custom initializer?

When adding a custom initializer to a subclass, are there any rules as to what kind of parameters it should take? As an example, is there a particular reason why UIView doesn't have the initializer below, and would there be any argument for not adding it to a custom subclass of UIView?
- (instancetype)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor;
I haven't been able to find an answer to this on the web, so I hope that some of you can enlighten me.
You can add anything in there. But then you can add so many that it becomes ridiculous...
initWithFrame:backgroundColor:tintColor:alpha:hidden:userTouchEnabled:...
It really depends on what you're using the subclass for.
For instance, you might create a PlayingCardView subclass. This is going to have certain properties... suit, faceValue. Because every card MUST have a suit and face value it makes sense to put these into the init method.
So it would be sensible to create an initialiser...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue;
because every card has to have a suit and a face value.
Equally, you could have another property backImage to set the image on the "back" of the card. So you could have...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue backImage:(UIImage *)backImage;
Now you can use one of two initialisers. One for the "default" back image the other to set a custom back image.
Then you get into designated initialisers in this case, it would be preferable not to have repeated code in both init methods so you would make the first method like this...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue
{
UIImage *defaultBackImage = [UIImage imageNamed:#"defaultCardImage"];
return [self initWithSuit:suit faceValue:faceValue backImage:defaultBackImage];
}
And the designated initialiser would do all the actual setting up of the card.
In reality though, there is no fixed way and no correct way of doing this and it can take a while to find a pattern that you find easiest/best to use.
Your custom initializer can take any parameter you want to. As any other class, UIView define some let's say basic behaviour, so if you need any other behaviour you are free to add it using a subclass for example. Don't complain that UIView or any other classes don't have methods that you think would be good for them to have.
I would recomend you not write a custom initializer which has many arguments because it increase the complexity. Think exactly what is needed for that classes to be initalized correctly.

Right way to create a customizable uiview

this question is about "style", because i think this is a very common problem and i'm looking for an elegant solution.
I have created some "advanced" UIView and i try to make them very customizable.
Usually i create the UIView structure inside a custom init method, but i need to know the value of all customizable parameter inside init method so sometimes i need a very long init method like:
initWithFrame:color:font:verticalspace:verylonglist:
I tried to use delegate design pattern but i need also to pass delegate inside init method.
My actual best solution is to leave empty the init method and move everything about layout inside a "configure" method. everytime i chance a property like background color or font i will call this method and i will rebuild the view.
I think there is a best way to solve this problem...
I'd be curious to see the code of UITableView Class, because with that class you can pass a delegate outside init method.
Check out something like a UIButton or UILabel. They both have tons of configurable aspects, however to simply create an instance of one of those objects, they need very little information.
In general, provide init methods that allow the consumer of your class to specify the least amount of information for the class to work.
If you do want to give the consumer a way to initialize the class with a bunch of values, consider using some sort of initWithDictionary: method that takes an NSDictionary of parameters. This keeps your method names short and allows the user to customize an arbitrary number of settings for your class.
You could also consider providing a way for the consumer to request an instance with some standard set of values. UITableViewCell, for example, has an initWithStyle:reuseIdentifier: method. The important part is the style - UITableViewCell provides several default styles like UITableViewCellStyleDefault and UITableViewCellStyleSubtitle.
I don't know if it is the standard/best practices way but I use a dictionary in cases like this and pass that to an initWithDictionaryinitializer. Would be possible too to create a class method that returns a 'default settings' type dictionary which can then be customized (and delegate set), so that not every param needs to be specified whenever the class is used.

Reusing codes between in two similar subclasses Objective C

I have a bit of code that I use to draw a border around a NSTextField when mousing over it, and while editing it, as well as to have it resize vertically when the user is typing. I want to use this code on an NSTokenFieldCell now. I've gotten it to work fine, and the implementation is identical for both NSTextField and NSTokenFieldCell. I was wondering if there was some way I could avoid the need to duplicate my code between the two class types. I believe NSTokenFieldCell is actually a subclass of NSTextField.
I ended up pulling all my custom functionality out into a separate NSObject class, and then gave both my NSTextField and NSTokenField classes an instance of it, then I just proxied all of the custom logic into my "logic" object using - (id)forwardingTargetForSelector:(SEL)aSelector
It's not perfect as I still need to manually proxy over the methods that I overrode such as drawRect in each class, but I'd say it falls into the "good enough" category now. I'm interested to see if anyone has a better solution I can try.

Making classes work together in obj-C

I'm writing a program for iPhone that will first let the user take a photo, then will dynamically retrieve a colour of the place where the user taps on the image, and draw a rectangle of that colour. I have two relevant classes for this: AppViewController and AppView. The former contains all the UI elements and IBActions, the latter the position of last tap, the touches-handling methods and the drawRect (and a static method to get colour data at a given coords of an image).
What I wanted to do is to put the touch-handling (calling drawRect in touchesMoved/Ended) and the drawRect in the AppViewController. That doesn't work, since that class doesn't inherit from UIView, but from UIViewController. What's the correct way to do that?
Another way to phrase that: How to constantly change something (well, constantly as long as the user is swiping across the screen) in a class that doesn't support touch-detection methods?
(This probably doesn't explain it well. Please ask clarifying questions).
I think the delegate pattern might be helpful to you in this situation. You could call your delegate's shouldUpdateRectangle selector in touchesMoved/Ended.
There is not really a correct way to move the view's behaviors into a view controller, since that is not the way the classes are meant to be used. You should probably look at what's driving you to try to subvert the framework's design this way, because that is likely going to be easier to fix.
It's not uncommon, though, for a view to call out to a supporting class for help in this stuff. You could certainly have your view's drawRect: call methods in the view controller, though I would be careful about mixing their concerns too much, because it could get hard to figure out who's responsible for what.

Where do FirstResponder methods come from?

I'm looking at IKImageDemo supplied by Apple, the rotate round-slider is linked to a setRotation: method in the FirstResponder. However, none of the objects in the project seem to HAVE such a method, and yet the code works.
I'm trying copy this into my own project, and MY FirstResponder doesn't have a setRotation: method, so I'm not sure where it lives. Google has been unhelpful...
thanks.
Well, the first responder in the app happens to be an instance of IKImageView. IKImageView responds to the setRotation: selector (which can be seen by passing respondsToSelector:#selector(setRotation:) to any instance of IKImageView), although I cannot find where in documentation it mentions the setRotation: method
First Responder methods aren't magic. What happens when a message is sent to the first responder is that the app's current first responder (this is usually the focused view/control) is asked whether or not it implements the method. If it does, the method is called. If it doesn't, the next responder up the chain is asked, and so on until the top level (the NSApplication instance) is reached. The object must actually implement the method for it to be called, it can't just declare it.
In this case IKImageView implements -setRotation: as a private method. This means that the method is present (which is why the IKImageView accepts the message sent to the First Responder) but its use is not documented or supported. It seems odd that Apple would ship an example using a private method but there you go. It's definitely the case that sometimes methods are accidentally left out of the public headers when their use is supported, however it's generally wise to avoid private methods unless someone from Apple has specifically told you it's OK to use one.
You can generate headers for all methods of an Objective-C object, including private methods, from the binary using class-dump.
IKImageView has a public method -setRotationAngle: which is probably the way to go if you want to change the rotation.
I've found a way of resolving this annoyance. Even in the original Apple example, once you remove the binding for setRotation in the First Responder, you cannot put it back, unless doing this trick: simply use the Attributes Inspector for the First Responder and add a User Defined action "setRotation:" with type "id". Now even the yellow triangle in the First Responder binding for setRotation: in the Apple example disappears, and it shows up also in my own IKImageView instance.