In the .h file of UICollectionView a comment says:
// If a class is registered, it will be instantiated via alloc/initWithFrame:
Is there a way that I can have it call a custom init method?
How about [cell configureForData:data] right after you dequeue it? You probably need to re-configure the data on dequeued cells, anyway.
Suppose there is a way that you can have it call a custom init method, you wouldn't pass anything to the custom init method by dequeueReusableCellWithReuseIdentifier:forIndexPath:, so setting up the data should be separate from the init method.
Related
I want to recall awakeFromNib when the tableView reload it's cells, to re-execuse the code I am executing there and newly load a pageViewController who is inside the cell, is that possible?
I believe awakeFromNib is called on an object when it is initialized from a nib file. So you can not call it manually.
Read this thread for object loading process from nib file.
See the documentation from apple about awakeFromNIb method
After all objects have been instantiated and initialized, the
nib-loading code reestablishes the outlet and action connections for
all of those objects. It then calls the awakeFromNib method of the
objects.
So, calling it manually looks not possible. Moreover I suggest you to put the lines of code in awakeFromNib into a seperate method and call that method. It will work for you.
As the other respondents point out, you should not call any of the "lifecycle" methods yourself. However, there is no reason on earth why you can't do something like:
override func awakeFromNib() {
super.awakeFromNib()
self.doSetupStuffINeedToRepeat()
}
func doSetupStuffINeedToRepeat() {
//...
}
Then you can simply call doSetupStuffINeedToRepeat() anytime you want. The reason that you shouldn't call awakeFromNib yourself is that, if done properly, it should call super.awakeFromNib, and doing this in the middle of execution may (will) really mess things up...
I'm trying to write an extension method on UIView that will be called whenever a view is initialized, meaning that the method should be invoked without my having to call on it explicitly. Is there a way to accomplish this such as with key-value observing?
This question already has answers here:
Is it possible to make the -init method private in Objective-C?
(9 answers)
how to block a superclass method to be called to a subclass
(5 answers)
Closed 9 years ago.
Suppose you have a UIView subclass. You define an init method "myInitWithFrame: ... andWhatNot:...". You know you won't be using the init method inherited from UIView ever and your custom init method does some vital custom initialising so that you want to force client classes to never use the inherited initWithFrame method.
Is it possible to hide the standard initWithFrame method that was inherited from UIView?
Actually, you can get compile-time warnings about calling a method on a subclass. Use the __attribute((deprecated)) attribute. If you want people to use -initWithPizza: instead of -initWithFrame:, do this:
#interface MyView : UIView
- (id)initWithPizza:(MyPizza *)pizza;
#end
#interface MyView (Deprecations)
- (id)initWithFrame:(CGRect)frame __attribute((deprecated("Use initWithPizza: instead")));
#end
Putting the -initWithFrame: declaration in a separate category is necessary to avoid Xcode complaining that you declared the method in the header but didn't implement it. Since you're just inheriting it from the superclass, that's fine; you don't have to implement it at all. But if you want to implement it to throw an exception, or call through to -initWithPizza: with a default argument, that's fine.
Of course, this won't stop UIKit from calling -initWithFrame: if it was already going to do so. But if you can guarantee that won't happen, then you're fine.
Actually, you CAN restrict with a subclass. You can override whichever methods you want to block in your subclass's .h file. You can make initWithFrame unavailable by placing the following in your .h file.
- (id) initWithFrame:(CGRect) frame __attribute__((unavailable("message")));
This will make the initWithFrame: method unavailable to anyone using your subclass.
To keep other code form calling this method, you can further restrict by putting this in your .m file.
- (id) initWithFrame:(CGRect) frame
{
return nil;
}
No. You can't prevent the users of your subclass from calling the methods of a superclass. You could override them and throw an exception inside, but that would just produce a broken subclass.
Remember that inheritance works as an "is a" extension, that is, instances of your subclasses should behave normally in any context that doesn't know about this particular subclass but knows about its superclass. It's only in places that have explicit knowledge about your subclass that you can benefit from adding extra initialization and other methods.
For example, UIKit has no knowledge of your subclass. So if you want to make your UIView subclass available from a NIB, you need to use the initialization methods that will be called by the NIB loading system, namely initWithCoder:. You can simply call your own initialization methods inside initWithCoder:. But if there are any additional parameters you would like to pass to the init method, you'll have to provide a way to configure them after initialization.
I recently did a programmatic alloc/init of a table cell subclass, and with some NSLog's, I was able to learn that pretty much all of the initializers were being called even though all I did was alloc/init, if I recall correctly.
init
initWithStyle
What is the logic to this?
Which one calls which?
Everything traces back to init. A UITableViewCell is a subclass of NSObject, so it has an init method.
initWithFrame is deprecated, and has been for some time (since iOS 3). You shouldn't be using it.
It was replaced in iOS 3 with initWithStyle, which you use to indicate what style of cell you'd like to create.
initWithCoder is another NSObject method, part of the NSCoding protocol. Again, you can see it in UITableViewCell because it is a sub-class of NSObject. initWithCoder is used to unarchive an object (perhaps you have saved an object directly to a file, for example).
You can tell which calls which by looking at the order in which the log messages appear.
A common pattern in Objective-C code is to have a "designated initialiser", which actually creates and returns a configured instance of the class. All of the other initialisers call the designated initialiser with fixed values for some of the parameters that weren't specified by the caller, or provide further configuration once the designated initialiser has returned.
I am writing a custom subclass of UITableView. I would need this object itself to be its own data source and delegate, and this subclass would then have its own data source and delegate. This is done primarily so I can intercept calls to the datasource and delegate and potentially augment them before sending them off to their actual datasources.
My class is defined as so.
CustomTableView : UITableView<UITableViewDelegate, UITableViewDataSource> {
...
id customDataSource;
id customDelegate;
}
The problem comes when I try to set my data source and delegate.
I would like to override uitableview's properties:
- (void)setDataSource(id<UITableViewDataSource>)ds {
[super setDataSource:self]
customDataSource = ds;
}
Basically, I would like to tell the parent class(UItableView) to set the data source to self. I would then forward any callbacks to the customDataSource, after I have modified them.
[super setDataSource:self] doesnt crash, but the datasource never gets set. Does anyone have any ideas? Thanks
I ended up not needing to use the method proposed in this question, but I did get it working. The problem was that I had accidentaly synthesized the properties that needed overriding, namely dataSource and delegate.
For people who need to do this in the future, simply override setDelegate and setDataSource in your custom subclass.
Dont assign the datasource to self. Create an intermediate object, which you contain in your CustomTableView, and set the datasource to that. Call it DataSourceInterceptor or something.
Another way to accomplish this would be to method-swizzle the datasource object that is being set.