NSTableView reloadData external class - objective-c

I have an NSTableview in class "spielplan", which I can reload easily with reloadData, but how can I reload the Table from my AppDelegate.m???
I think, there is a simple solution, but I don't get it!

Short answer: You shouldn't.
You class spielplan (which should be renamed to PMGameBoard) is probably a controller class that manages views, including the tableView. So it's the responsibility of this controller to reload the tableView's data should need be.
The external event from your app delegate, whatever it is, should be made available to the spielplan instance by some means of notification. The exact method of communication depends on the type of event (NSNotification, ...). See this objc.io article.

Create property or outlet (depends on do you use storyboard or not) in your spielplan.h file, for example
#property (nonatomic, strong) IBOutlets UITableView *myTableView;
and in the AppDelegate file get reference to spielplan object and call reload method:
[spielplan.myTableView reloadData];
If spielplan is subclass of UITableViewController you don't have to create outlet or property to the table view in your AppDelegate call:
[spielplan.tableView reloadData];
Bear in mind that when you try to get reference to your view controller from AppDelegate and the view controller is not in view hierarchy it can be deallocated or maybe it hasn't been allocate yet and call reloadData it doesn't make sense.

Related

Is it a good practice to subclass a UIViewController's subclass?

Say you have a 2 subclass of tableView controller.
They both have the same header and footer view on top of the bottom of the header. They both implement pull to refresh.
They both have some common features.
The only different is one is for displaying the whole businesses, the other is for displaying only businesses you bookmark.
It looks like they both need to have the same parent class and the different is resolved on the child class. The differences are minor anyway.
I suppose the parent has it's own XIB, the children has it's own XIB.
Hmm... How would that work out? With the exception of container UIViewController, each controller should view a fullview of content. So which view should we display? The child or the superClass? Should child view add it's superclass subview?
Anyone have ever tried that?
Any code sample on the web that use this approach?
It sounds like, based on the business logic you explain, that everything is in common, except the list of data you're presenting. You could expose a property on your UITableViewController subclass to set the business objects that your tableview presents:
#interface JTBusinessesTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *businesses;
#end
The code that instantiates this class would set the business objects:
JTBusinessesTableViewController *businessListings; //Instantiate from XIB or Storyboard
businessListings.businesses = [self bookmarkedBusinesses];
[self.navigationController pushViewController:businessListings animated:YES]
The code for displaying all businesses isn't going to be much different:
JTBusinessesTableViewController *businessListings; //Instantiate from XIB or Storyboard
businessListings.businesses = [self allBusinesses]; // Here we assign all of them
[self.navigationController pushViewController:businessListings animated:YES]
You're just selectively giving this view controller, the business objects to display.

Objective-C / iOS: Subclassing UITableViewController for a custom view

As we all know, table views in Cocoa Touch are one of the niftiest pieces of framework elements that's out there. As a convenience, Apple gave us a nice view controller class to encapsulate the functionality of a table view in a vc, the UITableViewController.
At the same time, there are times that we want to utilize the functionality of a table view without having it take up the whole screen. However, there seems to be no way to do this by subclassing UITableViewController. Instead, I had to hookup a table view and manually subscribe to the UITableViewDelegate and UITableViewDataSource. If I try to subclass UITableViewController, my app crashes before it can even put the view on-screen...
My question is, is there something I'm missing? When subclassing UITableViewController, I hook up my custom table view to the tableView property in UITableViewController. Is there something else I have to do?
UITableViewController only adds minor conveniences over UIViewController: it creates and positions the table view, hooks up the delegate & datasource (to itself, generally), passes the view controller editing property through to the table, and does a couple of useful UI bits when the view appears. (See [the docs][1] for details.)
Just about all of the above are either A) things that you're needing to change in order to have a non-fullscreen table, or B) things that you can do in a line or two each, and which UITableViewController only does for your convenience. For cases like this, you're better off using your own UIViewController subclass.
Step 1: Subclass UIViewController instead of UITableViewController
MyTableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
Step 2: Use interface builder to drop a tableView and custom View
Step 3: Declare the tableView property as IBOutlet in your MyTableViewController header file and bind it to the tableView in the interface builder
IMHO, This process would give you more flexibility.

Redrawing an NSView

