JSON and iPhone table view - ios

I'm trying JSON parser for first time and i need a little help
When I try to populate a table view it works OK, but when I scroll the table or select a row the app crashes. I would appreciate any help.
Here are the files I have:
#import <UIKit/UIKit.h>
#class RootViewController;
#interface BooksJsonAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
NSMutableArray *statuses;
NSMutableData *responseData;
}
#property(nonatomic, retain)NSMutableArray *statuses;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
and
#import "BooksJsonAppDelegate.h"
#import "RootViewController.h"
#import "SBJson.h"
#implementation BooksJsonAppDelegate
#synthesize window;
#synthesize navigationController,statuses;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://assignment.golgek.mobi/api/v10/items"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
statuses = [parser objectWithString:json_string error:nil];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Connection Failed: %#",[error description]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
}
- (void)applicationWillResignActive:(UIApplication *)application {
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
}
- (void)applicationWillTerminate:(UIApplication *)application {
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
}
- (void)dealloc {
[navigationController release];
[window release];
[super dealloc];
}
#end
then the root view controller
#import <UIKit/UIKit.h>
#class DetailView,BooksJsonAppDelegate;
#interface RootViewController : UITableViewController {
DetailView *detailView;
BooksJsonAppDelegate *booksAppDelegate;
}
#end
and
#import "RootViewController.h"
#import "DetailView.h"
#import "BooksJsonAppDelegate.h"
#implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
booksAppDelegate = (BooksJsonAppDelegate *)[[UIApplication sharedApplication] delegate];
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [booksAppDelegate.statuses count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSDictionary *aBook = [booksAppDelegate.statuses objectAtIndex:[indexPath row]];
cell.textLabel.text = [aBook objectForKey:#"title"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *aBook = [booksAppDelegate.statuses objectAtIndex:[indexPath row]];
detailView = [[DetailView alloc] initWithNibName:#"DetailView" bundle:nil];
// ...
// Pass the selected object to the new view controller.
detailView.title = [aBook objectForKey:#"title"];
[self.navigationController pushViewController:detailView animated:YES];
[detailView release];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end

You will probably need to retain your statuses
statuses = [[parser objectWithString:json_string error:nil] retain];
The JSON parser will return an autoreleased object :)
As Dan points out in the comments the better way of doing this is to set the property like this :
self.statuses = [parser objectWithString:json_string error:nil];
This has the advantage of not leaking memory if you set it twice and you can use KVO ot tell if it's changed. Much better :)

Are you sure booksAppDelegate.statuses is correctly populated?
You can check this by logging the json proces, after statuses = [parser objectWithString:json_string error:nil];
just add the following line: NSLog(#"%#",[statuses description]); to see what data is put into the dictionary

Related

Segue performing in story

I have three ViewControllers. In first I open thirdViewController and in thirdViewController I open secondViewController. I use segue to perform seondViewController, but id doesn't work.
#import "thirdViewController.h"
#import "ViewController.h"
#import "DetailViewController.h"
#import "secondViewController.h"
#interface thirdViewController (){
NSDictionary *currencies;
NSMutableArray *arrayCurrenciesKeys;
NSMutableData *webData;
NSURLConnection *connection ;
NSMutableArray *array;
NSMutableArray *temp;
}
#end
#implementation thirdViewController
#synthesize tableView,cityname;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title=#"Типи валют";
[[self tableView]setDelegate:self];
[[self tableView]setDataSource:self];
array=[[NSMutableArray alloc]init];
NSURL *url =[NSURL URLWithString:#"http:resources.finance.ua/ua/public/currency-cash.json"];
NSURLRequest *request =[NSURLRequest requestWithURL:url];
connection= [NSURLConnection connectionWithRequest:request delegate:self];
if(connection)
{
webData=[[NSMutableData alloc] init];
}
tableView.backgroundColor=[UIColor clearColor];
tableView.alpha=0.9;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return [array count];
}
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =#"Cell"; UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text=[array objectAtIndex:indexPath.row];
return cell;
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error");
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
NSDictionary *feed =[allDataDictionary objectForKey:#"organizations";
for(NSDictionary *diction1 in feed){
NSString *label1 = [diction1 objectForKey:#"cityId"];
[temp addObject:label1];
NSString *label2 =[[allDataDictionary objectForKey: #"cities" ] objectForKey:[NSString stringWithFormat:#"%#",label1]];
if(![array containsObject:label2]){
[array addObject:label2];}
else{
;
}
[[self tableView]reloadData];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"Banks" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"Banks"]) {
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Also i add segue identificator in the storyboard. I also try to present it with navigation controller,but it doesn't work too.
I have three ViewControllers. In first I open thirdViewController and in thirdViewController I open secondViewController. I use segue to perform seondViewController, but id doesn't work.
I assume that your "first" is ViewController.h
1- Are you sure that the identifier of the segue from thirdViewController to secondViewController is #"Banks"?
You can be misleading it with the identifier of the segue from ViewController to thirdViewController.
2- Double check that you have the exact same string in Interface Builder and in code.
It can be #"Bankss" in Interface Builder and can be #"Banks" in code.

Cant perform delegation

I have a table view controller and a view controller.
StackTableViewController - list of strings
HomeViewController - empty view controller with a label
The HomeViewController label should present always the first sting of the StackTableViewController.
I need to make sure if the first string is deleted to present the new first string.
And this is where I have the problem...if I delete the first string and going back to the HomeViewController, the label is still the string I just deleted....And if I terminate the app and open it again, the correct string shown in the label.
This is How I did it so far:
this is the relevant methods in my StackTableViewController.h + .m:
#protocol StackTableViewControllerDelegate <NSObject>
#optional
-(void)didDeleteObject;
#end
#interface StackTableViewController : UITableViewController <UITableViewDataSource,UITableViewDelegate>
#property (strong,nonatomic) id<StackTableViewControllerDelegate> delegate;
#property (strong, nonatomic) NSString *currentTarget;
#end
#import "StackTableViewController.h"
#import "Target.h"
#import "StackTableViewCell.h"
#import "HomeViewController.h"
#import "CoreDataStack.h"
#interface StackTableViewController () <NSFetchedResultsControllerDelegate>
#property (nonatomic, strong) NSFetchedResultsController *fetchedResultController;
#end
#implementation StackTableViewController
- (id)init {
self = [super initWithNibName:#"StackTableViewController" bundle:nil];
if (self) {
// Do something
[self.fetchedResultController performFetch:nil];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *current = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = current.body;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *current = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = current.body;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
Target *target = [self.fetchedResultController objectAtIndexPath:indexPath];
CoreDataStack *stack = [CoreDataStack defaultStack];
[[stack managedObjectContext] deleteObject:target];
[stack saveContext];
if ([_delegate respondsToSelector:#selector(didDeleteObject)]) {
[_delegate didDeleteObject];
}
}
And this is the relevant methods in the HomeViewController.h + .m:
#import <UIKit/UIKit.h>
#import "StackTableViewController.h"
#interface HomeViewController : UIViewController {
StackTableViewController *stackTableViewController;
}
#property (strong, nonatomic) IBOutlet UILabel *homeLabel;
- (IBAction)goToStack:(id)sender;
#import "StackTableViewController.h"
#interface HomeViewController () <StackTableViewControllerDelegate>
#end
#implementation HomeViewController
- (id)init {
self = [super initWithNibName:#"HomeViewController" bundle:nil];
if (self) {
// Do something
stackTableViewController = [[StackTableViewController alloc] init];
stackTableViewController.delegate = self;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.navigationController setNavigationBarHidden:YES];
self.homeLabel.font = [UIFont fontWithName:#"Candara-Bold" size:40];
self.homeLabel.text = stackTableViewController.currentTarget;
}
- (void)didDeleteObject {
self.homeLabel.text = stackTableViewController.currentTarget;
}
- (IBAction)goToStack:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
CoreDataStack.h +.m:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface CoreDataStack : NSObject
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
+ (instancetype)defaultStack;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
#import "CoreDataStack.h"
#implementation CoreDataStack
#pragma mark - Core Data stack
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (instancetype)defaultStack {
static CoreDataStack *defaultStack;
static dispatch_once_t onceTocken;
dispatch_once (&onceTocken, ^{
defaultStack = [[self alloc] init];
});
return defaultStack;
}
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "digitalCrown.Treats" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Treats" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Treats.sqlite"];
NSError *error = nil;
NSString *failureReason = #"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = #"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#end
Please help me to solve this, I was tying allot of ways but probably i'm missing something that got to do with view controller lifecycle or something.
(the CoreDataStack is a singleton)
tnx!!
I have noticed that you haven't exposed where and how do you go back as you said here:
And this is where I have the problem...if I delete the first string
and going back to the HomeViewController, the label is still the
string I just deleted
You have two choices to fix it:
1) Use viewWillAppear function and update the required text in it.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// get the most recent updates and assign to the UI
self.homeLabel.text = stackTableViewController.currentTarget;
}
So either you have just loaded this UI or coming back from the next UI, this will be going to help to get the latest updates.
2) Before calling popViewControllerAnimated make sure you have updated text.
if (_delegate && [_delegate respondsToSelector:#selector(didDeleteObject)])
{
// updated the UI through delegate
[_delegate didDeleteObject];
}
// This should be call when your work is done, since
// It will start ending the session of this UI so it will obviously
// miss the track of the `_delegate` variable.
[self.navigationController popViewControllerAnimated:YES];
Hope it helps!
I think you just need to reset your currentTarget property after you delete the object:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
Target *target = [self.fetchedResultController objectAtIndexPath:indexPath];
CoreDataStack *stack = [CoreDataStack defaultStack];
[[stack managedObjectContext] deleteObject:target];
[stack saveContext];
// The FRC should recognise that the deletion has happened, and consequently have updated its
// indexes, so the following will access the NEW first item, even if it has just changed:
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
Target *current = [self.fetchedResultController objectAtIndexPath:indexPath];
self.currentTarget = current.body;
if ([_delegate respondsToSelector:#selector(didDeleteObject)]) {
[_delegate didDeleteObject];
}
}
I think you'd be better off setting up your variables differently. Specifically, it seems like you would be better off to have a singleton object that holds and manages the stack for you, but here's a way to do what you have set up. I've written a basic app that includes all of its UI in code. Here are the pertinent files:
// AppDelegate.h
// StackTableTesting
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
// AppDelegate.m
// StackTableTesting
#import "AppDelegate.h"
#import "HomeViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
HomeViewController *vc = [[HomeViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
nav.navigationBar.translucent = NO;
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
#end
// Created by Michael McEvoy on 12/23/14.
// Copyright (c) 2014 Mustard Seed Software LLC. All rights reserved.
#import <UIKit/UIKit.h>
#import "StackTableViewController.h"
#interface HomeViewController : UIViewController
#end
// HomeViewController.m
// StackTableTesting
#import "HomeViewController.h"
#import "StackTableViewController.h"
#interface HomeViewController () <StackTableViewControllerDelegate> {
}
#pragma mark -
#pragma mark - Private Properties
#property (strong, nonatomic) StackTableViewController *stackTableViewController;
#property (strong, nonatomic) UILabel *homeLabel;
#end
#pragma mark -
#pragma mark - Implementation
#implementation HomeViewController
#pragma mark -
#pragma mark - Initialization
- (instancetype)init {
self = [super init];
if (self != nil) {
self.stackTableViewController = [[StackTableViewController alloc] init];
self.stackTableViewController.delegate = self;
}
return self;
}
#pragma mark -
#pragma mark - View Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUserInterface];
}
#pragma mark -
#pragma mark - StackTableViewControllerDelegate Protocol Methods
- (void)didDeleteObject {
self.homeLabel.text = self.stackTableViewController.currentTarget;
}
#pragma mark -
#pragma mark - Button Presses
- (void)goToStack {
[self.navigationController pushViewController:self.stackTableViewController animated:YES];
}
#pragma mark -
#pragma mark - UI Setup
// This is because there's no Storyboard
- (void)setupUserInterface {
self.homeLabel = [[UILabel alloc] init];
self.homeLabel.font = [UIFont fontWithName:#"Candara-Bold" size:40];
self.homeLabel.frame = CGRectMake(20, 20, 200, 50);
self.homeLabel.text = self.stackTableViewController.currentTarget;
self.homeLabel.textColor = [UIColor blackColor];
[self.view addSubview:self.homeLabel];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(20, 80, 200, 50);
[button addTarget:self action:#selector(goToStack) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Go To Stack" forState:UIControlStateNormal];
[self.view addSubview:button];
self.view.backgroundColor = [UIColor whiteColor];
}
#end
// StackTableViewController.h
// StackTableTesting
#import <UIKit/UIKit.h>
#protocol StackTableViewControllerDelegate <NSObject>
- (void)didDeleteObject;
#end
#interface StackTableViewController : UITableViewController {
}
#pragma mark -
#pragma mark - Properties
#property (weak, nonatomic) id <StackTableViewControllerDelegate> delegate;
#property (copy, nonatomic) NSString *currentTarget;
#end
// StackTableViewController.m
// StackTableTesting
#import "StackTableViewController.h"
#interface StackTableViewController () {
}
#pragma mark -
#pragma mark - Private Properties
#property (strong, nonatomic) NSMutableArray *stack;
#end
#pragma mark -
#pragma mark - Implementation
#implementation StackTableViewController
#pragma mark -
#pragma mark - Initialization
- (instancetype)init {
self = [super init];
if (self != nil) {
self.stack = [NSMutableArray array];
for (int i = 0; i < 10; i = i + 1) {
[self.stack addObject:[NSString stringWithFormat:#"Item %d", i + 1]];
self.currentTarget = self.stack[0];
}
}
return self;
}
#pragma mark -
#pragma mark - View Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
}
#pragma mark -
#pragma mark - UITableViewDataSource Protocol Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.stack.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
cell.textLabel.text = self.stack[indexPath.row];
return cell;
}
#pragma mark -
#pragma mark - UITableViewDelegate Protocol Methods
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
[self.stack removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
self.currentTarget = self.stack[0];
if ([_delegate respondsToSelector:#selector(didDeleteObject)]) {
[_delegate didDeleteObject];
}
}
#end
I think this setup does what you're trying to do, based on your question.
Just set the label value again when HomeViewController appear again. That should work since you said that re-launching the app. solves the problem. This should work too.
- (void)viewWillAppear:(BOOL)animated {
self.homeLabel.text = stackTableViewController.currentTarget;
}
- (id)init {
self = [super initWithNibName:#"HomeViewController" bundle:nil];
if (self) {
// Do something
stackTableViewController = [[StackTableViewController alloc] init];
stackTableViewController.delegate = self;
}
return self;
}
Here, you create a StackTableViewController and set self as the delegate. This is fine.
- (IBAction)goToStack:(id)sender {
StackTableViewController *vc = [[StackTableViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
Here, you create a brand new StackTableViewController and push it, without setting the delegate object. Any changes you do in the pushed view controller won't be fed back to the home view controller because the delegate is not set.
Either push your existing stackViewController, or set the delegate on your newly created one.
As an additional point, this:
#property (strong,nonatomic) id<StackTableViewControllerDelegate> delegate;
Coupled with this:
#interface HomeViewController : UIViewController {
StackTableViewController *stackTableViewController;
}
And the fact you're setting the delegate of the stack table view controller to the home view controller (which owns the stack table view controller) means you're creating a strong reference cycle. Delegates are normally weak references for this purpose.

How to implement MWFeedParser in my project

I'm trying to use the MWFeedParser library in my app. On my homescreen, I have a view controller named NewsViewController.
In the MWFeedParser library, the root view controller is called RootViewController. I've tried to copy all the code from the RootViewController into the NewsViewController .H + .M and in IB I've linked the tableview to "dataSource" and "delegate". But when my app starts the tableview is empty.
Here's how to code looks like:
.H:
#import <UIKit/UIKit.h>
#import "MWFeedItem.h"
#import "MWFeedParser.h"
#interface NewsViewController : UITableViewController <MWFeedParserDelegate, UITableViewDelegate, UITableViewDataSource> {
// Parsing
MWFeedParser *feedParser;
NSMutableArray *parsedItems;
// Displaying
NSArray *itemsToDisplay;
NSDateFormatter *formatter;
IBOutlet UITableView *tableView;
}
// Properties
#property (nonatomic, retain) NSArray *itemsToDisplay;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
-(IBAction)goHome;
#end
.M:
#import "NSString+HTML.h"
#import "MWFeedParser.h"
#import "DetailTableViewController.h"
#implementation NewsViewController
#synthesize itemsToDisplay, tableView;
#pragma mark -
#pragma mark View lifecycle
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"News", #"News");
self.tabBarItem.image = [UIImage imageNamed:#"icon_news"]; }
return self;
}
- (void)viewDidLoad
{
label.shadowOffset = CGSizeMake(0.0f, 1.0f);
label.textColor = [UIColor colorWithRed:0xB3/249.0 green:0xB3/252.0 blue:0xB3/253.0 alpha:1];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Date
// Setup
formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
parsedItems = [[NSMutableArray alloc] init];
self.itemsToDisplay = [NSArray array];
// Refresh button
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(refresh)];
// Parse
NSURL *feedURL = [NSURL URLWithString:#"http://www.mywebsite.com/feed/"];
feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL];
feedParser.delegate = self;
feedParser.feedParseType = ParseTypeFull; // Parse feed info and all items
feedParser.connectionType = ConnectionTypeAsynchronously;
[feedParser parse];
UIImage *someImage = [UIImage imageNamed:#"back_active1#2x.png"];
[button setBackgroundImage:someImage forState:UIControlStateHighlighted];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated {
static BOOL first = YES;
if (first) {
UIViewController *popup = [[Home1ViewController alloc] initWithNibName:#"Home1ViewController" bundle:nil];
[self presentViewController:popup animated:NO completion:nil];
first = NO;
}
}
#pragma mark -
#pragma mark Parsing
// Reset and reparse
- (void)refresh {
self.title = #"Refreshing...";
[parsedItems removeAllObjects];
[feedParser stopParsing];
[feedParser parse];
self.tableView.userInteractionEnabled = NO;
self.tableView.alpha = 0.3;
}
- (void)updateTableWithParsedItems {
self.itemsToDisplay = [parsedItems sortedArrayUsingDescriptors:
[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:#"date"
ascending:NO]]];
self.tableView.userInteractionEnabled = YES;
self.tableView.alpha = 1;
[self.tableView reloadData];
}
#pragma mark -
#pragma mark MWFeedParserDelegate
- (void)feedParserDidStart:(MWFeedParser *)parser {
NSLog(#"Started Parsing: %#", parser.url);
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedInfo:(MWFeedInfo *)info {
NSLog(#"Parsed Feed Info: “%#”", info.title);
self.title = info.title;
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item {
NSLog(#"Parsed Feed Item: “%#”", item.title);
if (item) [parsedItems addObject:item];
}
- (void)feedParserDidFinish:(MWFeedParser *)parser {
NSLog(#"Finished Parsing%#", (parser.stopped ? #" (Stopped)" : #""));
[self updateTableWithParsedItems];
}
- (void)feedParser:(MWFeedParser *)parser didFailWithError:(NSError *)error {
NSLog(#"Finished Parsing With Error: %#", error);
if (parsedItems.count == 0) {
self.title = #"Failed"; // Show failed message in title
} else {
// Failed but some items parsed, so show and inform of error
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Parsing Incomplete"
message:#"There was an error during the parsing of this feed. Not all of the feed items could parsed."
delegate:nil
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alert show];
}
[self updateTableWithParsedItems];
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return itemsToDisplay.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell.
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
if (item) {
// Process
NSString *itemTitle = item.title ? [item.title stringByConvertingHTMLToPlainText] : #"[No Title]";
NSString *itemSummary = item.summary ? [item.summary stringByConvertingHTMLToPlainText] : #"[No Summary]";
// Set
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.textLabel.text = itemTitle;
NSMutableString *subtitle = [NSMutableString string];
if (item.date) [subtitle appendFormat:#"%#: ", [formatter stringFromDate:item.date]];
[subtitle appendString:itemSummary];
cell.detailTextLabel.text = subtitle;
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Show detail
DetailTableViewController *detail = [[DetailTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
detail.item = (MWFeedItem *)[itemsToDisplay objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detail animated:YES];
// Deselect
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
Please help me fix this!
you can follow the following link to use MWFeedParser : https://0club1.blogspot.in/
If your Table view is empty, you could have got the following error:
NSURLSession/NSURLConnection HTTP load failed
To allow HTTP, we need to allow arbitrary loads in App Transport Security Settings. Select info.plist in your project, in Information property list add new list as App Transport Security Settings.
Within that add Allow Arbitary Loads and mark it as YES.

Getting JSON data and populate TableView in iOS

Good evening!
I need some help. I'm getting some data from the Google Places API in JSON format but I'm not getting to populate a TableView in iPad (SplitView Based Application). I starting with iOS developing so probably there are many mistakes! I used a project example that used Twitter API to retrieve the posts and just renamed the JSON data names.
I have four files that are used in the project and implement the function:
SimpleSplitController.h
SimpleSplitController.m
SplitSampleAppDelegate.h
SplitSampleAppDelegate.m
I get an ERROR at SplitSampleDelegate.m file, as it's checked there...
If someone may help me, I'd be very grateful!
Here are the codes that implement:
SplitSampleAppDelegate.h
#import <UIKit/UIKit.h>
#class APTabBarControllerForSplitController;
#interface SplitSampleAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
NSMutableData *responseData;
NSMutableArray *tweets;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet APTabBarControllerForSplitController *tabBarController;
#property (nonatomic, retain) NSMutableArray *tweets;
#end
SplitSampleAppDelegate.m
#import "SplitSampleAppDelegate.h"
#import "APTabBarControllerForSplitController.h"
#implementation SplitSampleAppDelegate
#synthesize window=_window;
#synthesize tabBarController=_tabBarController;
#synthesize tweets;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.tabBarController.delegate = self;
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
// Add the view controller's view to the window and display.
responseData = [[NSMutableData data] retain];
tweets = [NSMutableArray array];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"https://maps.googleapis.com/maps/api/place/search/json?location=-15.815347,-47.9164097&radius=500&types=restaurant&sensor=true&key=AIzaSyBLY-lBALViJ6ybrgtOqQGhsCDQtsdKsnc"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSDictionary *results = [responseString JSONValue];
NSMutableArray *allTweets = [results objectForKey:#"results"];
//This is the part that I get an ERROR
[viewController setTweets:allTweets];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
SimpleSplitController.h
#import <UIKit/UIKit.h>
#import "APSplitViewController.h"
#import <MapKit/MapKit.h>
#interface SimpleSplitController : APSplitViewController {
NSMutableData *responseData;
NSArray *tweets;
}
#property (nonatomic, retain) UIViewController *left;
#property (nonatomic, retain) UIViewController *right;
#property (nonatomic, retain) NSArray *tweets;
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
#end
SimpleSplitController.m
#import "SimpleSplitController.h"
#import <QuartzCore/QuartzCore.h>
#import "JSON/JSON.h"
#import "Tweet.h"
#interface SimpleSplitController()
- (UIColor *) randomColor;
- (UIViewController*) randomViewController1;
- (UIViewController*) randomViewController2;
- (UIViewController*) randomViewController3;
- (void) buttonPushRandomViewController1;
- (void) buttonPushRandomViewController2;
#end
#implementation SimpleSplitController
#synthesize left, right;
#synthesize tweets;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSDictionary *aTweet = [tweets objectAtIndex:[indexPath row]];
cell.textLabel.text = [aTweet objectForKey:#"name"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.detailTextLabel.text = [aTweet objectForKey:#"vicinity"];
NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"icon"]];
NSData *data = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Probable you are wrong here. You are checking object, instead of value.
NSMutableArray *allTweets = [results valueForKey:#"results"];
Jope your problem is resolved.

iOS (iPhone/iPad) SDK - Using a JSON parser with Twitter's user_timeline

Ok, here is my code:
(appname)AppDelegate.h:
#import <UIKit/UIKit.h>
#class TwitterViewContoller;
#interface <appname>AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *rootController;
TwitterViewContoller *viewController;
NSMutableData *responseData;
NSMutableArray *tweets;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
#property (nonatomic, retain) IBOutlet TwitterViewContoller *viewController;
#property (nonatomic, retain) NSMutableArray *tweets;
#end
(appname)AppDelegate.m:
#import "<appname>AppDelegate.h"
#import "TwitterViewContoller.h"
#import "SBJson.h"
#implementation <appname>AppDelegate
#synthesize window = _window;
#synthesize rootController;
#synthesize viewController;
#synthesize tweets;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
responseData = [[NSMutableData data] retain];
tweets = [NSMutableArray array];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://api.twitter.com/1/statuses/user_timeline.json?screen_name=USER_NAME_ID"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
//[window addSubview:rootController.view];
//[window makeKeyAndVisible];
return YES;
}
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
//NSDictionary *results = [responseString JSONValue]; <---This...
//NSArray *allTweets = [results objectForKey:#"results"]; <--- and this was original code but it caused an exception,
NSArray *allTweets = [responseString JSONValue]; //<-- So I used this instead.
NSLog(#"THE ARRAY = %#", allTweets); //<-- THE ARRAY IS SHOWING FINE IN THE OUTPUT LOG
[viewController setTweets:allTweets];
[self.window addSubview:rootController.view];
[self.window makeKeyAndVisible];
}
- (void)dealloc {
[_window release];
[rootController release];
[viewController release];
[super dealloc];
}
#end
TwitterViewContoller.h: (yes, I know I spelt it wrong - lol)
#import <UIKit/UIKit.h>
#import "SBJson.h"
#interface TwitterViewContoller : UIViewController {
IBOutlet UILabel *label;
NSArray *tweets;
IBOutlet UITableView *tview;
}
#property(nonatomic, retain) IBOutlet UILabel *label;
#property(nonatomic, retain) NSArray *tweets;
#end
TwitterViewContoller.m:
#import "TwitterViewContoller.h"
#import "Tweet.h"
#implementation TwitterViewContoller
#synthesize label;
#synthesize tweets;
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 20;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 80;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSLog(#"THE ARRAY = %#", tweets); //<--ARRAY IS NULL <-- <-- <--
NSDictionary *aTweet = [tweets objectAtIndex:[indexPath row]];
cell.textLabel.text = [aTweet objectForKey:#"text"];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.detailTextLabel.text = [aTweet objectForKey:#"screen_name"];
NSURL *url = [NSURL URLWithString:[aTweet objectForKey:#"profile_image_url"]];
NSData *data = [NSData dataWithContentsOfURL:url];
cell.imageView.image = [UIImage imageWithData:data];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
tweets = [[NSArray alloc]init];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void) dealloc {
[tweets release];
[super dealloc];
}
#end
The problem is that my UITableView is showing up but none of my tweets are. I have noticed that the "tweets" array in TwitterViewContoller (I know I spelt it wrong) is empty (the null problem is fixed) but "allTweets" in my AppDelegate isn't empty. Any ideas?
Test to ensure that in your app delegate, the viewController property is not nil. If you have miswired it in IB (I don't see any instantiation of it in your app delegate), it will silently fail when you call setTweets.
Also, if your view controller is visible and you re-set the tweets property, the table view won't update itself. Instead of synthesizing your tweets property, write your own getter and setter, like so (you could also use KVO for this purpose if you like)
-(NSMutableArray*)tweets {
return [[tweets retain] autorelease];
}
-(void)setTweets:(NSMutableArray*)newTweets {
if(newTweets != tweets) {
[newTweets retain];
[tweets release];
tweets = newTweets;
[tView reloadData];
}
}
As an aside, you should have -tableView:numberOfRowsInSection: return [tweets count] rather than a fixed number, and it isn't necessary to implement -tableView:heightForRowAtIndexPath: if your rows are all the same height -- you can just set the rowHeight property in IB or in code on the table view.
Update
If your view controller property isn't getting populated, it might be easiest to just load and add it manually in -application:didFinishLaunchingWithOptions -- I think your current approach of delaying the display of any interface until the web request finishes is conceptually problematic. What happens if the network isn't available? Here's some code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... omitting the first few lines
// let's make sure that we have the tab bar controller, at least
NSAssert(nil != self.rootViewController, #"tab bar controller not hooked up!");
self.viewController = [[[TwitterViewContoller alloc] initWithNibName:#"TwitterViewContoller" andBundle:nil] autorelease];
self.rootViewController.viewControllers = [NSArray arrayWithObject:self.viewController];
// this is now the Right Way to set the root view for your app, in iOS 4.0 and later
self.window.rootViewController = self.rootViewController;
[self.window makeKeyAndVisible];
}
There are a lot of ways that you can confuse yourself when you're starting a new project. I like to customize all of my views to have hideous background colors at first so I always know if they're on screen or not -- using ugly colors helps ensure that I don't forget to change them later.

Resources