Getting The element hierarchy of the given app - ios

I want to make one internal application(not want to put it on AppStore). In which i have following scenario.
I am putting my app(say "XApp") in background. Now, i open other app in foreground(Say "YApp"). Now, i want to get the current elements hieararchy of the YApp in Xapp. I am having development provisioning profile/certificate for the Yapp.
I just want the Element hierarchy, almost similar to what i get, if i run the UIAutomation of instruments and throw the following command through .js script.
UIATarget.localTarget().frontMostApp().logElementTree();
In short, i need same result as from above command, but without connecting device to any PC via usb cable. It is OK, if it is by using private apis or for jailbroken device. As i have mentioned that, i dont want to put it on App Store.
EDIT:
I can find elements hierarchy of my own app, i.e. for XApp itself, by runnning following code as,
-(void) showViewHeirarchy:(UIView*)v
{
for (UIView *vv in v.subviews)
{
NSLog(#"SubView:%#",[vv description]);
NSLog(#"count:%lu",(unsigned long)vv.subviews.count);
if (vv.subviews.count>0)
{
[self showViewHeirarchy:vv];
}
}
}
Calling above function after viewDidLoad method completed its execution(not in viewDidLoad), and calling it such as:
UIWindow *v=[[UIApplication sharedApplication] keyWindow];
[self showViewHeirarchy:v];
So, can anyone know how to get refrence of UIApplication object of one App from other App(running in background), so that my job will became easier.

Related

WatchKit extension crash: "Program ended with exit code: 0"

For people wanting to reply quickly without reading the post: I am not hitting any memory limits. Read the whole post for details.
My WatchKit extension cannot properly function without the user first being "onboarded" through the phone app. Onboarding is where the user must accept the permissions that we require, so it's very crucial.
On my WatchKit extension, I wanted to display a simple warning for users who had not finished onboarding within our phone app yet.
As such, I thought I'd get the status of onboarding from the phone in two ways:
When the user opens the app/the app is activated (I use the willActivate method to detect this)
When the app finishes onboarding it sends a message to the watch of its completion (if the extension is reachable, of course)
Both of these combined would ensure that the status of onboarding is always kept in sync with the watch.
I wrote the first possibility in, utilizing reply handlers to exchange the information. It worked just fine, without any troubles. The warning telling the user to complete disappears, the extension does not crash, and all is well.
I then wrote in the second possibility, of the extension being reachable when the user finishes onboarding (with the phone then directly sending the companion the new status of onboarding). My extension crashes when it receives this message, and I am stuck with this odd error.
Program ended with exit code: 0
My extension does not even get a chance to handle the new onboarding status, the extension just quits and the above error is given to me.
I am not hitting any sort of memory limit. I have read the technical Q&A which describes what a memory usage limit error looks like, and I don't receive any sort of output like that whatsoever. As well, before the extension should receive the message, this is what my memory consumption looks like.
I have monitored the memory consumption of the extension right after finishing onboarding, and I see not a single spike indicating that I've gone over any kind of threshold.
I have tried going line by line over the code which manages the onboarding error, and I cannot find a single reason that it would crash with this error. Especially since the reply handler method of fetching the onboarding status works so reliably.
Here is the code of how I'm sending the message to the watch.
- (void)sendOnboardingStatusToWatch {
if(self.connected){
[self.session sendMessage:#{
LMAppleWatchCommunicationKey: LMAppleWatchCommunicationKeyOnboardingComplete,
LMAppleWatchCommunicationKeyOnboardingComplete: #(LMMusicPlayer.onboardingComplete)
}
replyHandler:nil
errorHandler:^(NSError * _Nonnull error) {
NSLog(#"Error sending onboarding status: %#", error);
}];
}
}
(All LMAppleWatchCommunicationKeys are simply #define'd keys with exactly their key as the string value. ie. #define LMAppleWatchCommunicationKey #"LMAppleWatchCommunicationKey")
Even though it's never called by the extension, here is the exact receiving code of the extension which handles the incoming data, if it helps.
- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message {
NSString *key = [message objectForKey:LMAppleWatchCommunicationKey];
if([key isEqualToString:LMAppleWatchCommunicationKeyOnboardingComplete]){
BOOL newOnboardingStatus = [message objectForKey:LMAppleWatchCommunicationKeyOnboardingComplete];
[[NSUserDefaults standardUserDefaults] setBool:newOnboardingStatus
forKey:LMAppleWatchCommunicationKeyOnboardingComplete];
dispatch_async(dispatch_get_main_queue(), ^{
for(id<LMWCompanionBridgeDelegate> delegate in self.delegates){
if([delegate respondsToSelector:#selector(onboardingCompleteStatusChanged:)]){
[delegate onboardingCompleteStatusChanged:newOnboardingStatus];
}
}
});
}
}
Before including this onboarding-related code, my WatchKit extension was tested by over 100 people, without any troubles. I am using the exact same custom error dialogue that I was using before, just with a different string. I cannot for the life of me figure out what is causing this crash, and the ambiguity of it has given me very little to work with.
Any help would be greatly appreciated. Thank you very much for taking your time to read my post.
Edit: I just tried creating a symbolic breakpoint for exit(), which is never hit. If I call exit() myself, it calls the breakpoint, so I know the breakpoint itself is working.

Is it possible to dismiss System Alerts using EarlGrey (iOS UI Testing)?

I'm beginning to experiment with EarlGrey a little bit, having done UI Testing using the XCUITest for some months now. I'm running into the classic problem of being unable to dismiss system alerts, which is strange as it looks as though Google implemented a matcher for system alerts called grey_systemAlertViewShown(). I'm trying to detect system alerts using GREYCondition. Here's what I've tried:
- (void)waitForAndDismissSystemAlertForSeconds:(NSInteger)seconds {
GREYCondition *interactableCondition = [GREYCondition conditionWithName:#"isInteractable" block:^BOOL{
// Fails if element is not interactable
NSError *error;
[[EarlGrey selectElementWithMatcher:grey_systemAlertViewShown()] assertWithMatcher:grey_interactable() error:&error];
if (error) {
return NO;
} else {
NSError *allowButtonError;
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(#"Allow")] assertWithMatcher:grey_notNil() error:&allowButtonError];
if (!allowButtonError) {
[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(#"Allow")] performAction:grey_tap()];
}
return YES;
}];
[interactableCondition waitWithTimeout:seconds];
}
I've also tried using addUIInterruptionMonitorWithDescription as described here (but using EarlGrey code to do basically what I am doing above in the interruption monitors): Xcode 7 UI Testing: how to dismiss a series of system alerts in code
Neither approach works. Breakpoints don't fire for the non-error case in my GREYCondition, and the interruption monitor doesn't dismiss my alert either.
Does anybody know if EarlGrey supports dismissing system alerts?
As the docs for grey_systemAlertViewShown indicate, grey_systemAlertViewShown merely checks to see if system alert views are shown. A better usage of the API would be to assert that system alert is not shown (maybe because the test app has mocked out the code that causes system alerts).
Code that taps a button that requests causes system alert to be shown (for ex: requests user's geo location) comes here...
// Assert that in the test app system alert view is not shown because we have mocked out the part of code that requests user location.
[[EarlGrey selectElementWithMatcher:grey_anything()] assertWithMatcher:grey_not(grey_systemAlertViewShown())];
As of this writing system alert views cannot be dismissed by EarlGrey. Alertviews that are launched by the app can be dismissed. The FAQ has a question that indicates that EarlGrey tests will fail if modal dialogs are present.
The best way we found to get around this was to include a launch argument for testing, in which we wouldn't register the app for notifications.
Something like:
if [[[NSProcessInfo processInfo] arguments] containsObject:argument] {
return;
}
before you call
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
This way, the "Do you want to allow push notifications..." alert won't show.
It is possible to grant all the required permissions using AppleSimulatorUtils util.
This approach eliminates the need to dismiss alerts and saves time.
Install an util by entering next commands in the Terminal app
brew tap wix/brew
brew install applesimutils
And grant permission(s) with
applesimutils --byId <simulator UDID> --bundle <bundle identifier> --setPermissions "notifications=YES"
For more info and examples please refer to
https://github.com/wix/AppleSimulatorUtils
EarlGreyImpl.invoked(fromFile: #file, lineNumber: #line).selectElement(with: grey_text("Click")).perform(grey_tap())
//use above code it might work for your problem

How to stop execution of for loop in middle in ios

Hi in my application i have two types of syncs. 1.Auto sync 2.Manual Sync. In both the syncs i am downloding a bunch of files from server. If I choose auto sync all files will get download.
Code is like this
for(int i=0;i<filescount;i++)
{
[self downloadfiles];
}
-(void)download files
{
//Here i am creating `NSInvocationOperation`.
if(!synchingfilecount)
totalreceiveddata=0;
}
Based on totalreceiveddata I am updating progress bar. Now the issue is if it autosync it is working fine.While downloading files using autosync and in middle if i click manual sync that time [self downloadfiles]; method will get called but the issue is synchingfilescount is not updating immediately it's completeing the autosyncfiles download and synchingfilescount become 0 due to this reason totalreceiveddata become 0 and progress bar is disappearing. After complete this opertiona again synchingfilecount becomes 4 but i cannot able to see the progress bar due to above situation. Please any one help me how can I come out from this situation.
Ok, if I understand your question correctly, it sounds like you need to create some flags so that you can manage the flow of your code. You can do this by making a boolean property and setting it as you need in the completion block of these sync methods. That way you can call a method or only execute a method after the call is complete.

IOS:CS193p fall2013 assignment2 task2:add a button to let user to restart the game

I am learning the course CS193P(IOS develop) on itunes and I just started assignment2. I got stuck on the task that asks me to restart the game.
A little bit background on the project: I am writing code for the newly added action method for the restart button in my CardGameViewController. I have two private properties: game and deck. I use lazy initialization in the CardGameViewController to initialize them when user first touch a button(flip a card).(The original project that the professor went over in the lecture is just some cards on the UI and user can flip them around and match them,without the restart function, which is the one I am asked to add in the homework.)
In order for the user to restart the game, I think I need to reinitialize the two properties I mentioned above and update the UI. I tried the following code but the program crashed when I touch the button I just added:
- (IBAction)touchRestartButton:(UIButton *)sender
{
self.game = nil;
self.theDeck = nil;
// Maybe I also need to initialize the two properties again here using some code which I cannot figure out right now....
[self updateUI];
}
Can anyone explain to me how to reinitialize a property in objective-c?(I also tried [self.game release], but the complier prevented me to do this because it says it is in ARC mode)
Or is there any other way to finish this restarting game task?

NSNotificationCenter callback while app in background

One question and one issue:
I have the following code:
- (void) registerForLocalCalendarChanges
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(localCalendarStoreChanged) name:EKEventStoreChangedNotification object:store ];
}
- (void) localCalendarStoreChanged
{
// This gets call when an event in store changes
// you have to go through the calendar to look for changes
[self getCalendarEvents];
}
These methods are in a class/object called CalendarEventReporter which contains the method getCalendarEvents (in the callback).
Two things:
1) If the app is in the background the callback does not run. Is there a way to make it do that?
2) When I bring the app back into the foreground (after having changed the calendar on the device) the app crashes without any error message in the debug window or on the device. My guess is that the CalendarEventReporter object that contains the callback is being garbage-collected. Is that possible? Any other thoughts on what might be causing the crash? Or how to see any error messages?
1) In order for the app to run in the background you should be using one of the modes mentioned in the "Background Execution and Multitasking section here:
uses location services
records or plays audio
provides VOIP
services
background refresh
connection to external devices
like through BLE
If you are not using any of the above, it is not possible to get asynchronous events in the background.
2) In order to see the crash logs/call stack place an exception breakpoint or look into the "Device Logs" section here: Window->Organizer->Devices->"Device Name" on left->Device Logs on Xcode.
To answer your first question, take a look at https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
What I did to get code running in the background is to do something like
In the .h file
UIBackgroundTaskIdentifier backgroundUploadTask;
In the .m file
-(void) functionYouWantToRunInTheBackground
{
self.backgroundUploadTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
//code to do something
}
-(void) endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUploadTask];
self.backgroundUploadTask = UIBackgroundTaskInvalid;
}
The code above I pretty much learned from objective c - Proper use of beginBackgroundTaskWithExpirationHandler
As for your second question, you should set a breakpoint where code is supposed to run when you bring the app back to the foreground. No one can figure out why an app crashes if not given enough code or information.
The solution to the second part of the question was to raise the scope of the object containing the callback code. I raised it to the level of the containing ViewController. This seems to work. I still can't figure out how to raise the Notification (i.e. execute the call back) if the notification comes while the app is in the background/suspended. This prevented the object containing the callback from being cleaned up.

Resources