-(void)reloadView{
NSLog(#"IN RELOAD VIEW ");
[[self tableView] reloadData];
}
- (void)viewDidLoad {
UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
[self navigationItem].rightBarButtonItem = barButton;
[activityIndicator startAnimating];
[self callStudentsWebService];
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
[self setTitle:#"Students"];
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleBlack;
UIBarButtonItem *add = [[UIBarButtonItem alloc] initWithTitle:#"Add Student" style:UIBarButtonItemStyleBordered target:self action:#selector(addStudent)];
UIBarButtonItem *flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *import = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemOrganize target:self action:#selector(addStudent)];
NSArray* toolbarItems = [NSArray arrayWithObjects:add,flexible,import, nil];
self.toolbarItems = toolbarItems;
}
Above is my Code in a Class which is a subclass of UITableViewController.
Now my problem is when I come onto the screen First Time it get the records from web service from the method [self callStudentsWebService] . Now i have a button in uitoolbar in the same view which updates the list . I am calling the reloadView method to refresh the List but it calls the numberOfRowsInSection and viewDidLoad method but does not call cellForRowAtIndexPath method. But when i goto other screen and come back again it does refresh my List from start.
What could be the reason ?? Please help i am new in iPad Development. And i m doing all this in iPad.
Thanks alot
EDITED
#interface StudentsList : UITableViewController {
DetailViewController *detailViewController;
UIToolbar *toolbar;
UIActivityIndicatorView *activityIndicator;
}
May be your data.count is 0? If there is some data it should call cellForRowAtIndexPath after [[self tableView] reloadData];
Do the refresh code in another separate method -(void)refreshData then call this whenever you want such as in -viewDidLoad or on a button tap...
Try to call -(void)reloadView from
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self reloadView];
}
Related
I am using UIImagePickerController with a custom overlay to record a video in my app. For the implementation of the UIImagePickerController, I have used the code from a great Ray Wenderlich tutorial.
I have hidden the controls for the camera, and created a simple custom overlay view. This has worked and loads fine.
I have then created a toolbar and buttons for the view, to record the video:
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
usingDelegate: (id <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>) delegate {
if (([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera] == NO)
|| (delegate == nil)
|| (controller == nil))
return NO;
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
// Displays a control that allows the user to choose movie capture
cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
// Hides the controls for moving & scaling pictures, or for
// trimming movies. To instead show the controls, use YES.
cameraUI.allowsEditing = NO;
cameraUI.delegate = delegate;
//Overlay view and toolbar setup
// creating overlayView
UIView* overlayView = [[UIView alloc] initWithFrame:cameraUI.view.frame];
// letting png transparency be
float width = 320;
float AR = (4.0/3.0);
float toolbar_height = 480 - (AR*width);
UIToolbar *toolBar=[[UIToolbar alloc]initWithFrame:CGRectMake(0, (AR*width), 320, toolbar_height)];
//toolBar.tintColor = [UIColor colorWithRed:(252/255.) green:(0/255.) blue:(48/255.) alpha:1];
toolBar.tintColor = [UIColor colorWithRed:(49/255.) green:(52/255.) blue:(49/255.) alpha:1];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *RecordBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(recordPressed:)];
UIBarButtonItem *CancelBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(imagePickerControllerDidCancel:)];
NSArray *buttons = [NSArray arrayWithObjects: CancelBarButtonItem, flexibleSpace, RecordBarButtonItem, flexibleSpace, nil];
[toolBar setItems: buttons animated:NO];
[overlayView addSubview:toolBar];
[overlayView.layer setOpaque:NO];
overlayView.opaque = NO;
cameraUI.showsCameraControls = NO;
cameraUI.cameraOverlayView = overlayView;
[controller presentViewController: cameraUI animated: YES completion:nil];
return YES;
}
My button recordBarButtonItem calls recordPressed which is given by:
- (void) recordPressed: (UIImagePickerController *) picker {
NSLog(#"lets record");
[picker startVideoCapture];
}
So the 'lets record' appears on the log, but I receive an NSInvalidArgumentException error for the startVideoCapture. I know theres something obviously wrong with the way im trying to start the video capture through the button press, but I cant figure it out. Still quite a novice at iOS so forgive me if the solution is simple!
Cheers,
Mike
The problem is that the action you attach to the initWithBarButtonSystemItem call doesn't pass the UIImagePickerController instance along.
What I would do is set the UIImagePickerController as a property of your class and access that property from your action, like this:
In your .h:
#property (nonatomic, strong) UIImagePickerController *cameraUI;
In your .m:
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
usingDelegate: (id <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>) delegate {
...
self.cameraUI = [[UIImagePickerController alloc] init];
...
UIBarButtonItem *RecordBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(recordPressed)]; // Removed the ':'
...
}
- (void) recordPressed {
NSLog(#"lets record");
[self.cameraUI startVideoCapture];
}
Actually I've just quickly tested it in some code I've gotten open, the sender for your action on the button press is UIBarButtonItem *. So there's a couple of things you can do, you can either go down the root of
UIBarButtonItem *senderButton = (UIBarButtonItem *)sender;
if(senderButton.image == UIBarButtonSystemItemCamera)
{
//Handle behaviour
}
Or set the tag variable for each button and skip the image check and look at the tags instead, which might make the logic a bit easier.
I am trying to learn to use dispatch_get_global_queue to perform a web call asynchronously. Basically, I need to update the User Interface depending on the user's location. I started using dispatch_get_global_queue because the user interface was unresponsive while the web call was performed.
Now, my problem is that the buttons do not appear correctly when buttonUpdate is called. One button is supposed to be black, and the other is green. However, now they both appear the default blue. Also, the words/title of the buttons do not appear until I click on one of them. Anyone know why? Thank you!
I have this method called preButtonUpdate that calls the buttonUpdate method asynchronously:
-(void)preButtonUpdate {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[self buttonUpdate];
});
}
The preButtonUpdate method is called in viewDidAppear and appReturnsActive:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self preButtonUpdate];
//other code
}
- (void)appReturnsActive {
[myTimer invalidate];
myTimer = nil;
//ONLY WANT TO PERFORM THE UPDATE IF VIEWING THE PROFILE VIEW CONTROLLER
UIViewController *currentVC = self.navigationController.visibleViewController;
NSString * name = NSStringFromClass([currentVC class]);
if ([name isEqualToString:#"ProfileViewController"]) {
[self preButtonUpdate];
}
}
Then, the preButtonUpdate calls the buttonUpdate method, which performs the web query and updates the user interface:
-(void) buttonUpdate {
[locationManagerProfile stopUpdatingLocation];
NSString *userLatitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLatitude];
NSString *userLongitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLongitude];
NSString *placeLatitude = [[NSUserDefaults standardUserDefaults]
stringForKey:#"savedLatitude"];
NSString *placeLongitude = [[NSUserDefaults standardUserDefaults]
stringForKey:#"savedLongitude"];
NSString *distanceURL = [NSString stringWithFormat:#"http://www.website.com/page.php?
lat1=%#&lon1=%#&lat2=%#&lon2=%#",userLatitude, userLongitude, placeLatitude,
placeLongitude];
NSData *distanceURLResult = [NSData dataWithContentsOfURL:[NSURL
URLWithString:distanceURL]];
NSString *distanceInFeet = [[NSString alloc] initWithData:distanceURLResult
encoding:NSUTF8StringEncoding];
if ([distanceInFeet isEqualToString:#"1"]) {
UIBarButtonItem *btnGo = [[UIBarButtonItem alloc] initWithTitle:#"Button A"
style:UIBarButtonItemStyleBordered target:self action:#selector(actionA)];
self.navigationItem.rightBarButtonItem = btnGo;
[self.navigationItem.rightBarButtonItem setTintColor:[UIColor
colorWithRed:44.0/255.0 green:160.0/255.0 blue:65.0/255.0 alpha:1.0]];
UIBarButtonItem *btnGoTwo = [[UIBarButtonItem alloc] initWithTitle:#"Button B"
style:UIBarButtonItemStyleBordered target:self action:#selector(actionB)];
self.navigationItem.rightBarButtonItem = btnGoTwo;
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:btnGo,
btnGoTwo, nil];
}
if ([distanceInFeet isEqualToString:#"0"]) {
UIBarButtonItem *btnGo = [[UIBarButtonItem alloc] initWithTitle:#"Button C"
style:UIBarButtonItemStyleBordered target:self action:#selector(actionC)];
self.navigationItem.rightBarButtonItem = btnGo;
[self.navigationItem.rightBarButtonItem setTintColor:[UIColor
colorWithRed:44.0/255.0 green:160.0/255.0 blue:65.0/255.0 alpha:1.0]];
UIBarButtonItem *btnGoTwo = [[UIBarButtonItem alloc] initWithTitle:#"Button B"
style:UIBarButtonItemStyleBordered target:self action:#selector(actionB)];
self.navigationItem.rightBarButtonItem = btnGoTwo;
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:btnGo,
btnGoTwo, nil];
}
}
UI Update is always done on the main thread. So keep your UI update code out of the despatch queue
Keep [self buttonUpdate]; out of the dispatch_async block
-(void)preButtonUpdate {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[self buttonUpdate];
});
}
Unblocking Your User Interface - Apple Developer
EDIT:
Put the if condtion code just outside the dispatch_async block
I have a UIViewController which has a UITableView as a child besides other elements. I want to add editing support on that tableView with this simple line:
self.navigationItem.rightBarButtonItem = self.editButtonItem;
It works if I set this on UITableViewController view type, but obviously that does not work on tableView's that are subviews. Actually it shows the editing button but the edit action is not triggered.
Anyway if there is no elegant solution for that I will simply implement custom editing button.
Thanks!
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"My View Controller";
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(editButtonSelected:)] autorelease];
}
- (void) editButtonSelected: (id) sender
{
if (tableView1.editing) {
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(editButtonSelected:)] autorelease];
[self.tableView1 setEditing:NO animated:YES];
} else {
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(editButtonSelected:)] autorelease];
[self.tableView1 setEditing:YES animated:YES];
}
}
You need to implement setEditing:animated yourself:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[self.tableView setEditing:editing animated:animated];
[super setEditing:editing animated:animated];
}
I've just found a solution. Replacing self.editButtonItem with self.myTableViewController.editButtonItem like that:
self.navigationItem.rightBarButtonItem = self.myTableViewController.editButtonItem;
It works like a charm. Could it be more simple? :)
self.navigationItem.leftBarButtonItem = self.editButtonItem;
Here in my application i created a leftbarbuttonitem programatically in viewWillAppear methos, i have two click twice to work this, my code is as follows.
Code for creating UIBarButtonItem(left bar button)
goingBackButton = [[UIBarButtonItem alloc] init];
goingBackButton.title = #"Back";
goingBackButton.target = self;
goingBackButton.action = #selector(backAction);
self.navigationItem.leftBarButtonItem = goingBackButton;
[goingBackButton release];
Action code
- (IBAction) backAction {
NSLog(#"Inside the backAction of uploadViewController");
[self.navigationController popViewControllerAnimated:YES];
NSLog(#"Inside the backAction1 of uploadViewController");
}
Try the below code:
UIBarButtonItem *bar = [[UIBarButtonItem alloc]initWithTitle:#"back" style:UIBarButtonItemStyleDone target:nil action:#selector(back)];
self.navigationItem.leftBarButtonItem = bar;
[bar release];
-(void)back
{
[self.navigationController popViewControllerAnimated:YES];
}
Right now I'm using this in my -viewDidLoad method:
UIToolbar *toolbar = [[UIToolbar alloc] init];
UIBarButtonItem *flexibleSpace = [UIBarButtonItem alloc];
flexibleSpace = [flexibleSpace initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
// Add a back button to allow user to close the modal view
NSString *back = NSLocalizedString(#"Back", nil);
UIBarButtonItem *backButton = [UIBarButtonItem alloc];
backButton = [backButton initWithTitle:back
style:UIBarButtonItemStyleDone
target:self
action:#selector(dismissModalViewControllerAnimated:)];
// Add a centered title to the toolbar
// I doubt this is the "correct" way to do this, but it seems to work.
// The "width" property of a UIBarButtonItem doesn't seem to correspond to
// the actual width if the button is flexible (i.e. the width isn't explicitly
// set), so I'm using this hack instead.
// This is obviously NOT an optimal solution. For one thing, if the button padding
// ever changes, it has to be changed manually here as well. For another, it is
// a pain to do this for every button I add to the toolbar, and furthermore the title
// is centered only according to its own width, not the toolbar's.
const CGRect toolbarFrame = [toolbar frame];
const CGFloat backWidth = [back sizeWithFont:[UIFont boldSystemFontOfSize:[UIFont buttonFontSize]]
constrainedToSize:toolbarFrame.size].width;
const CGRect titleFrame = {{0.0f, 0.0f},
{toolbarFrame.size.width - (backWidth * 2.0f), 50.0f}};
UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
[titleLabel setText:[self title]];
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setTextAlignment:UITextAlignmentCenter];
[titleLabel setFont:[UIFont boldSystemFontOfSize:20.0f]];
[titleLabel setTextColor:[UIColor whiteColor]];
[titleLabel setShadowColor:[UIColor colorWithWhite:0.0f alpha:0.5f]];
[titleLabel setShadowOffset:CGSizeMake(0.0f, -1.0f)];
UIBarButtonItem *titleItem = [[UIBarButtonItem alloc] initWithCustomView:titleLabel];
[titleLabel release];
NSArray *items = [[NSArray alloc] initWithObjects:flexibleSpace, titleItem, backButton, nil];
[flexibleSpace release];
[titleItem release];
[backButton release];
[toolbar setItems:items];
[items release];
[view addSubview:toolbar];
[toolbar release];
Does anyone have a better method for doing this? What I'm using feels like a major hack :(.
Edit:
Thanks for the suggestion Darren!
Here's what I'm using now, if anyone's interested:
First, in accordance with Darren's suggestion, I'm wrapping my modal view controller in a generic UINavigationController (which contains it's own UIToolbar, UINavigationBar, that comes with a title):
MyCustomViewController *myModalViewController = [[MyModalViewController alloc] init];
[myModalViewController setTitle:#"Foo"];
UINavigationController *modalNavController = [[UINavigationController alloc] initWithRootView:myModalViewController];
[myModalViewController release];
// This is intended to be presented in another view controller class
[self presentModalViewController:modalNavController animated:YES];
[modalNavController release];
Then in my -init method for the MyModalViewController class, I have this:
- (id)init
{
if (self = [super init]) {
UIBarButtonItem *backButtonItem = [UIBarButtonItem alloc];
backButtonItem = [backButtonItem initWithTitle:back
style:UIBarButtonItemStyleDone
target:[self navigationController]
action:#selector(dismissModalViewControllerAnimated:)];
[[self navigationItem] setRightBarButtonItem:backButtonItem];
[backButtonItem release];
}
return self;
}
This is a much cleaner solution than before. Thanks.
You should wrap your view controller inside a generic UINavigationController when you present the modal view:
MyCustomController* myController = [[MyCustomController alloc] init];
editor.title = #"My Title";
UINavigationController* modalController = [[UINavigationController alloc] initWithRootViewController:myController];
[self.navigationController presentModalViewController:modalController animated:YES];
[modalController release];
[myController release];
Your custom controller can specify its toolbar buttons in its init method:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(doCancel:)] autorelease];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:#selector(doSave:)] autorelease];
}
return self;
}
You should be adding the title in the items property
i.e.
#property(nonatomic, copy) NSArray *items
where items is init with a title
initWithTitle:style:target:action:
See http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIToolbar_Class/Reference/Reference.html#//apple_ref/occ/instp/UIToolbar/items
and
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIBarButtonItem_Class/Reference/Reference.html#//apple_ref/occ/instm/UIBarButtonItem/initWithTitle:style:target:action:
for the details.
Hope that helps
[Edit]
P.S. The UIBarButtonItem is also where you would be adding your buttons ;-)