How to automatically load subviews for testing? - ios

I'm writing an iOS app that has a problem on a view that's about 4 taps deep into the UINavigation stack. It's becoming a pain to have to repeatedly tap tap tap through the simulator to drill down to the UIViewController I need every time I want to run the thing.
Is there a way to automate this?
I tried just instantly calling [self tableView:self.tableView didSelectIndex... manually, however that blows up because data hasn't been loaded into the table yet...
I'd prefer something fast w/o a lot of overhead to it - otherwise it'll take more time to implement the solution than I'd save by not tapping the screen 4 times...
Thanks for any insight you guys can provide.

I do this all the time - in the appDelegate, I just add some code wrapped in a #ifdef that just makes the subview the initial view of the navigation controller. Once you get the subview working you can turn the ifdef off. Using the technique will save you lots of time - in fact I'm using it right now to add functionality to my app in the store.

Related

Force XCTest to use cached accessibility hierarchy view instead of doing new snapshot

Is this possible to:
Force XCUITest to use cached accessibility hierarchy instead of making a new snapshot for it?
or maybe.. is there any way to control which XCTest actions (tap, swipe, etc) should make a new hierarchy snapshot before instead of using cached one?
I'm having some issues - I'm swiping through 20 pages in my app, they have a lot of elements and each swipe takes approx. 4 seconds, while 3 seconds are spent idle doing nothing on "Snapshot accessibility hierarchy for ..." step which is executed before swipe (automatically) and actually this is not needed at all in my cause because my selector for swipe doesn't change - it's always the same (and I'm not doing any assertions), so while I'm swiping I don't need to refresh hierarchy view, only at the end while I'm totally done swiping - and this is after 19 swipes.
Any suggestions?
I've tried to use EarlGrey in exactly the same screen and it has no issues, everything was really smooth, no delays between swipes. I bet it's getting hierarchy view too before each swipe (I'm not sure, or maybe the secret is that they're using cached hierarchy view in this case and that's why it's fast) but it seems that it takes a lot of less time and it's never noticeable like in XCUITest.
Cheers!

Transitioning from one UIPopoverController to another is slow on iOS8

My app has multiple buttons each of which brings up a different UIPopoverController. We have 'passthroughViews' set so the buttons are still enabled while the popovers are up. Pressing one of the buttons while a popover is displayed dismisses the current popover and brings up the new one. The trouble is, this seems very slow on iOS8. The popovers come up and go away on their own just fine -- it's just when we switch from one to another that there is a pause between when the first one closes and next one starts to show. I'm calling these dismissPopoverAnimated and presentPopoverFromRect: calls back to back, so there is nothing going on between the two. I've tried setting 'animated' to NO for both of these but the pause still remains. Any help is greatly appreciated.
Rather than close the popover, re-purpose the same popover when the 2nd button is pressed. Move the location of the popover, on the screen and load the new content into it. Seems like that would be quicker and avoid whatever contention or latency issues you are experiencing switching from one modal view to the next (I suspect that is what the issue is). You'd lose the disappear/reappear animations, but it should be near instantaneous and provide a good user experience, because users don't really (in the long run) want to wait through animations to see their content when they push a new button anyway.
What's inside these popovers? If they're tied to something running on the main thread, then you are likely seeing that as your lag element. You might want to lean up your viewDidLoad and viewWillAppear methods. Try running largish processes on a background thread and updating it after appearing.
If you are using a core data store then you are likely using the primary context, which always runs on the main thread. Try caching those calls ahead of time, or run your fetches on a child thread and returning those to the main thread after the popover has loaded.
Try this code,
[UIView transitionWithView:pop1.contentViewController.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[pop1 dismissPopoverAnimated:NO];
} completion:^(BOOL finished) {
[pop2 presentPopoverFromRect:btn.bounds inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:NO];
}];
hope it helps.
I had a similar issue that had my head banging on the problem for almost a day: the UIPopoverController was extremely slow to appear on occasion (sometimes it was sluggish, other time almost fine, other it was taking like 4" to appear...), and this happened only on iOs8 (iOs7 was always blink-fast), which leads me to believe that my solution might help you as well.
After much debugging I have come to the conclusion that the problem for me was connected the fact that I showed the popover within the
- (NSIndexPath *) tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
method (but I would'n rule out that other similar cases exist).
My solution is running the presentPopoverFromRect: method (my logs showed it was the slow method) just after the willSelectRowAtIndexPath: method ended (as a matter of fact I crammed the whole popover "initialize and show" in the function to delay as well, to be on the safe side, and because my code was already like that).
This boils down to running the UIPopoverController initialization and display code in a block like this one:
dispatch_async(dispatch_get_main_queue(), ^() {
// Do the popover stuff here
});
Even if you are not using table, other similar problems might exist within iOs8 (because this is an Apple bug!), so I guess this might worth a try...
Hope it helps,
Cheers

How can I get the size of the keyboard on iPhone?

I want to get the keyboard size without using NSNotification. When I press the plus button, it can replace the keyboard with a custom UIView like this:
Then the plus button is pressed and the view loaded:
How can I achieve this?
I already made same rookie mistake like you want to do here. The problem is you will write a lot only to realize you do not want to avoid standard flow provided you by iOS team. For example you will definitely have a bad time dealing with issue like this one (there is additional bar which is part of standard keyboard for Chinese locale):
I solved this by using other people's work from DAKeyboardControl project. You do not need to attach observer (or if you use DAKeyboardControl - block) directly to your bar with buttons, but to your controller and check what user is trying to do and animate this bar accordingly. In the sources you can see how to get keyboard's animation duration and timing function. It may sound more complicated than it indeed is, just give it a try.

UITabBarController switch tab is slow at first time

I am working on an ipad project whose UITabBarController (it's also the root) has 5 tabs.
The second tab is a tableview where there are quite rich UI elements.
The problem is that everytime I launch the app and click the second tab, I would be blocked for 0.3 second to show the viewcontroller. However, after the first time enter this tab, it only takes me 0.03 to enter this tab again.
So I thought the ViewDidLoad cost too much, because I do a lot addSubView or reloadData there. So I add
[libraryVC viewDidLoad];
[libraryVC viewWillAppear:YES];
[libraryVC viewDidAppear:YES];
in application:didFinishLaunchingWithOptions, I think if I do this view load stuff before user enter the second tab, then there will be no block.
However after I tested this approach, I found the cost was not be reduced. So I guess the time cost may be used in the view render when first show this viewcontroller. When the viewcontroller's view has been rendered before, then the following show will be fast. But I have no idea to solve this problem.
I think this problem is very common when the viewcontroller's view is really complicated, so does anyone has an idea of the approach to solve this problem? Or does anyone can give a detail description of the reason why the block happens?
Thanks for any help!
Perhaps multithreading the time intensive methods/calls is the solution you are looking for. If you search "ios grand central dispatch" on Google, some great resources will be available. Apple's Grand Central Dispatch reference is one of the better pieces of documentation they have.

UIViewController viewDidLoad vs. viewWillAppear: What is the proper division of labor?

I have always been a bit unclear on the type of tasks that should be assigned to viewDidLoad vs. viewWillAppear: in a UIViewController subclass.
e.g. I am doing an app where I have a UIViewController subclass hitting a server, getting data, feeding it to a view and then displaying that view. What are the pros and cons of doing this in viewDidLoad vs. viewWillAppear?
viewDidLoad is things you have to do once. viewWillAppear gets called every time the view appears. You should do things that you only have to do once in viewDidLoad - like setting your UILabel texts. However, you may want to modify a specific part of the view every time the user gets to view it, e.g. the iPod application scrolls the lyrics back to the top every time you go to the "Now Playing" view.
However, when you are loading things from a server, you also have to think about latency. If you pack all of your network communication into viewDidLoad or viewWillAppear, they will be executed before the user gets to see the view - possibly resulting a short freeze of your app. It may be good idea to first show the user an unpopulated view with an activity indicator of some sort. When you are done with your networking, which may take a second or two (or may even fail - who knows?), you can populate the view with your data. Good examples on how this could be done can be seen in various twitter clients. For example, when you view the author detail page in Twitterrific, the view only says "Loading..." until the network queries have completed.
It's important to note that using viewDidLoad for positioning is a bit risky and should be avoided since the bounds are not set. this may cause unexpected results (I had a variety of issues...)
This post describes quite well the different methods and what happens in each of them.
currently for one-time init and positioning I'm thinking of using viewDidAppear with a flag, if anyone has any other recommendation please let me know.
Initially used only ViewDidLoad with tableView. On testing with loss of Wifi, by setting device to airplane mode, realized that the table did not refresh with return of Wifi. In fact, there appears to be no way to refresh tableView on the device even by hitting the home button with background mode set to YES in -Info.plist.
My solution:
-(void) viewWillAppear: (BOOL) animated { [self.tableView reloadData];}
Depends, Do you need the data to be loaded each time you open the view? or only once?
Red : They don't require to change every time. Once they are loaded they stay as how they were.
Purple: They need to change over time or after you load each time. You don't want to see the same 3 suggested users to follow, it needs to be reloaded every time you come back to the screen. Their photos may get updated... you don't want to see a photo from 5 years ago...
viewDidLoad: Whatever processing you have that needs to be done once.
viewWilLAppear: Whatever processing that needs to change every time the page is loaded.
Labels, icons, button titles or most dataInputedByDeveloper usually don't change.
Names, photos, links, button status, lists (input Arrays for your tableViews or collectionView) or most dataInputedByUser usually do change.

Resources