I'm a long-time lurker at Stack Overflow, and joined up today just to post a solution to a problem that has vexed me for weeks, for which I haven't seen the solution anywhere else. Maybe someone else will be helped.
We have an iOS app written in Swift that uses a vendor-supplied SDK to communicate with a specific BLE device. The problem was that iOS would pause the app when it moved into the background rather than leave it running, but would only do this under iOS9. Under iOS10 & 11, everything worked fine in the background.
At first I figured the vendor needed to tweak their SDK code, but their sample application worked fine in the background on iOS9.
Cutting to the chase: our app was instantiating the BLE worker class from within AppDelegate, since it needs to run independently of whatever view is currently displayed on the screen. It finally dawned on me that the biggest difference between our app and the vendor's sample app was that they instantiated the BLE scanning, etc., from within a view controller class.
I modified the code to instantiate the BLE worker object from within the viewDidLoad event of the first view controller, and then set a reference to it in AppDelegate. That did the trick. I'm guessing that iOS9 needs the BLE code to be tied to the main UI processing thread, rather than AppDelegate, in order to know to allow the app to continue to run in the background.
So if you need to communicate with a BLE device when your app is backgrounded, and backgrounding doesn't work for iOS9 devices only, make sure you instantiate the BLE communication from within a View Controller class.
Related
In an Xcode project, how can I write any Swift codes that crashes the Application on startup once it’s launched/run on the simulator or device?
You can follow app lifecycle events in your UIApplicationDelegate. For example application(_:didFinishLaunchingWithOptions:)) is called, when the app started and a little time before it's visible. You can put the crashing code there.
There are a few ways to crash the app. One of them is to call fatalError().
On IOS 5, we now have the notification bar on top to put messages. I have seen that Local Notifications will only happen if the app is in the background (not sure when queued, and / or when the notification is to fire, assume the latter).
Is there any way to put notifications in the notification bar while the app is in the foreground?
From my understanding, your app will be notified of a local notification while the app is running in the application:didReceiveLocalNotification delegate method, but a banner will not be shown at the top of the device screen, not will an entry be put in Notification Center. Your app is notified however, and this is so you can show your own UI for the notification in the app, or choose to ignore it.
Notification Center is only for notifications that you're missed because the app is not in the foreground, and that's why they disappear when the app is opened.
Yes, local notifications work with the simulator. However, make sure you are implementing application:didreceiveLocalNotification in your app delegate if you want to see the nofication while your app is in the foreground (source)
further troubleshooting steps per our conversation in chat and based on the above.
Like i said there are only 2 possibilities of why its not working. placement (in app delegate vs another class) and the application variable. so if it works in the app delegate then im not sure how to resolve that other then making a public method that you can reach from the class you want the notification to come from. probably not the most elegant or proper way but i dont know what else to say.
If its the application variable then make sure you use the same one i posted, application from the applicationfinishloading arguments list vs [[shared application]
Im trying to simulate a touch on as UIWebView, how can I programmatically fire a touch event at a certain location? (x and y coordinates)
Just call touchesBegan?
Ideally I'd like to do it without any javascript hack because in the future it may not be a uiwebview
It's not easy to synthesize a touch event on the iPhone: you have to use undisclosed API, so you have a high probability of breaking on every update of the iOS and getting rejecting from Apple.
Here's a link that demonstrates how to synthesize a touch event on the iPhone:
Here's another question on StackOverflow: How to send a touch event to iPhone OS?
It's worth pointing out the KIF framework here. It's intended to run in the simulator but part of the code is simulating touch evens in code. with luck, this will be a good starting point.
https://github.com/square/KIF
Specifically, look at stepToTapViewWithAccessibilityLabel in KIFTestStep.m and the line
[view tapAtPoint:tappablePointInElement];
What you need to do is first create the events you want, and then send them to SpringBoard over the "purple port" eg. mach port. To make them system wide you must forward them to each application over the port. That means you need to actually do what the windowmanager does and looking at which app is active, screen locked, etc.
There are a hand full of private framework APIs that work (IOSurface, GraphicServices, SpringBoardServices, etc.) to get you the pieces you need.
You will have to load these private frameworks at runtime using something like dlopen().
This is 100% possible without jailbreak as of iOS 6.1.4 (current ATM), but you will be loading private frameworks which is not allowed by apple for AppStore ;)
It is possible. Exactly how you mentioned, using GSEvents and sending them to the purple named port of the aplication you are trying to control/simulate. Of course you need KennyTM's GSEvent.h to accomplish this.
I've done this for iOS 4.3, just by changing some of the values that Kenny had (like kGSHandInfoTypeTouchDown), but now I'm trying to do it for iOS 5 and it's not working, till now.
EDIT: It is now working for iOS 5.1.
Without jailbreaking there is no real way to hook a gesture recognizer into all views of the entire system. First off, your app running in the background doesn't have the ability of executing this code.
I am creating a Universal iOs application as part of an assignment (iPad and iPhone :) ).
Naturally, they have a UI which I have been accustomed to create through the NIB files, using the fancy drag and drop schemes. This obviously seems like a great strategy when you are making a dedicated iOS device application.
However, with the universal application, I notice that this strategy can be a challenge since the 2 UIs differ and human error can promote a lack of consistency in the two UI's + double the work!!!
I noticed the solution to the assignment I am doing has the UI created through the AppDelegate file, I have never really done this, and from this stems the questions:
What is the appDelegate files for anyways?
Is it the way to create the UI for the Universal application through the App delegate? Or do you people still create the UI's through the NIB files meticulously for both iPhone and iPad?
P.S: Side question: This assignment requires me to create a Windows based application vs a View based application which is what I have naturally learnt to do. I understand a Windows based App can grow into a view based application and vice versa. However, I do not understand when you should choose to create a Windows based application?
The AppDelegate in Cocoa is your central Singleton that controls the app workflow. It's used by the underlying Framework to start the application, signal runtime envrionment changes and terminate the app. Being a singleton, it's always there and easy to reference ([UIApplication applicationDelegate]) and it loads up your first view controller.
It's generally common to let the application delegate keep refernces to model and controller objects. But what you describe, the whole UI programmed through the appDelegate, is bad style.
No matter if you use NIB's or you code your UI by manually adding UIElements to the view in code, you should do so in ViewController. Generally, the appDelegate will call the first view controller and that viewcontroller will call all view controller afterwards.
Im trying to simulate a touch on as UIWebView, how can I programmatically fire a touch event at a certain location? (x and y coordinates)
Just call touchesBegan?
Ideally I'd like to do it without any javascript hack because in the future it may not be a uiwebview
It's not easy to synthesize a touch event on the iPhone: you have to use undisclosed API, so you have a high probability of breaking on every update of the iOS and getting rejecting from Apple.
Here's a link that demonstrates how to synthesize a touch event on the iPhone:
Here's another question on StackOverflow: How to send a touch event to iPhone OS?
It's worth pointing out the KIF framework here. It's intended to run in the simulator but part of the code is simulating touch evens in code. with luck, this will be a good starting point.
https://github.com/square/KIF
Specifically, look at stepToTapViewWithAccessibilityLabel in KIFTestStep.m and the line
[view tapAtPoint:tappablePointInElement];
What you need to do is first create the events you want, and then send them to SpringBoard over the "purple port" eg. mach port. To make them system wide you must forward them to each application over the port. That means you need to actually do what the windowmanager does and looking at which app is active, screen locked, etc.
There are a hand full of private framework APIs that work (IOSurface, GraphicServices, SpringBoardServices, etc.) to get you the pieces you need.
You will have to load these private frameworks at runtime using something like dlopen().
This is 100% possible without jailbreak as of iOS 6.1.4 (current ATM), but you will be loading private frameworks which is not allowed by apple for AppStore ;)
It is possible. Exactly how you mentioned, using GSEvents and sending them to the purple named port of the aplication you are trying to control/simulate. Of course you need KennyTM's GSEvent.h to accomplish this.
I've done this for iOS 4.3, just by changing some of the values that Kenny had (like kGSHandInfoTypeTouchDown), but now I'm trying to do it for iOS 5 and it's not working, till now.
EDIT: It is now working for iOS 5.1.
Without jailbreaking there is no real way to hook a gesture recognizer into all views of the entire system. First off, your app running in the background doesn't have the ability of executing this code.