I have 2 views
1) A
2) B
When I segue from view A to view B, it takes a long while to load, so I added an activity indicator in the segue.
My problem is, when I segue over to view B, my screen freezes(loads) in view A and only for a split second, it shows the activity indicator before going onto view B.
How do I make sure the activity indicator appears before it starts to load.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[self useActivityIndicator];
if ([[segue identifier] isEqualToString:#"ShowAdsDetail"])
{
//do anything that needs to be done
}
}
-(void)useActivityIndicator{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[activityView startAnimating];
subView.hidden = NO;
}
I had a similar issue with a UIActivityIndicator that was animating too fast. The segue was pushing the next view controller right away and barely showing the activity indicator.
In case this can help others - I was able to fix it by implementing performSelector:withObject:afterDelay and then, in the removeSpinner method, calling my performSegueWithIdentifier method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
[self.spinner startAnimating];
[self performSelector:#selector(removeSpinner:) withObject:self.spinner afterDelay:2.0];
}
- (void)removeSpinner: (UIActivityIndicatorView *)spinner {
[self.spinner stopAnimating];
[self.spinner removeFromSuperview];
[self performSegueWithIdentifier:#"showMyPlans" sender:nil];
}
Just change your code like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self useActivityIndicator];
});
if ([[segue identifier] isEqualToString:#"ShowAdsDetail"])
{
//do anything that needs to be done
}
}
-(void)useActivityIndicator
{
dispatch_async(dispatch_get_main_queue(),^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[activityView startAnimating];
subView.hidden = NO;
});
}
Related
I am trying to do some experiment.
- (IBAction)btn1Action:(id)sender {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"popvc2id" sender:self];
});
NSLog(#"TAP");
}
When button will tap it will take 1 second to perform segue and when this button tapped again it will trigger segue twice, so two instance of ViewController will be created.
In instruments I can see two instances but one of them is leaked VC object.
Now what I am trying to do is
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
VC2 *vc2 = [segue destinationViewController];
[ary addObject:vc2];
if(ary.count > 1) {
VC2 *vc = (VC2*)ary[1];
vc = nil;
[ary removeObjectAtIndex:1];
}
[ary removeAllObjects];
NSLog(#"-> %#", vc2);
}
to keep a record of VC objects and try to destroy the second obj, so I can prevent memory leak.
But its not working, how to I can fix it?
If you want to cancel your previous request. My suggestion is using NSObject CancelPreviousRequest method
How to implement:
- (IBAction)btn1Action:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(delayedAction) object:nil];
[self performSelector:#selector(delayedAction) withObject:nil afterDelay:1];
}
-(void)delayedAction{
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"popvc2id" sender:self];
});
}
- (IBAction)btn1Action:(id)sender {
__block UIButton * btn = (UIButton*) sender;
btn.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"popvc2id" sender:self];
btn.enabled = YES;
});
NSLog(#"TAP");
}
Wrote by memory, may be compile errors here
when I come the part of sending image from UICollectionViewController to another ViewController here is View A:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Detail Segue"])
{
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
NSIndexPath *path = [[self.collectionView indexPathsForSelectedItems] lastObject];
Photo *selectedPhoto = self.photos[path.row];
PhotoDetailVC.photo = selectedPhoto;
}
}
and I receive it in the ViewController (View B) using:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.imageView.image= self.photo.image;
}
I think the problem is that you didn't call performSegueWithIdentifier:sender: in any place in code which actually responsible for triggering navigation not prepareForSegue:sender: which is called when preparing for the navigation
so I suggest to implement collectionView:didSelectItemAtIndexPath: as the following
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
Photo *selectedPhoto = self.photos[path.row];
// this line is the one that is responsible for navigation
[self performSegueWithIdentifier:#"Detail Segue" sender:selectedPhoto];
}
and modify prepareForSegue:sender: as the following
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"Detail Segue"]) {
PhotoDetailViewController *PhotoDetailVC = segue.destinationViewController;
PhotoDetailVC.photo = sender;
}
}
Couple of months ago I asked a question to show the UISearchDisplayController and it worked like a charm but
Now I am presenting another controller after user taps on the searchResultsController's tableview cell and it selects a cell and hides the searchResultsController to show MapView but once you tap the search bar searchResultsController doesn't shows up but once you press cancel button and tap search bar again it starts working again.
Scenario is exactly the Apple's Maps app opening up favourite view along with recent view controller with segments.
Here's my code for UISearchControllerDelegate:
- (void)willPresentSearchController:(UISearchController *)searchController
{
mainViewController *__weak weakSelf=self;
dispatch_async(dispatch_get_main_queue(), ^{
mainViewController *__strong strongSelf = weakSelf;
strongSelf.searchController.searchResultsController.view.hidden = NO;
});
}
- (void)didPresentSearchController:(UISearchController *)searchController
{
self.searchController.searchResultsController.view.hidden = NO;
}
And here is my code for UISearchBarDelegate.
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
mainViewController *__weak weakSelf=self;
dispatch_async(dispatch_get_main_queue(), ^{
mainViewController *__strong strongSelf = weakSelf;
strongSelf.searchController.searchBar.showsCancelButton = YES;
});
self.searchController.searchResultsController.view.hidden = NO;
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar{
mainViewController *__weak weakSelf=self;
dispatch_async(dispatch_get_main_queue(), ^{
mainViewController *__strong strongSelf = weakSelf;
strongSelf.searchController.searchBar.showsCancelButton = NO;
});
return YES;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
mainViewController *__weak weakSelf=self;
dispatch_async(dispatch_get_main_queue(), ^{
mainViewController *__strong strongSelf = weakSelf;
strongSelf.searchController.searchResultsController.view.hidden = YES;
});
[searchBar resignFirstResponder];
}];
}
i make my custom tab bar using segue it's run successfully , now i try to pass data between two view controller which is on tab bar view controller
my code for tab bar controller
- (void) perform {
ViewController *ctbcv = (ViewController *)self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
for(UIView *view in ctbcv.placeholder.subviews)
{
[view removeFromSuperview];
}
ctbcv.currentViewController = dst;
[ctbcv.placeholder addSubview:dst.view];
}
and segue condition
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"HomeSegue"]
|| [segue.identifier isEqualToString:#"DeveloperSegue"]
|| [segue.identifier isEqualToString:#"DesignerSegue"]|| [segue.identifier isEqualToString:#"btn4"]){
NSLog(#"%lu",(unsigned long)[self.buttons.subviews count]);
for (int i=0; i<[self.buttons.subviews count];i++) {
UIButton *button = (UIButton *)[self.buttons.subviews objectAtIndex:i];
[button setSelected:NO];
}
UIButton *button = (UIButton *)sender;
NSLog(#"%ld", (long)button.tag);
btnclicked = button.tag;
[button setSelected:YES];
}
}
this code run successfully, now i create button on 1st view controller and give segue to the new view controller , it's crash when click on button.
- (void)viewDidLoad {
[super viewDidLoad];
[btnnext addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
-(void) buttonClicked:(UIButton*)sender
{
NSLog(#"you clicked on button %ld", (long)sender.tag);
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
navVC *vc = [segue destinationViewController];
}
}
After this code it crash and Xcode show "THREAD 1: EXC_BAD_ACCESS(code=2 , address = 0xc)" any solution ?
i use this reference for making custom tab bar
i make button which open new view controller in this tab bar.
Thank You
just check out that u have put your code in the main controller that you wants to use and not in tabs of tab bar controller.
I'm trying to implement MWPhotoBrowser in my project. I've added all the delegates, but it still will not display the photo.
Here's my didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"MWPhotoBrowserSegue" sender:self]
}
This is my segue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue identifier] isEqualToString:#"MWPhotoBorwserSegue"])
{
photoBrowser = [[MWPhotoBrowser alloc]initWithDelegate:self];
UINavigationController * nc = [[UINavigationController alloc]initWithRootViewController:photoBrowser];
nc.modalTransitionStyle = UIModalTransitionStyleCrossDisolve;
[photos addObject:[MWPhoto photoWithImage:[UIImage imageNamed:#"picasa.jpg"]];
[photoBrowser setCurrentPhotoIndex:0];
[self.navigationController presentViewController:nc animated:YES completion:nil];
}
}
The #ofPhotosInBrowser:
-(NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser
{
return self.photos.count;
}
photoAtIndex:
- (MWPhoto *)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < self.photos.count)
return [self.photos objectAtIndex:index];
return nil;
}
Here's what I get after the didSelectRowAtIndexPath: is called:
Edit for Solution:
MWPhotoBrowser will not display a photo unless you put self.title in the initWithStyle: method. I also forgot to add the viewWillDisappear and viewWillAppear
I think u need to call reload data on it. Check Mwphotobrowser.h for proper way to do it.
try this [[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self presentViewController:yourNewNavigationController animated:YES completion:nil];
}];