Whats the best way to setup & populate my nstableview with json data? - json

I'm sorry if this has already been answered. I'm a bit of a noob. From all the examples I've found I can't seem to work this out.
I'm building a mac osx application using Xcode 5. My interface that I've created in Interface builder has three tableviews. My data to populate these views is json format and it is being received successfully using NSURLConnection.
What is the best way to popular the tableviews? A lot of the tutorials I've followed use an arraycontroller that is dragged and dropped using IB. From what I understand I don't need an array controller and need to hand code controllers for each of tableviews. Is that correct? If so, please explain how I go about this and setup the bindings.
Also, when clicking on a column in tableview 1 I'm planning on making it adjust the data in tableview 2 & 3 so if that impacts anything please let me know.
Thanks in advance!
Update 6 Jan
Here is my code currently..
ContactsTableViewController.h
#import <Foundation/Foundation.h>
#interface ContactsTableViewController : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
IBOutlet NSTableView *contactsTableView;
}
-(id) init;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView;
-(NSView *) tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
#end
ContactsTableViewController.m
#import "ContactsTableViewController.h"
#implementation ContactsTableViewController
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
NSLog(#"numberOfRowsInTableView called");
return 1;
}
- (id) init {
NSLog(#"init called");
[contactsTableView setDelegate:self];
[contactsTableView setDataSource:self];
[contactsTableView reloadData];
return self;
}
- (void) initme {
NSLog(#"customfunc");
}
-(NSView *) tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSLog(#"viewForTableColumn called");
NSTextField *result = [tableView makeViewWithIdentifier:#"name" owner:self];// result is now guaranteed to be valid,
result.stringValue = #"My Name"; //[self.nameArray objectAtIndex:row];
return result;
}
#end
In my appDelegate:
- (void) awakeFromNib {
NSLog(#"AWAKE");
ContactsTableViewController *contactsController = [[ContactsTableViewController alloc] init];
}
Currently nothing is showing in the tableview and numberOfRowsInTableView & viewForTableColumn aren't getting called.

Look at the UITableViewDataSource, you need to implement the protocol in one of your classes, probable your view controller, implement the UITableViewDelegate to get row selection events in the same class.

Related

How to use the coords from locationManager in local HTML file?

Since iOS 6 has a bug with GeoLocation/WatchPosition to obtain the users position, I am implenting in xcode the locationManager and get the coordinates.
But, I want to use these coords in a local HTML (webView) file.
Is it possible to use,send or call the coords from locationManager to the HTML / JavaScript file?
EDIT:
I thought about a possible solution... cookies... can that be done because I can not get a output in my code below:
EDIT 2:
Yes it can... I adjust the code below and it works. Important is the Cookie domain and path option so webView (HTML) can get the cookie.
But if someone knows a better solution, please let me know, i like to learn!
- (void)applicationdidBecomeActive {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
...
NSLog(#"%#", DevicePosition);
NSDictionary *newCookieDict = [NSMutableDictionary
dictionaryWithObjectsAndKeys:
#".^filecookies^", NSHTTPCookieDomain,
#"DevicePos", NSHTTPCookieName,
#"/", NSHTTPCookiePath,
DevicePosition, NSHTTPCookieValue,
//#"2012-01-01 12:00:00 -0100", NSHTTPCookieExpires,
nil];
//create a new cookie
NSHTTPCookie *cookie = [NSHTTPCookie
cookieWithProperties:newCookieDict];
//add the new cookie
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
// dev cookie controle
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [cookieJar cookies]) {
NSLog(#"%#", cookie);
}
HTML file:
<script type="text/javascript">
function getCookie(name) {
var re = new RegExp(name + "=([^;]+)");
var value = re.exec(document.cookie);
return (value != null) ? unescape(value[1]) : null;
}
</script>
There is a simple way to soluve your question.
You can use WebViewJavascriptBridge to 'populate' a Objective C's method to webview, so your html page can access that method via window.xxx to invoke the method implemented in Objective C.
Please take a look at https://github.com/marcuswestin/WebViewJavascriptBridge

Trouble with new View Controller called from a UITextField Xcode

In the current App that I am writing, I have a UITextField that has a link in it. So I want to call a new View Controller instead of Safari. I can have it open in Safari, but I don't want the user to leave my App. I have done some research and am doing the following.
I made a new file called MyApplication and placed the following inside the .m file to override openURL
#import "MyApplication.h"
#implementation MyApplication
- (BOOL)openURL:(NSURL *)url
{
if ([self handleOpenURL:url])
return YES;
else
return [super openURL:url];
}
- (BOOL)handleOpenURL:(NSURL *)url
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"71"];
[self presentViewController:vc animated:YES completion:nil];
return YES;
}
#end
In the attributes inspector under View Controller I called the Title 71. I also called the storyboard ID and restoration ID 71 just to be sure! In the main.m file I have replaced the third nil with #"MyApplication" as you can see.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, #"MyApplication", NSStringFromClass([AppDelegate class]));
}
}
However, the App fails to build because in the method handleOpenURL I am getting an error on the line
[self presentViewController:vc animated:YES completion:nil];
It says No visible #interface for 'MyApplication' declares the selector 'presentViewController:animated:completion:' All the samples and questions I have seen are using the deprecated method presentModal but Xcode tells me to use this newer method presentViewController. So does anyone know what I am doing wrong? I must be missing something, but I can't for the life of me find out. Thanks in advance on any insight to this matter!!!
May be you're missing the :
#import <UIKit/UIKit.h>

Game Kit with iOS6

I recently tried to authenticate the local user on iOS 6 with the new iOS 6 method, and it returns in the authenticate handler-
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
How do I display this view controller? (FYI- GC automatically dismisses the window when completed authenticating the local player)
I'm using storyboard in the project.
Thanks!
Once you set the handler, it will be called at different situations. In those calls, the viewController parameter can be nil or it can actually be an instance GKHostedAuthenticateViewController.
You need to check if the viewController is not nil, and in that case, you can display it as you would do with any other view controller.
Here you have some sample code from the Game Center Programming guide
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil)
{
[self showAuthenticationDialogWhenReasonable: viewController
}
else if (localPlayer.isAuthenticated)
{
[self authenticatedPlayer: localPlayer];
}
else
{
[self disableGameCenter];
}
}];
}
Check out the GKLocalPlayer Class Reference and the Game Center Programming Guide

