If UIRefreshControl is started programmatically,(beginRefreshing and then endRefreshing ) when it is not visible, then there would be a continuous flicker in the UIRefreshControl animation on next manual refresh.
Add this method in UITableViewController subclass and do a pull to refresh after 2 seconds and you will see the flicker
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIRefreshControl * refreshControl = [[UIRefreshControl alloc] init];
self.refreshControl = refreshControl;
[self.refreshControl beginRefreshing];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.refreshControl endRefreshing];
});
}
How to avoid this flicker?
Put your code in the viewDidLoad or viewWillAppear instead of viewDidAppear.
Also, can you tell me the reasoning behind putting the code inside the viewDidAppear method, rather than viewDidLoad or viewWillAppear?
Related
I want to use UIActivityIndicator on a function.
I'm implementing some Core Filters, some of which take almost a second to implement. I want that UIActivityIndicator to start and stop according the function.
I looked up online, but it's mostly using a timer. So that would make it hard-wired and not based on how long it actually takes to implement the function.
Can someone tell me a small example how I can do that ?
Declare ActivityIndicator
#property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
then,
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
// Do any additional setup after loading the view, typically from a nib.
CGRect frame = CGRectMake (120.0, 185.0, 80, 80);
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:frame];
[self.view addSubview:self.activityIndicatorView];
}
using this code you can start and stop the activityIndicator
[self.activityIndicatorView startAnimating]; //start
[self.activityIndicatorView stopAnimating]; //stop
all UI animation and navigation would be performed once the method execution is over. So if you want such functionality go for timer or dispatch queue.
as follows
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithFrame:self.window.frame];
[activity startAnimating];
//Your methods to be executed
double delayInSeconds = 0.01;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[activity stopAnimating];
});
in this method execution is kept in a queue after the execution of current method, method written dispatch_time_t will be executed.
I am doing one application.In that i am doing the animation for uiimageview to show the different image like below
UIImageView * fearthersanimate = nil;
[fearthersanimate setCenter:sender.center];
fearthersanimate = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120,200)];
[fearthersanimate setCenter:CGPointMake(sender.center.x, sender.center.y)];
fearthersanimate .animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"water_can_1.png"],
[UIImage imageNamed:#"water_can_2.png"],[UIImage imageNamed:#"water_can_3.png"],
[UIImage imageNamed:#"water_can_4.png"],[UIImage imageNamed:#"water_can_5.png"],
[UIImage imageNamed:#"water_can_6.png"],[UIImage imageNamed:#"water_can_7.png"],
[UIImage imageNamed:#"water_can_8.png"],
nil];
fearthersanimate.animationDuration = 1.0f;
fearthersanimate.animationRepeatCount = 1;
[self.view addSubview: fearthersanimate];
[fearthersanimate startAnimating];
But remaining operation is starting before end of this animation.But i need to do this animation first and until i need to stop the remaining process.
You can call your rest of operation in other method and call it after the same delay as you set animation time for images.
Below is the line of code by which you can call other method after some time interval
[self performSelector:#selector(restOfOperations) withObject:nil afterDelay:1.0];
//restOfOperations method defination/implementation
-(void)restOfOperations
{
//your code you want to perform after image animation
}
You can use the UIView animation block. For example:
[UIView animateWithDuration:0.5 animations:^{
} completion:^(BOOL finished) {
}];
Put the remaining process in the completion block.
Those animations are performed asynchronously, so you just need to fight async with async.
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(feathersanimate.animationDuration * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// Remaining logic
});
In an iOs app I am using a UINavigationController. On start-up this will have a title set but after a few seconds (in response to some data from a server) this title will need to change.
I tried:
self.title = #"new title";
self.navigationController.title = #"new";
self.navigationItem.title- #"new";
Nothing works... any suggestions?
self.title = #"new";
This might set again after you have to got response from server in the method which is calling to get response.
self.navigationItem.title = #"Old title";
// after some time
double waitToUpdate = .5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitToUpdate * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.navigationItem.title = #"New title";
});
change UINavigationController title for each view is easy enough. you just need to change the value of self.navigationItem.title. If you wan't to change it with some delay, you can use performSelector:withObject:afterDelay. For example :
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self performSelector:#selector(changeTitle:) withObject:#"New Title" afterDelay:2.]; // two seconds delay
}
- (void)changeTitle:(NSString *)title {
self.navigationItem.title = title;
}
I have a simple table view inside a navigation controller with the toolbar visible. On the toolbar is a search button, and the table view's table header view is set to my UISearchBar. If I scroll the table view up and then tap on the search bar to activate it, everything happens normally. But if I tap on the search button, which activates search bar programmatically, then all interactions with the search bar are disabled (looks like it's blocked by something), and the user can't clear the search, cancel the search or even navigate around the text in the textfield.
-(void)viewDidLoad
{
[self setupSearchBar];
}
-(void)setupSearchBar
{
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 44.0)];
self.searchBar.autocorrectionType = UITextAutocorrectionTypeDefault;
self.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar
contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self.searchController.searchResultsTableView registerNib:[UINib nibWithNibName:#"ItemCell" bundle:nil]
forCellReuseIdentifier:CellIdentifier];
for (UIView* subview in self.searchBar.subviews) {
if ([subview conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField*)subview setKeyboardAppearance:UIKeyboardAppearanceAlert];
[(UITextField*)subview setReturnKeyType:UIReturnKeyDone];
}
}
self.tableView.contentOffset = CGPointMake(0, self.searchBar.frame.size.height);
}
-(IBAction)search:(id)sender
{
[self.searchBar becomeFirstResponder]; // also tried [self.searchController setActive:YES animated:YES];
}
I've set up my search display controller with an NSFetchedResultsController like described in this SO post.
UPDATE
I worked around this problem by making my UITableView scroll to the top before setting the UISearchBar to first responder. Why does this work? I don't know, seeing that the becoming first responder part is not an issue, but if the search bar is not on the screen when it becomes first responder, the cancel and clear buttons won't work. This is my code now.
-(void)search:(id)sender
{
[self.tableView setContentOffset:CGPointMake(0, -self.tableView.contentInset.top) animated:NO];
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.searchController setActive:YES animated:YES];
[self.searchController.searchBar becomeFirstResponder];
});
}
If someone has any insights as to why this works, I'm all ears.
Try performing a hit test, to see if your view is obstructed.
[self.view hitTest:[self.view convertPoint:searchBar.center fromView:searchBar]];
Im trying to implement a way of taking a screenshot in my application. I want the UINavigationBar tip slide up - take the screenshot - and then the UINavigationBar can slide down nice and easy. I need the app to wait/hold a few seconds between some lines of code, because this way the first animation does not get time to finish:
[self.navigationController setNavigationBarHidden:YES animated:YES ];
[self.navigationController setNavigationBarHidden:NO animated:YES];
So, is there a way of delaying execution, like when animation a button like so:
[UIView animateWithDuration:0.5 delay:3 options:UIViewAnimationOptionCurveEaseOut animations:^{self.myButton.frame = someButtonFrane;} completion:nil];
regards
You can use:
double delayInSeconds = 2.0; // number of seconds to wait
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
/***********************
* Your code goes here *
***********************/
});
You can use:
[self performSelector:#selector(hideShowBarButton) withObject:nil afterDelay:1.0];
and of course:
- (void) hideShowBarButton{
if (self.navigationController.navigationBarHidden)
[self.navigationController setNavigationBarHidden:NO animated:YES ];
else
[self.navigationController setNavigationBarHidden:YES animated:YES ];
}
While there doesn't appear to be a callback for setNavigationBarHidden's completion, it will take UINavigationControllerHideShowBarDuration seconds. So just use a NSTimer to delay it:
[NSTimer scheduledTimerWithTimeInterval:UINavigationControllerHideShowBarDuration target:self selector:#selector(myFunction:) userInfo:nil repeats:NO];
You may want to add a small amount to the delay as a fail-safe;
[NSTimer scheduledTimerWithTimeInterval:UINavigationControllerHideShowBarDuration+0.05 target:self selector:#selector(myFunction:) userInfo:nil repeats:NO];
See also this related question: UINavigationControoller - setNavigationBarHidden:animated: How to sync other animations