After app launched for a long time,
there are some logs in console while touching the screen:
BKSendHIDEvent: IOHIDEventSystemConnectionDispatchEvent error:0xE00002E8 -- Unknown event dropped
and all buttons have no response, whole app freeze.
Currently, this problem only happened on iPhone 5s.
Similar issue: https://forums.xamarin.com/discussion/55646/alot-of-annotation-on-mkmapview
Does anyone have the same issue?
Update: I've found that there are more than 500 threads when app being killed by iOS, because I use a third party class Reachability too many times. To fix that, I declare a static variable, the freeze seems not happen again.
static Reachability *staticReachability;
+(NetworkStatus)detectNetwork{
if (staticReachability == nil) {
staticReachability = [Reachability reachabilityForInternetConnection];
[staticReachability startNotifier];
}
NetworkStatus status = [staticReachability currentReachabilityStatus];
return status;
}
I have the same problem.
In My case it happends after switch off wifi in iPad (OS 9.1). Application is unresponsive. In console I can see the same errors.
After switch wifi on, application is again responsive and I can continue.
I have got fix for that...
In My case using swift, with Xcode 7.2.
I have used custom label, and func layoutSubviews() call infinite time and console is showing BKSendHIDEvent: IOHIDEventSystemConnectionDispatchEvent
below is fix for same:
class CustomLabel: UILabel {
var isSubLayoutSet: Bool = false
override internal init(frame: CGRect) {
super.init(frame: frame)
}
required internal init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
if isSubLayoutSet == false
{
//--- do your stuff related to set font or any operation...
///---
isSubLayoutSet = true
}
}
fyi, i'm seeing the same console output "unknown event dropped" after updating to iOS 9.3. I'm not sure if it's the OS, or a specific app running a background process, but I see it in many different apps including the home screen as well as immediately on restarting, so I think it's a bug in the latest 9.3 update.
Related
I have the following code to detect my internet connection state
override func viewDidLoad() {
super.viewDidLoad()
internetStatus()
// Do any additional setup after loading the view.
}
func internetStatus(){
let nwPathMonitor = NWPathMonitor()
nwPathMonitor.start(queue: DispatchQueue(label: "network_monitor"))
nwPathMonitor.pathUpdateHandler = { path in
if (path.status == .satisfied){
if (path.usesInterfaceType(.wifi)){
print("wifi")
}
if (path.usesInterfaceType(.cellular)){
print("cellular")
}
}
if (path.status == .unsatisfied)
{
print("noConnection")
}
if (path.status == .requiresConnection){
}
}
}
This works fine but on iOs simulator I am unable to detect reconnects. When I disconnect "noConnection" is printed which fine but when I connect "noConnection" prints again. Is this some sort of bug or there is something wrong in my code
So this works fine on real device but on simulator it doesnot work. I am using macos Big Sur and XCode 12.5
I have an issue with CoreMotion and the following code :
let motionManager = CMMotionManager()
It blocks my Mainthread for 4-5 seconds and I don't know why. The problem appears when I updated my iPhone XR to 12.2. It does not block the mainthread with a iPhone 6S on 12.1.3.
I think it may be a hardware problem or iOS version.
Thank you
CoreMotion is doing a lot on his own during init.
Move the initialisation do a different thread.
Edit:
I can confirm the issue with 12.2 on a development iPhone Xs. No issue on a real used device. I see also violation warnings telling CoreMotion tries to access the Applicationstate from a background thread.
However moving the init to a separate thread fixes any UI hangs here. The init of coremotion still does take a while. I created a empty single view application project and changed the ViewController class
class ViewController: UIViewController {
var motionManager: CMMotionManager?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
view.backgroundColor = UIColor.red
DispatchQueue.global().async {
self.motionManager = CMMotionManager()
DispatchQueue.main.async {
self.view.backgroundColor = UIColor.green
}
}
view.backgroundColor = UIColor.yellow
}
}
Without a separate thread, the red color remains. With a separate thread the color is instant yellow and finally green on the dev XS and instant green on my iPhone 8Plus.
Addition:
Interestingly, without XCode attached, the dev device has no issues.
Try to run your code without being connected to the Debugger.
Basically the problem is the same as this one: XCTestCase: Wait for app to idle
I am using perpetually repeating "background animations" in my views. The UI testing of Xcode/iOS wants to wait for all UIView animations to end before it considers the app idle and goes on with stuff like tapping buttons etc. It just doesn't work with the way we've designed the app(s). (Specifically, we have a button that is animated with UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse options, so it never stops.)
But I'm thinking there might be some way to turn off and/or shorten the state "Wait for app to idle". Is there? How? Is there any other way around this?
You actually can disable wait for app to idle. This is a hack and may not be stable. With animations disabled, and this hack enabled, I am seeing about a 20% performance gain (on top of the performance boost from disabling animations).
All you have to do is swizzle out the method that is called to idle the app and no-op it. That method is XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:
Here is my working solution in swift 3 - there is likely a better way but this works for a proof of concept.
Extend the XCTestCase class. I'll call mine MyTestCase
static var swizzledOutIdle = false
override func setUp() {
if !MyTestCase.swizzledOutIdle { // ensure the swizzle only happens once
let original = class_getInstanceMethod(objc_getClass("XCUIApplicationProcess") as! AnyClass, Selector(("waitForQuiescenceIncludingAnimationsIdle:")))
let replaced = class_getInstanceMethod(type(of: self), #selector(MyTestCase.replace))
method_exchangeImplementations(original, replaced)
MyTestCase.swizzledOutIdle = true
}
super.setUp()
}
#objc func replace() {
return
}
Note wait for app to idle will no longer appear in the logs.
Unfortunately using Apple's UI Testing you can't turn 'wait for app to idle' or poll other network activity, however you can use environment variables to disable animations in your app to make the tests more stable. In your setup method before your test set an environment variable like this.
override func setUp() {
super.setUp()
continueAfterFailure = false
let app = XCUIApplication()
app.launchEnvironment = ["UITEST_DISABLE_ANIMATIONS" : "YES"]
app.launch()
}
Now in your source code:
if (ProcessInfo.processInfo.environment["UITEST_DISABLE_ANIMATIONS"] == "YES") {
UIView.setAnimationsEnabled(false)
}
You can place that check in a specific view if you only want it to disable animations for that specific view or in a delegate file to disable animations throughout the app.
I used gh123man answer in Objective-C in case anyone needs it:
- (void)disableWaitForIdle {
SEL originalSelector = NSSelectorFromString(#"waitForQuiescenceIncludingAnimationsIdle:");
SEL swizzledSelector = #selector(doNothing);
Method originalMethod = class_getInstanceMethod(objc_getClass("XCUIApplicationProcess"), originalSelector);
Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (void)doNothing {
// no-op
}
I was using gh123man's solution in setUp() of a couple of test classes and it worked like a charm until updating to iOS 13.3. Since then app gets stuck in launching state.
Found that it still works if I move it to methods like disableWaitForIdle() and enableWaitForIdle() and call them only in the most granular manner (before and after the tap where I know the app will never become idle), e.g. like this:
#discardableResult func selectOption() -> Self {
disableWaitForIdle()
app.cells["Option"].firstMatch.waitAndForceTap(timeout: 20)
enableWaitForIdle()
return self
}
I translated to Objective-C, and successfully used, h.w.powers' Swift solution, in case anyone needs it.
For setting up:
XCUIApplication *app = [[XCUIApplication alloc] init];
app.launchEnvironment = #{#"UITEST_DISABLE_ANIMATIONS":#"YES"};
[app launch];
and then in your code
if ([[[NSProcessInfo processInfo] environment][#"UITEST_DISABLE_ANIMATIONS"] isEqualToString:#"YES"]) {
// do something like stopping the animation
}
For anyone who intermittently runs into this wait for app to idle problem, I also experienced it a few times while running local XCUITests. Quitting and re-opening the simulator has done the trick for me, not sure exactly why. Maybe some system UIKit stuff getting wacky after the simulator has been running for 2 weeks.
I am having a problem with the proximity sensor on the iPhone. It seems that when the idle timer is disabled and the proximity monitoring is enabled the screen (sometimes) will turn on when receiving a notification. After this the proximity state is reported incorrectly and the screen won't turn off again.
I provided a sample project to illustrate the problem. But the steps to reproduce are quite simple. I tested this on multiple phones (4S, 5, 6, 6+) with multiple iOS versions (7.0.3 and 8.3). It seems to occur most reliably when the phone is not connected to a power source or debugger.
The code in my only ViewController is (the view is created in a storyboard):
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var checkingToggleButton: UIButton!
#IBOutlet weak var debugLabel: UILabel!
#IBOutlet weak var screenDebugLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.checkingToggleButton.setTitle("Start checking", forState: UIControlState.Normal)
self.debugLabel.text = "Not checking"
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("proximityChanged:"), name: "UIDeviceProximityStateDidChangeNotification", object: nil)
}
#IBAction func handleCheckingToggle(sender: AnyObject) {
let enabled = !UIDevice.currentDevice().proximityMonitoringEnabled
if enabled {
self.debugLabel.text = "Checking"
self.checkingToggleButton.setTitle("Stop checking", forState: UIControlState.Normal)
} else {
self.debugLabel.text = "Not checking"
self.checkingToggleButton.setTitle("Start checking", forState: UIControlState.Normal)
}
UIApplication.sharedApplication().idleTimerDisabled = enabled
UIDevice.currentDevice().proximityMonitoringEnabled = enabled
}
func proximityChanged(notification:NSNotification)
{
if UIDevice.currentDevice().proximityState{
self.screenDebugLabel.text = "Proximity true"
println("Proximity true")
} else {
self.screenDebugLabel.text = "Proximity false"
println("Proximity false")
}
}
}
Steps to reproduce:
Build the provided sample project on a device and run the App on the the device disconnected from power and the debugger (this seems to make some difference).
Enable proximityMonitoring and disable the idle timer by pressing the "Start checking" button.
Cover the proximity sensor, this turns the screen off.
Wait approximately 2 minutes (this also makes a difference, doing it too soon won't reproduce the problem)
Send yourself a notification (for instance an iMessage)
The screen will turn on and won't turn off again. We also created a label that shows the current proximityState, the state is (incorrectly) reported as false.
Link to sample project on GitHub:
https://github.com/TimPelgrim/ProximityTest
I've tested a lot of things with the Notification method.
As Asi mentioned it, it doesn't work well. The solution is to observe the variable.
The issue is still there in iOS 11.4.1 (not tested on iOS 12 beta yet).
Swift 4:
// Prepare you observer variable
private var observer: NSKeyValueObservation?
// ...
// Start observing proximityState
self.observer = UIDevice.current.observe(\.proximityState) { [weak self] (device, _) in
print("State changed: \("device.proximityState")")
}
// ...
// Don't forget to call the `invalidate` method on your observer when you want to stop observing
self.observer?.invalidate()
I sent in a technical support issue to the apple engineers and they told me this is a bug in the operating system. No report on when it gets fixed but be advised that this issue seems to be occur in all versions of (at least) iOS 7 and 8 and that there does not seem to be a workaround. I will update here if I receive notice of a fix.
There is actually workaround..
UIDevice.current.proximityState is changing as it should change. but the problem is with the UIDeviceProximityStateDidChange notification.
So the workaround is to create timer that check every x time if UIDevice.current.proximityState changed and that it. just don't use UIDeviceProximityStateDidChange.
I am developing an app that communicates between the watch and the iOS parent app. It sends data from the WatchKit extension to the parent application by opening it. I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch. After that, application:handleWatchKitExtension:reply is called in the app's delegate.
From there you can open a notification to the view controller with:
NSNotificationCenter.defaultCenter().postNotificationName(aName: String, object anObject: AnyObject?)
"aName" is what you can open up in the view conroller with:
NSNotificationCenter.defaultCenter().addObserver(self,
selector: Selector("handleWatchKitNotification:"),
name: "WatchKitSaysHello",
object: nil)
Here is my code for my interface controller in my WatchKit extension:
//
// InterfaceController.swift
// SendColors WatchKit Extension
//
// Created by Tommy on 12/30/14.
// Copyright (c) 2014 Tommy. All rights reserved.
//
import WatchKit
import Foundation
class InterfaceController: WKInterfaceController {
var ypo = false
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
// Configure interface objects here.
}
#IBOutlet weak var redButton: WKInterfaceButton!
#IBOutlet weak var greenButton: WKInterfaceButton!
#IBOutlet weak var blueButton: WKInterfaceButton!
#IBAction func onRedButtonClick() {
if ypo {
openParentAppWithColor("Yellow")
}
else {
openParentAppWithColor("Red")
}
}
#IBOutlet weak var moreButton: WKInterfaceButton!
#IBAction func moreButtonClick() {
if !ypo {
ypo = true
redButton.setTitle("Yellow")
redButton.setColor(UIColor.yellowColor())
greenButton.setTitle("Purple")
greenButton.setColor(UIColor.purpleColor())
blueButton.setTitle("Orange")
blueButton.setColor(UIColor.orangeColor())
moreButton.setTitle("Back")
}
else {
ypo = false
redButton.setTitle("Red")
redButton.setColor(UIColor.redColor())
greenButton.setTitle("Green")
greenButton.setColor(UIColor.greenColor())
blueButton.setTitle("Blue")
blueButton.setColor(UIColor.blueColor())
moreButton.setTitle("More...")
}
}
#IBAction func onGreenButtonClick() {
if ypo {
openParentAppWithColor("Purple")
}
else {
openParentAppWithColor("Green")
}
}
#IBAction func onBlueButtonClick() {
if ypo {
openParentAppWithColor("Orange")
}
else {
openParentAppWithColor("Blue")
}
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
private func openParentAppWithColor(color: String) {
if ["color": color] != nil {
if !WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in
println(reply)
}) {
println("ERROR")
}
}
}
}
My problem is that say for instance I clicked the red button on the watch simulator. The action would be called and in that action it calls openParentApplicationWithColor("Red") which would call WKInterfaceController.openParentApplication(["color": color], reply: { (reply, error) -> Void in }) What this is supposed to do is open the parent app on the simulator. It opens it in the background. I, therefore open it manually. When I open the app manually, the background is completely black. I suspect the problem is that I did not enable App Groups in the Capabilities tab. In order to do that, you need to be in the developer program. Should I join it to do this, or is there another problem? I am using Xcode 6.2 Beta 3. Thank you all in advance!
I have tested and can confirm that openParentApplication:reply: does not require App Groups to be enabled.
I understand that openParentApplication:reply, when called, opens the iPhone application from the Apple Watch.
This method opens the iPhone app in the background. In previous betas of Xcode 6.2 the app did open in the foreground, but this was not the intended behaviour and is not how the WatchKit Extension-iPhone app communication will work in the shipping version.
You can still launch the iPhone app in the foreground manually, but this isn't necessary unless you want to test the use case of both being used at once. At least with the API currently available, the iPhone app it can't be launched programmatically by the watch app to the foreground, and the watch app can't be launched programmatically by the iPhone app.
Once the app launches, you've reported the screen is still black when you expect it to change colour based on the message you've sent it. Is application:handleWatchKitExtension:reply: being called in the iPhone app? You will know it is definitely being called if you are receiving the reply block back for execution in your WatchKit Extension, which should be outputting something from your println(reply). If so, then the issue is with the code in the iPhone app to do something with the message you've passed to it. It would be useful to see your implementation of that method in your AppDelegate of the iPhone app. (Note if that method failed to call the reply block, it might still be receiving the message and you wouldn't get the reply, but then you would be seeing an error message about the reply not being received.)
Note that you won't see NSLog messages or get breakpoints in Xcode when running the Watch extension initially, but you can select Debug > Attach to process > [select your iPhone app under 'Likely targets'] and then you will get the logs and breakpoints of the iPhone app instead of the Watch app, while still being able to use the Watch app in the watch simulator. Most useful for debugging.
No, you no need to make group enable to use ole parent application. you can make a request to open parent IOS application and waiting a reply from IOS App without setting the group app. You only need to setting the group app when you want to share data between watchkit app and IOS app using NSUserDefauts with suite name.
I am using Xcode 6.2 Beta 5. Select Debug > Attach to process > [select your iPhone app under likely targets is not working. I see the NSLogs for Watch extension but not in iPhone app delegate and view controller of iPhone app.