What is the proper way to unload views in iOS 6 in a memory warning (Apple doc flaw)?

In iOS 6, viewWillUnload and viewDidUnload are deprecated and UIViewControllers no longer unload views that are not visible on screen during a memory warning. The View Controller Programming Guide has an example of how to manually restore this behavior.
Here is the code sample:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Add code to clean up any of your own resources that are no longer necessary.
if ([self.view window] == nil)
{
// Add code to preserve data stored in the views that might be
// needed later.
// Add code to clean up other strong references to the view in
// the view hierarchy.
self.view = nil;
}
}
Below the code sample is the following note:
The next time the view property is accessed, the view is reloaded
exactly as it was the first time.
There is an obvious flaw here. If a view controller that has not loaded its view receives a memory warning it will load its view in the line if ([self.view window] == nil) and then proceed to clean up and release it again. At best, this is inefficient. At worst, it makes the memory conditions worse if a complex view hierarchy and supporting data are loaded. I verified this behavior in the iOS simulator.
I can certainly code around this but seems odd for Apple docs to have such an error. Am I missing something?
The correct check in a view controller for the view being loaded and on screen is:
if ([self isViewLoaded] && [self.view window] == nil)
My full solution in iOS 6 to have a view controller unload views and cleanup similar to iOS 5 is the following:
// will not be called in iOS 6, see iOS docs
- (void)viewWillUnload
{
[super viewWillUnload];
[self my_viewWillUnload];
}
// will not be called in iOS 6, see iOS docs
- (void)viewDidUnload
{
[super viewDidUnload];
[self my_viewDidUnload];
}
// in iOS 6, view is no longer unloaded so do it manually
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
if ([self isViewLoaded] && [self.view window] == nil) {
[self my_viewWillUnload];
self.view = nil;
[self my_viewDidUnload];
}
}
- (void)my_viewWillUnload
{
// prepare to unload view
}
- (void)my_viewDidUnload
{
// the view is unloaded, clean up as normal
}

UIViewController.navigationController becomes nil

I bumped into a problem where UIViewController.navigationController becomes nil and I'm desperately trying to find an answer to this one.
The UINavigationController gets setup in the application delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.rootViewController = [[RootViewController alloc] initWithNibName:#"RootView" bundle:nil];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:self.rootViewController];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}
When the RootViewController is appearing, the self.navigationController member is set and I can use it to hide the navigation bar, like so:
- (void)viewWillAppear:(BOOL)animated {
NSLog( #"self = %#, self.navigationController = %#", self, self.navigationController );
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
The debug output shows values for self and self.navigationController.
When a button is clicked in this controller, self remains the same value indeed but self.navigationController is now nil:
- (IBAction)buttonClicked:(id)sender {
NSLog( #"self = %#, self.navigationController = %#", self, self.navigationController );
// here, self.navigationController is nil, so
// [self.navigationController pushViewController:...] doesn't work :-(
}
I've seen dozens of questions regarding this problem and the answer is always that the UIViewController is not part of a UINavigationController. Since accessing the navigationController in viewWillAppear works fine, I believe something else must be going on. Do you have any pointers? I'll happily provide more detail if necessary.
Try this in the app delegate:
[(UINavigationController *)self.window.rootViewController pushViewController:yourViewController animated:NO];
the rootviewcontroller is actually UINavigationController if you po to debug it. This works for me.
Your code shows that you are only using the navigationController's view but just pray that navigationController life is handled by some magic hand which is not the case.
You need someone to be the explicit owner of the navigationController here.
In fact, the following line:
[self.window addSubview:navigationController.view];
seems to indicate that what you want is for the window's rootViewController to be navigationController:
self.window.rootViewController = navigationController;
But also, it seems that the application's delegate is to be an owner of navigationController as well so navigationController should, in fact, be an ivar of your app's delegate.
In short, fix your object graph (and it will coincidentally do the extra retain you manually did and fix your bug)
I had a problem with a nil view controller and found that it was not connected properly in storyboard to the app delegate.
As always, it helps to formulate the question just to find the solution some minutes later.
I fell prey to ARC, I guess. Once I retained the UINavigationController in the application delegate, it worked fine.