I have a tableView, and a "Reload" button that fetches data from a URL and reloads the table, a costly operation (in particular the fetch part).
I want display info to the user while this is happening, so I thought I'd put up a "Loading" UITextView on top, do the fetch/reload operation, then remove the UITextView.
Here's the code:
- (IBAction)refreshData:(id)sender {
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-30, self.view.frame.size.width, 30)];
[self.view addSubview:textView];
textView.text = #"Loading..";
textView.textColor = [UIColor whiteColor];
textView.backgroundColor = [UIColor grayColor];
textView.editable = NO;
[self fetchData];
[self.tableView reloadData];
[textView removeFromSuperview];
}
The behavior I get is that the fetchData executes before the UITextView renders on screen. I know this because I have NSLogs inside fetchData that execute before the UITextView shows up on screen.
Is there something obvious I'm missing here? Thanks.
Replace [self fetchData]; with
[self performSelectorInBackground:#selector(fetchData) withObject:nil];
Then inside your fetchData method, after your fetch is done, add
[self performSelectorOnMainThread:#selector(fetchDataFinished) withObject:nil waitUntilDone:NO];
where the new method fetchDataFinished is defined as
-(void) fetchDataFinished{
[self.tableView reloadData];
[self.textView removeFromSuperview];
}
Note that you have to make textView a property so it is accessible in this method.
I have not tried out the above for your particular case, but I have used similar constructs successfully in many similar situations.
Related
In my view controller's I have following code
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%s",__PRETTY_FUNCTION__);
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:201.0/255.0 green:201.0/255.0 blue:201.0/255.0 alpha:1.0];
}
On this view when I click a button , I am presenting MFMailComposeViewController modally. When I present MFMailComposeViewController modally, navigation bar same color as set in viewWillAppear. I want default blue color as Apple told that don't customize this view. Here is my code which I have tried
Code 1:
-(void)sendEmailWithWithRecipients:(NSArray*)recipients andData:(NSData*)data {
if ([MFMailComposeViewController canSendMail]){
MFMailComposeViewController *mailComposeViewController = [[MFMailComposeViewController alloc] init];
mailComposeViewController.mailComposeDelegate = self;
self.navigationController.navigationBar.tintColor = nil;
[self presentModalViewController:mailComposeViewController animated:YES];
[mailComposeViewController release];
}
else {
[self showAlertWithTitle:#"Alert" andMessage:#"Can not send email. Please check your email settings."];
}
}
But above code is not working for tint color
Code 2: Set tint color in viewWillDisappear
-(void)viewWillDisappear:(BOOL)animated {
NSLog(#"%s",__PRETTY_FUNCTION__);
self.navigationController.navigationBar.tintColor = nil;
[super viewWillDisappear:animated];
}
Code 2 also not working.
But this is working fine in iOS5 without setting tintColor = nil while presenting MFMailComposeViewController modally & in viewWillDisappear. Its not working iOS 4.x
Anyone have solution for this? Thanks.
You can customize the navigationbar's tint color by accessing yourController's(ViewController which you are presetnting) topViewController.
Ex :
[self presentModalViewController:yourController animated:YES];
yourController.topViewController.navigationController.navigationBar.tintColor =
[UIColor (Your Color)];
Try setting the navigation bar style rather than the tint color. Tint color and bar style have slightly different side effects, so while I don't completely understand your needs, it might be exactly what you're looking for.
[self.navigationController.navigationBar setBarStyle:UIBarStyleDefault];
or
self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
And make sure you do this within the context of the modal view controller, not the previous view controller.
Instead of nil try this [UIColor ClearColor];
I have a small UIView that I hide/show in to show a message to the user. The message itself is in a UITextView that I add to the small UIView that gets shown.
The sliding-in and sliding-out works fine - but the prior messages are not cleared. I have spent enough time to fix the problem - but to no avail. Can someone lend me their eyes!!
Here is how the UITextField is created programatically:
#interface MessageVC : UIViewController {
UITextView *messageTV;
}
#property (nonatomic, retain) UITextView *messageTV;
- (id)init;
- (void)showMsg:(NSString *)title;
#end
and
- (id)init {
if (self = [super init]) {
self.view = [[[UIView alloc] initWithFrame:CGRectMake(0, 380, 320, 100)] autorelease];
[self.view setBackgroundColor:[UIColor blackColor]];
}
return self;
}
- (void)showMsg:(NSString *)title {
[self setMessageTV : [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 315, 90 )]];
[[self messageTV] setBackgroundColor : [UIColor greenColor]];
[[self messageTV] setTextColor : [UIColor whiteColor]];
[[self messageTV] setText:#""]; <<<<<<<< - does not clear the text
[[self messageTV] setText : title];
[self.view addSubview : [self messageTV]];
[self.view setHidden:NO];
}
- (void) hideMessage {
[self.view setHidden:YES]
}
I'll go out on a limb and ask why you're using a UITextView. I honestly have never needed to use a UITextView. Try changing it to a UILabel and see if the problem is specific to the UITextView. If you absolutely need a UITextView, let me know in a comment, but I have a suspicion that a UILabel is what you're after.
It appears that you are adding it as a subview every time. So you're actually creating multiple UITextViews and adding them on top of each other. You would either need to removeFromSuperview or just set the text of the instance variable.
Take these two lines out of showMsg and put them in viewDidLoad:
[self setMessageTV : [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 315, 90 )]];
[self.view addSubview : [self messageTV]];
I have tried hiding a segmented controller just like a button or label can be hidden in XCode. It's intended to be hidden/shown when touching a parent segmented controller above. This Code would work with Buttons or Labels:
mySegmContr.hidden = YES;
But it just won't work for segmented controllers. Can you help me out?
I figured out that you can use a simple UIView in which you put the things you want to hide. The UIView can then be hidden with
myView.hidden = YES;
still I found no way to hide a segmented control directly.
If you create a property for the segment controller you can do more stuff with it like changing it's location, resizing it and want you want hiding it.
In your .h file do this
UISegmentedControl *mySegment;
#property (nonatomic, retain) UISegmentedControl *mySegment;
-(void) createMySegment;
In your .m file do this
#synthesize mySegment;
- (void) createMySegment {
if ([self mySegment] == nil) {
NSArray *buttons = [NSArray arrayWithObjects:#"One", #"Two", #"Three", nil];
UISegmentedControl *segName = [[UISegmentedControl alloc] buttons];
[self setMySegment:segName];
[segName release];
segName.frame = CGRectMake(110, 62, 120, 25);
segName.segmentedControlStyle = UISegmentedControlStyleBar;
segName.momentary = NO;
segName.selectedSegmentIndex = 0;
[segName addTarget:self
action:#selector(pickMethod:)
forControlEvents:UIControlEventValueChanged];
[self.view addSubview:segName];
}
}
NOTE: With "setMySegment" above make sure you use a capital first letter which is M in "mySegment".
Then when you want to hide it use this. Don't for get to dealloc mySegment.
[[self mySegment] setHidden:YES];
I simply can't get this to work, I would think it was simple, but no luck.
- (void) animate {
UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 300.0f, 100.0f)];
[viewA setBackgroundColor:[UIColor blueColor]];
UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 300.0f, 100.0f)];
[viewB setBackgroundColor:[UIColor brownColor]];
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(10.0f, 10.0f, 300.0f, 100.0f)];
[container addSubview:viewA];
[self.view addSubview:container];
[UIView transitionWithView:container
duration:0.4
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[[[container subviews] objectAtIndex:0] removeFromSuperview];
[container addSubview:viewB];
}
completion:^(BOOL finished){
}];
}
This is how the documentation recommends you do it, make a container, add/remove the two subviews you want to flip between.
I can't get it to work. It will just display viewA, then viewB, as if the animation part is skipped, but the block is carried out?
If I switch the container in the [UIView transitionWithView:container with self.view it flips the entire view (As suspected) but I can not get it to do this with 2 subviews of self.view.
Is there no way around this?
I am looking to do something like the iPad Photos app, where a picture will flip and scale to full screen.
I really hope someone could help me out here, thank you in advance.
You can't put semicolons inside the block. If you want two things done in there, divide them with a ",".
Also CurveEase would probably be nice., if you want it.
This should work.
[UIView transitionWithView:container
duration:0.4
options:UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionCurveEaseInOut
animations:^{
[[[container subviews] objectAtIndex:0] removeFromSuperview],
[container addSubview:viewB];
}
completion:^(BOOL finished){
}];
If it does not, consider making the views instance variables and make sure they're allocated before you try to animate them. If you want to animate on a button push, you can do it directly with sender too, if the whole view is a UIButton.
I hope it helps.
I have created navigation based project. and in second screen i want to add uitabbarcontroller. so can any one suggest how i do this.
i already did lot of search but no success yet. so please can you provide a simple sample of this. i already tried below discussion but i think its not a good approach.
Navigation Based Application with TabBar
Thanks
Actually this is the correct approach. The one thing that is not correct is where the controllers are allocated. This is happened in the previous controller, the one that is making the push, but should be allocated in the object that is responsible, the TabBarController.
When you implement your action to show the UITabBarController make the following code:
- (void) theAction {
SomeTabBarControllerSubClass *controller = [[SomeTabBarControllerSubClass alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
Then when you implement the SomeTabBarControllerSubClass class:
(.h)
#interface SomeTabBarControllerSubClass : UITabBarController {
UIViewController *first;
UIViewController *second;
}
#end
(.m)
#implementation SomeTabBarControllerSubClass
- (void) viewDidLoad {
first = [[UIViewController alloc] init]; //Or initWithNib:
second = [[UIViewController alloc] init];
first.view.backgroundColor = [UIColor greenColor] //Just example
second.view.backgroundColor = [UIColor redColor] //Just example
first.tabBarItem.image = [UIImage imageNamed:#"someImage.png"];
self.viewControllers = [NSArray arrayWithObjects:first,second,nil];
}
- (void) dealloc {
[first dealloc];
[second dealloc];
[super dealloc];
}
#end