I want to print a list of all of the app's viewcontrollers which are loaded in order to understand why am I getting a white screen and for general debugging purposes.
Please advise,
Thanks,
Asaf
You can do some recursive printout like this (I know it's not perfect, but it's a start):
static void printViewControllerRecursively(UIViewController *viewController, NSUInteger level)
{
NSMutableString *spaces = [NSMutableString stringWithCapacity:level * 3];
for (NSUInteger i = 0; i < level; ++i)
{
[spaces appendString:#" "];
}
NSLog(#"%#->%#", spaces, viewController);
if ([viewController isKindOfClass:[UITabBarController class]])
{
for (UIViewController *child in [(UITabBarController *)viewController viewControllers])
{
printViewControllerRecursively(child, level + 1);
}
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
for (UIViewController *child in [(UINavigationController *)viewController viewControllers])
{
printViewControllerRecursively(child, ++level);
}
}
}
Then just call printViewControllerRecursively([UIApplication sharedApplication].keyWindow.rootViewController, 0);
This doesn't seem like a good way to try and debug anyhitng but that being said you can use:
NSLog(#"%#", [self.navigationController viewControllers]);
or
NSLog(#"%#", [self.tabBarController viewControllers]);
etc ...
Guess it depends on how you've setup your App.
Related
I have a UIPageViewController with a page curl (not that the transition type matters as neither works), where the second page doesn't display until the animation is finished. The code use to work, but no longer, any ideas would be great
The code is as follows:
- (void)viewDidLoad
{
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController"];
self.pageViewController.dataSource = self;
self.pageViewController.delegate = self;
// other code deleted, for easy reading
}
- (PsalmViewController *)viewControllerAtIndex:(NSUInteger)index
{
if (([self.mDelegate.mPsalms count] == 0) || (index >= [self.mDelegate.mPsalms count]))
return nil;
// Create a new view controller and pass suitable data.
PsalmViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"PsalmViewController"];
PsalmData *data = [self.mDelegate.mPsalms objectAtIndex:index];
[controller setupView:index psalm:data];
self.mNextPsalm = controller;
return controller;
}
#pragma mark - Page View Controller Data Source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
if (self.mNextIndex == 0 || self.mNextIndex == NSNotFound)
return nil;
self.mNextIndex = self.mPageIndex - 1;
self.mAnimating = true;
NSLog(#"Prev %lud", (unsigned long)self.mNextIndex);
return [self viewControllerAtIndex:self.mNextIndex];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
if (self.mNextIndex == NSNotFound)
return nil;
if (self.mNextIndex + 1 == [self.mDelegate.mPsalms count])
return nil;
self.mNextIndex = self.mPageIndex + 1;
self.mAnimating = true;
NSLog(#"Next %lu", (unsigned long)self.mNextIndex);
return [self viewControllerAtIndex:self.mNextIndex];
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return [self.mDelegate.mPsalms count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (completed)
{
self.mPageIndex = self.mNextIndex;
[self setCurrentPsalm:self.mNextPsalm];
}
else if (finished)
{
self.mNextIndex = self.mPageIndex;
}
if (completed || finished)
self.mAnimating = false;
NSLog(#"C %d F %d", completed, finished);
}
Again any help would be appreciated, I have no idea what is causing this problem.
Say, In my self.navigationController.viewControllers I have n number of viewControllers. Within them, I only want to remain 2 viewControllers in my self.navigationController.viewControllers. One is at 0 index & another one is at 1 index. Here is my code.
NSMutableArray *VCs = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
NSMutableArray *savedVCsArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [VCs count]; i++) {
UIViewController *vc = VCs[i];
if ([vc isKindOfClass:[LanguageSettingsViewController class]]) {
[savedVCsArray insertObject:vc atIndex:0];
} else if ([vc isKindOfClass:[SignInViewController class]]) {
[savedVCsArray insertObject:vc atIndex:1];
}
}
[self.navigationController setViewControllers:savedVCsArray];
NSLog(#"counts %i", [self.navigationController.viewControllers count]);
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
But, here I always get NSLog(#"counts %i", [self.navigationController.viewControllers count]); 0. Is there I am missing something? Thanks in advance. Glad if you reply.
xcode Version 8.3.2 (8E2002)
iOS 10.3
Make sure you confirm that you actually have the VCs you want:
UIViewController *langVC = nil;
UIViewController *signVC = nil;
for (UIViewController *vc in self.navigationController.viewControllers) {
if ([vc isKindOfClass:[LanguageSettingsViewController class]]) {
// [savedVCsArray insertObject:vc atIndex:0];
langVC = vc;
} else if ([vc isKindOfClass:[SignInViewController class]]) {
// [savedVCsArray insertObject:vc atIndex:1];
signVC = vc;
}
}
if (langVC == nil || signVC == nil) {
NSLog(#"Problem exists because langVC is %# / signVC is %#", langVC, signVC);
} else {
[self.navigationController setViewControllers:#[langVC, signVC] animated:YES];
}
I have a UIPageViewController in a UIViewController , I am having a problem where the pageviewcontroller's inner view are not shown [Although I am sure they are loaded from the server]!
Some helpful notes:
UIPageViewController (called :pageController)
Outer UIViewController (called :OfferDetailsViewController)
each viewController inside the pageController is of type OfferBannerPageViewController
Here is my code related to the problem , Please ask for any other blocks of code if you think it will help finding the problem source
some of :OfferDetailsViewController.m :
- (void)viewDidLoad {
[super viewDidLoad];
delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
if(_offerId)
{
_offer = [[Offer alloc]init];
[delegate setUpAConnectionToGetADetailedOffer:_offerId];
//first: load the offer
[self loadOffer];
[self startTimer];
}
}
-(void) loadOffer{
NSMutableString * pathPattern = [NSMutableString stringWithString: #"api/Offers/"];
[pathPattern appendString:_offerId];
[[RKObjectManager sharedManager]getObjectsAtPath:pathPattern parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
if(mappingResult){
_offer = (Offer *)[mappingResult.array firstObject];
//second load the offer banners images
[self setOfferView];
dispatch_async(dispatch_get_main_queue(), ^{
[self loadOfferBanners];
});
}else{
}
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
}
-(void)loadOfferBanners {
_offer.OfferPannerImagesObjects = [[NSMutableArray alloc]init];
for(int index = 0 ; index<_offer.OfferPannerImages.count ;index++){
NSURL *imageURL =[NSURL URLWithString:_offer.OfferPannerImages[index]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
//[UIImage imageWithData:imageData];
if(image){
[_offer.OfferPannerImagesObjects addObject: image];
}
}
if(_offer.OfferPannerImagesObjects.count>0){
[self setUpOfferBanners];
}
}
-(void)setUpOfferBanners {
self.pageController = [[UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
CGRect rect = [self.pagesView bounds];
[[self.pageController view] setFrame:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)];
OfferBannerPageViewController * initialBanner = [self viewControllerAtIndex: 0];
[self.pageController setViewControllers:[NSArray arrayWithObjects:initialBanner, nil] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil ];
[self addChildViewController:self.pageController];
[[self pagesView] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
self.pagesView.clipsToBounds=YES;
self.pagesView.layer.cornerRadius= 6;
}
here is the ViewControllerAtIndex method I debug it and found that index is always whereas when I hover in it after stopping at a break point I see its value as 0!
- (OfferBannerPageViewController *)viewControllerAtIndex:(NSUInteger)index {
OfferBannerPageViewController *offerBannerPageViewController = [[OfferBannerPageViewController alloc] initWithNibName:#"OfferBannerPageViewController" bundle:nil];
offerBannerPageViewController.bannerView = _offer.OfferPannerImagesObjects[index];
offerBannerPageViewController.index = [NSNumber numberWithLong:(long)index];
NSLog(#"____________________ [INDEX = %ld] ___________________",(long)index);
[offerBannerPageViewController.bannerView setImage:_offer.OfferPannerImagesObjects[index]];
return offerBannerPageViewController;
}
any help will be extremely appreciated, Thank you.
update
- (NSInteger)presentationCountForPageViewController: (UIPageViewController*)pageViewController {
// The number of items reflected in the page indicator.
return [_offer.OfferPannerImages count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
NSInteger index = (long)((OfferBannerPageViewController *)viewController).index;
if(index >= _offer.OfferPannerImagesObjects.count){
return nil;
}
index ++;
return [self viewControllerAtIndex:index];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSInteger index = (long)((OfferBannerPageViewController *)viewController).index;
if(index == 0)
return nil;
index--;
return [self viewControllerAtIndex:index];
}
update 2: OfferBannerPageViewController.h
#interface OfferBannerPageViewController : UIViewController
#property (strong,nonatomic) NSNumber * index;
#property (strong,nonatomic)IBOutlet UIImageView * bannerView;
#end
Not sure about this, but maybe you should use autoresizing masks to make sure OfferBannerPageViewController's view resizes width and height along with the superview. It might happen that when you set the frame of pageController.view based on bounds of superview, the bounds are 0 width and height and then doesn't resize.
So try:
[[self.pageController view] setFrame:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)];
[[self.pageController view] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
Have you implemented presentationCountForPageViewController, presentationIndexForPageViewController, viewControllerBeforeViewController and viewControllerAfterViewController methods?
Please, show them.
Having some difficultly with this one.
I am loading questions, answers, correct answers from a plist. All data is being read in fine and looks like below
- (void)viewDidLoad
{
[super viewDidLoad];
rootArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"question" ofType:#"plist"]];
currentQuestion = -1;
[self showNextQuestion];
}
-(void) showNextQuestion{
currentQuestion++;
int numItems = [rootArray count];
NSMutableArray *question = [NSMutableArray arrayWithCapacity:numItems];
NSMutableArray *A = [NSMutableArray arrayWithCapacity:numItems];
NSMutableArray *B = [NSMutableArray arrayWithCapacity:numItems];
NSMutableArray *C = [NSMutableArray arrayWithCapacity:numItems];
NSMutableArray *addimage = [NSMutableArray arrayWithCapacity:numItems];
NSMutableArray *Answer = [NSMutableArray arrayWithCapacity:numItems];
for (NSDictionary *itemData in rootArray) {
[question addObject:[itemData objectForKey:#"question"]];
[A addObject:[itemData objectForKey:#"A"]];
[B addObject:[itemData objectForKey:#"B"]];
[C addObject:[itemData objectForKey:#"C"]];
[addimage addObject:[itemData objectForKey:#"ImageUse"]];
[Answer addObject:[itemData objectForKey:#"ANS"]];
}
self.questionasked.text = question[currentQuestion];
self.answer1.text = A[currentQuestion];
self.answer2.text = B[currentQuestion];
self.answer3.text = C[currentQuestion];
additionImage.image = [UIImage imageNamed:addimage[currentQuestion]];
self.correctAns = Answer[currentQuestion];
if(currentQuestion == 4){
[ self performSegueWithIdentifier:#"levelclear" sender:nil];// here I am performing a segue to indicate that when 4 questions are displayed it will go to this view controller
}
}
I have 3 buttons in my VC, One for each option A,B,C which all have a function
- (IBAction)SelectA:(id)sender {
if ([self.correctAns isEqualToString:#"A"]) {
currentQuestion ++;
[self showNextQuestion];
}
else{
[self performSegueWithIdentifier:#"incorrect" sender:nil];
}
}
- (IBAction)SelectB:(id)sender {
if ([self.correctAns isEqualToString:#"B"]) {
currentQuestion ++;
[self showNextQuestion];
}
else{
[self performSegueWithIdentifier:#"incorrect" sender:nil];
}
}
- (IBAction)SelectC:(id)sender {
if ([self.correctAns isEqualToString:#"C"]) {
currentQuestion ++;
[self showNextQuestion];
}
else{
[self performSegueWithIdentifier:#"incorrect" sender:nil];
}
}
When I answer the question correctly it moves to the next question. However when I answer it incorrectly it goes to the incorrect VC informing of the incorrect question. This VC has a segue when the button is pressed to go back to the question VC(which I made in the storyboard). It does go back to the question VC but simply jumps back to the first question. I know it is something regarding the currentQuestion but not sure what.
Looks like when you segue to the incorrect answer you are destroying the questions view controller, and when yo go back to it, it is re created.
My code is not working on device, could anyone please help..?
- (id) TweetPost : (id) args {
NSArray *arr = args;
_post = [args objectAtIndex: 0];
NSLog(_post, nil);
[_post retain];
ENSURE_UI_THREAD(Tweet, args);
}
- (id) Tweet : (id) args {
NSLog(#"Routine Twitter Module", nil)
if (![_engine isAuthorized]) {
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
if (controller) {
[[TiApp app] showModalController:controller animated: YES];
}
} else {
[_engine sendUpdate: _post];
}
}
While executing this code, on simulator, it works fine but on device the App crashes, instantly after NSLog(_post, nil); in TweetPost method. I think this is due to ENSURE_UI_THREAD(Tweet, args);. Can anyone help me out..?
I have replaced the above both functions with:
- (void) TweetPost : (id) args {
NSArray *arr = args;
_post = [arr objectAtIndex: 0];
[_post retain];
NSLog(_post, nil);
[self Tweet: args];
}
- (void) Tweet : (id) args {
NSLog(#"Routine Twitter Module", nil);
ENSURE_UI_THREAD(Tweet, args);
if (![_engine isAuthorized]) {
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
if (controller) {
[[TiApp app] showModalController:controller animated: YES];
}
} else {
[_engine sendUpdate: _post];
}
}
And this is working fine. I don't know what was the error.