Sorry if this has been asked before or it's a really dumb question, but I can't figure it out. I have an NSView in my interface, and I have created a subclass of NSView in Xcode. Then using the identity inspector, I set my NSView's class to be the newly created NSView subclass. The view draws fine, but now I need to redraw it to change a string inside the view. I'm pretty sure this has to do with setNeedsDisplay, but what do I send the message to? I don't have a particular instance of my view in the code, since it's in Interface Builder, so what do I do?
Again, sorry if this is dumb. I haven't done much with NSView yet. Ask for more info if you need it. Thanks!
In the view controller subclass you have, add an ivar with type of your NSView subclass. Declare a property on it, and mark it as an outlet.
// ViewControllerSubclass.h
ViewType *myView;
#property(readwrite, assign) IBOutlet ViewType *myView;
// ViewControllerSubclass.m
#synthesize myView;
Now you have an outlet, connect it to the view you designed via IB. To do so, right click in IB on your view controller subclass (the file's owner), you should see the outlet in the list.
Once you have done that, you are now able to send messages to the view in your code.
To mark the view as needing redraw :
[myView setNeedsDisplay:YES];

The relationship between UIViewController and UIView

I'm trying to understand how these two are connected. Every time you make a UIViewController does it also automatically come with its own UIView?
Also are these from Cocoa or Objective-C?
UIViewController is a Cocoa Touch class built for the purpose of managing UIViews. It expects to have a view hierarchy, but you don't "automatically" get a view (this is slightly inaccurate; see edit below). Usually you will obtain views by calling initWithNibName on your view controller.
There is some built-in magic in Interface Builder which knows that if File's Owner is a UIViewController (or subclass), there is a property called view. That's about it.
Once you have linked a view controller and a view, the view controller does a fair amount of work for you: it registers as a responder for view touch events, registers for device rotation notifications (and handles them automatically, if you wish), helps you take care of some of the details of animation, and handles low-memory conditions semi-automatically.
Edit: correction—if you don't call initWithNibName or set the view property manually, the view property getter will invoke loadView if view is nil. The default implementation of loadView will see if you've set nibBundle and nibName and attempt to load the view from there (which is why you don't have to call initWithNibName, most of the time), but if those properties aren't set, it will instantiate a UIView object with default values. So technically, yes, it does automatically come with its own UIView, but most of the time that's of little value.
UIViewController doesn't automatically come with a view. You have to make a view in the -loadView method. By default, this loads the view from the nib file you've specified. You can also override this method to make a custom view if you prefer not to use a nib.
Also, the view is not created right when the UIViewController is created. UIViewController uses a technique known as lazy-loading to defer the creation of a view until the view is actually accessed for the first time.

Which should I use, -awakeFromNib or -viewDidLoad?

I recently had a problem in my app where some of the subviews I was creating in a UIViewController subclass's -awakeFromNib method were disappearing from the view. After some poking around I found that moving the code I had put in -awakeFromNib to -viewDidLoad solved the problem. Seems that -awakeFromNib gets called only once when the UIViewController is unarchived from the nib, and -viewDidLoad gets called every time the view is unarchived.
So what's the best practice? It looks like UIViewController's -awakeFromNib shouldn't be adding any views to the view, that kind of stuff should be done in -viewDidLoad. Am I understanding this correctly? Or am I more confused than I thought?
awakeFromNib is called when the controller itself is unarchived from a nib. viewDidLoad is called when the view is created/unarchived. This distinction is especially important when the controller's view is stored in a separate nib file.
Also important is that the awakeFromNib function will never be called after recovering from memory warning. But, the viewDidLoad function will be called.
Yes, it's correct. You shouldn't really rely on awakeFromNib to do that kind of tasks.
awakeFromNib is similar to an event that's called after deserialization in .NET. viewDidLoad is similar to Load event in .NET.
If you are familiar with the concepts from .NET, this should be enough, I think.
I'll try to answer by giving an example:
If define customCell class and customCell.xib file, and then load the cell by using
- (NSArray *)loadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options, awakeFromNib gets called when the objects in the xib are unarchived.
If you define a customViewController, then when the customViewController is created using - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil. viewDidLoad will get called when it's loaded into view hierarchy.
Some related confusing methods:
(void)loadView; This is where subclasses should create their custom view hierarchy if they aren't using a nib. If you don't specify a nib name, then loadView will attempt to load a nib whose name is the same as your view controller's class. If no such nib exists, then you must either call -setView: before -view is invoked, or override the -loadView method to set up your views programatically. -loadView should never be called directly.
(void)viewDidLoad: Called after the view has been loaded. For viewControllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.
For a ViewController, IBOutlets are available in viewDidLoad()
Here stackView represents an IBOutlet in a ViewController, stackView is nil in awakeFromNib, but it has been instantiated when viewDidLoad() is called.