I am trying to add pull to refresh to my app and am using the Pull to Refresh files here: https://github.com/leah/PullToRefresh However I am confused on how to make a subclass of my table view. How does one do that?
You mean something like this?
#interface MyTableViewController : PullRefreshTableViewController
{
//Member variables here.
}
// Methods and protocols here.
#end
Related
Sorry for a trivial (i suppose) question, but i have very small experience in programming for ios and in objective-c generally, so i can't figure by myself how to do some method in one place which will be working for all my view controllers (i don't want to multiply code by pasting this method in all my classes). It's a simple method which will connect to server in background thread and receive some data from it. This method is written i just need to figure how to make it work for all view controllers without multiplying code.
You have some choices:
Create a subclass of UIViewController and define all your ViewControllers subclasses of your custom class instead of UIViewController
Create a category of UIViewController with the implementation of the method
Create a class with your method declared as a class method:
E.g:
ConnectionManager.h
+ (NSArray *) getData;
ConnectionManager.m
+ (NSArray *) getData{
//method implementation
}
And you can call it from your view controllers like this:
[ConnectionManager getData]
A variant of this last option is to create a singleton object.
It seems very odd to do this "for all view controllers". Connecting to a network to get data would seem to be specific to each view controller to me.
Anyway, you could do something like this in a category.
#interface UIViewController (MyDataConnection)
- (void)thisIsYourMethodHere;
#end
and...
#implemnetation UIViewController (MyDataConnection)
- (void)thisIsYourMethodHere {
// do your networking stuff here.
}
#end
This means that in any view controller you can do...
[self thisIsYouMethodHere];
And it will run the code in the category.
I have application (UICatalog from Apple samples). I am using it with a framework called Lookback which is intended for screen recording.
I have interface defined as follows:
#interface AAPLSteppperViewController : UITableViewController
So it is in a straight way a subclass of UITableViewController. And it has implemented a methods as follows:
+ (NSString*)lookbackIdentifier {
return #"Profile Editor";
}
I wanted to investigate how lookbackIdentifier is being called and see something like that:
The question is: how to introduce such behavior as UITableViewController is a system class and I am not able to see the source of calls numbered 1 and 2 at the stack?
As I investigated framework docs, they recommend to implement always like that
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
...
}
As for me it looks like a change inside UIViewController - but how to achieve something like that?
I guess that it will include some playing with UIViewController but - how? I can't imagine how to override a single method of it without subclasssing.
I have only access to my AAPLSteppperViewController.
I would be grateful if somebody could give me a push in the right direction
As #dan pointed - swizzling is the right answer. I tried with instructions there: http://nshipster.com/method-swizzling/ and it gave me desired behaviour.
Thanks for help :)
I'm trying to category UIViewController to override viewWillAppear:. But getting this warning.
Category is implementing a method which also be implemented in primary
class
#implementation UIViewController (ViewWillAppearCategory)
-(void)viewWillAppear:(BOOL)animated
{
//.........
}
#end
I want to do some stuff during view appear in all screen, So I don't want to touch in all screen. that's why, go with category.
I may implement some method in sub class and I can call that method in all VC(all Screen). But I don't want this. It automatically invoke in view will appear call. Is this any idea to do this or did any mistake in above?
Note: This code will only appear in development phase for some testing purpose. So I'll remove this code when go with app store. So It should be easier task during removal, that is I won't touch all screen. I won't keep this code during submission to app store.
In such cases you must try Method Swizzling, a very nice formed concept which allows you to change the implementation of an existing selector.
For more details and code please visit the link below.
http://nshipster.com/method-swizzling/
categories are for adding new methods, not overriding existing ones. Maybe make a subclass of UIViewController, say, MyUIViewController, with this code:
-(void) viewWillAppear:(BOOL) animated {
// do your "category" stuff
}
then make all your other UIViewControllers subclasses of MyUIViewController with this code:
-(void) viewWillAppear:(BOOL) animated {
[super viewWillAppear:animated];
// rest of code for this class
}
I understand the reasons why you want to have a simple solution to test something on all screens and remove it easily, however:
You can not call super in a category, and not calling [super viewWillAppear:] may have unexpected results depending on the class and its particular implementation.
Swizzling methods is a hack and as you'll remove it from your final version, your testing version becomes useless as it may behave very differently.
On the other hand creating a UIViewController superclass where you properly override viewWillAppear: is not that complicated:
The code will belong only to a single class. No need to repeat/maintain code for every "screen".
You only need to change the other controllers' superclass and Nibs or Storyboards references once.
You can keep the superclass for both testing and release and the behavior will be similar.
You can do so many more things in a superclass than in a category.
Ultimately it would be interesting to know what are you trying to achieve. You could probably achieve similar things by implementing a UINavigationControllerDelegate and keep track of controllers getting pushed and popped.
As for viewWillAppear documentation:
This method is called before the receiver’s view is about to be added
to a view hierarchy and before any animations are configured for
showing the view. You can override this method to perform custom tasks
associated with displaying the view. For example, you might use this
method to change the orientation or style of the status bar to
coordinate with the orientation or style of the view being presented.
If you override this method, you must call super at some point in your implementation.
Again, you can't do that from a category.
As you are saying the code is going to be executed only in debug mode. Then why do you worry about warnings let the warning come you continue your work when it comes to release you remove your Category.
If you don't even need to see the warning your go with your same answer like
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"I get callback here too");
}
#pragma clang diagnostic pop
But I would say to go for subclassing because removing the existing class is also not that hard in XCode tool.
What you want to achieve defeats the purpose of a Category. However, there's another way aside from subclassing UIViewController but you have to touch the viewWillAppear method for each controller.
//UIViewController+CustomCategory.h
#interface UIViewConctroller (CustomCategory)
- (void)performCustomization;
#end
//UIViewController+CustomCategory.m
#implementation UIViewController (CustomCategory)
- (void)performCustomization {
// Do custom stuff…
}
#end
Then in each controller
//MYViewController.m
#import "UIViewController+CustomCategory.h"
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self performCustomization];
}
I have a problem with transfering data between viewcontrollers.
I`m now working on a small app, it has a main viewcontroller,and in this viewcontroller user can change some global data that all other viewcontrollers will use to fetch data from the internet. So, when the global data changes I need to tell other viewcontrollers to update data.
The question is how can I tell other viewcontrollers when the global data changes?
I know I should use NSNotificationCenter to solve this problem, but I feel notification is like a foreigner to all the viewcontrollers.
What I want to do is to add a ViewControllerManager to manage all the viewControllers. Firstly, I would add all the viewcontroller who need to use the global data to the manager.
Then ,when the global data changes I could find these viewcontrollers through the manager,and notify them to update the global data directly.
and this is my #interface.
#interface ViewControllerManager : NSObject
+ (ViewControllerManager *)sharedManager;
- (void)addViewController: (UIViewController *)viewController;
- (void)removeViewController: (UIViewController *)viewController;
- (void)removeViewControllerByClass: (Class)aClass;
- (UIViewController *)viewControllerByClass: (Class)aClass;
- (NSArray *)viewControllersByClass: (Class)aClass;
//get viewcontrollers who can response to selector, so I can send them this message.
- (NSArray *)viewControllersResponseTo: (SEL) selector;
//get current visible viewcontroller.
#property (nonatomic, retain) UIViewController * visibleViewController;
#end
It works well, through this manager I can get any viewcontroller I want, and I can transfer global data easily between viewcontrollers, But the problem is I don't know how to manage the memory correctly, in method [ViewControllerManager addViewController: ], I retain the viewController ,But I don`t know when to release it ,so this viewController will never be dealloc...
The latest point in time where you have a possibility to release is in your manager class's dealloc method. If you store those controllers in an array at the moment of adding them the array also retain them. It might be a solution to retain and release that array only, not the controllers. When an item is removed from an array the array does the necessary releasing. Also when an array is gone (released), the items are gone as well (automatically).
By the way what you are doing is called Mediator pattern I think. The controllers talk only to a central object not to each other. Only the mediator knows all the actors.
Finally , I solved this problem by using weak reference, and this is the code: https://github.com/github-xiaogang/ViewControllerManager
If I have a uitableview within a uitableview (yes the cells of the toplevel tableview are tableviews, but never mind that) on a tabbar tab and the user selects a row how can I get access to the selected item from my appdelegate and from the tabbar tabs
Mainly the question I have is if you have a var somewhere deep in your view heirachry how can a tabbar viewcontroller or the appdelegate get hold of it?
I usually use specific class to hold such variables. The source looks something like this:
static UIView *__someView = nil;
#implementation VariableContainer
+ (void)setSomeView:(UIView *)someView {
__someView = someView;
}
+ (UIView *)someView {
return __someView;
}
#end
When you create some object you want to access from some distant object you just call [VariableContainer setSomeView:] and when you need to access it [VariableContainer someView].
This is just one of many ways you can achieve this same result. A few tips about this one:
for every custom object (such as your app delegate) put in header "#class objectName"
try importing this container only into source files (no headers)
do not use retain, only have weak links
you can put as many objects as you wish so have only 1 container
I hope this helps a bit.