Swift checking internet connection with a button - iphone

I know that a lot of people may have asked quite the same question, but what I would like to do is a little different.
I would like to know how can check if the internet is on, while pressing a button.
When the user press the button, if he isn't connect to the internet the next page won't show up. A message would appear demanding him to connect the internet. Than if he is connect to the internet, when he clicks the button the page would change normally.
Anybody knows how I can do this?
Thanks!

Use this class, call isConnectedToNetwork() when the button is pressed (I'm assuming you know how to use #IBAction). If it returns true let the user know in which ever way you want that there is interwebs.
import Foundation
import SystemConfiguration
enum ReachabilityType {
case WWAN,
WiFi,
NotConnected
}
public class Connected {
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)).takeRetainedValue()
}
var flags: SCNetworkReachabilityFlags = 0
if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 {
return false
}
let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection) ? true : false
}
}
I got this code from somewhere on the internet I don't think this is the exact project I got it from but It seems this guy possibly made it from the same source. https://github.com/Isuru-Nanayakkara/IJReachability/blob/master/IJReachability/IJReachability/IJReachability.swift
Also there is the apple Reachability obj-c files you can use and just use a header.

Related

How to get focused element's cursor position using accessibility API in macOS?

I'm working on a mac app that uses Accessibility APIs to get the cursor position from the focused element (Focused element can be from any app) and shows a window near the cursor position.
I checked the window positioning in native apps like XCode, Notes, and Messages and tried on web apps as well everything is working fine.
I checked the same on the slack desktop app where I'm facing an issue. Which is I'm getting the XOrigin always as 0 and YOrigin as 982 (That is equal to my screen's size: NSScreen.main?.frame.height). Seems it is breaking on electron apps. What am I missing here? Do we need to account for anything else to handle electron apps?
Attaching my code for reference.
extension AXUIElement {
func getCursorRect() -> CGRect? {
guard let cursorPosition = cursorPosition else {return nil}
var cfRange: CFRange = .init(location: cursorPosition, length: 1)
let axval: AXValue? = AXValueCreate(.cfRange, &cfRange)
var bounds: CFTypeRef?
guard let axval = axval else {return nil}
AXUIElementCopyParameterizedAttributeValue(self, kAXBoundsForRangeParameterizedAttribute as CFString, axval, &bounds)
var cursorRect: CGRect = .zero
guard let bounds = bounds else {return nil}
AXValueGetValue(bounds as! AXValue, .cgRect, &cursorRect)
return cursorRect
}
}

Core Bluetooth - Communicate with LED Light

I am working on Core Bluetooth communicate with LED Light. When peripheral write the value to communication, take some time to get response from hardware(LED).As we are using UISLider to write values we are facing delay in hardware. I think a queue occur whenever we are moving slider fast. How can i fix this delay?
let slider0:UInt8 = UInt8(sliderBrightness.value) // Brightness
let slider1:UInt8 = UInt8(mode) // Mode
let slider2:UInt8 = UInt8(sliderDirection.value) // Direction
let slider3:UInt8 = UInt8(sliderStrength.value) // Strength
let slider4:UInt8 = UInt8(sliderWhite.value) // Neutral LED Dimming
let slider5:UInt8 = UInt8(sliderOrange.value) // Warm LED Dimming
let slider6:UInt8 = UInt8(mode == 3 ? sliderOrbit.value : sliderOnTime.value) // According to Mode
let slider7:UInt8 = UInt8(sliderOffTime.value) // According to Mode
let slider8:UInt8 = UInt8(255)
let buff: [UInt8] = [slider0,slider1,slider2,slider3,slider4,slider5,slider6,slider7,slider8]
let data = Data(bytes: buff, count: buff.count)
let sliderVal = Int(sender?.value ?? 0.0)
guard let char = ledChar else {return}
if sender == nil || sliderVal % 1 == 0 {
print(sliderVal)
if sender != nil, previousValue == sliderVal {
return
}
previousValue = sliderVal
pendingRequestWorkItem?.cancel()
let requestWorkItem = DispatchWorkItem { [weak self] in
self?.writeLEDValueToChar( withCharacteristic: char, withValue: data)
}
pendingRequestWorkItem = requestWorkItem
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(12),
execute: requestWorkItem)
One thing you could try would be to get rid of the dispatch queue all together and write the value directly. Of course, some values will not be written since the phone will still be handling the last value transmission. You could simply ignore this error. Something like this could do the trick:
if sender == nil || sliderVal % 1 == 0 {
print(sliderVal)
if sender != nil, previousValue == sliderVal {
return
}
previousValue = sliderVal
writeLEDValueToChar( withCharacteristic: char, withValue: data)
}
Another way could be to not use every possible value from the slider by setting the step width of the slider:
Slider(
value: $speed,
in: 0...100,
step: 5
)
This way you would get only the values 0, 5, 10, 15, ... instead of 0.0000, 0.0001, 0.0002, ... which would decrease the amount of entries in the DispatchQueue while moving the slider

How to solve SceneKit Renderer "EXC_BAD_ACCESS (code=1, address=0xf000000010a10c10)"?

Here is the error I am getting, check the attached picture for more info.
com.apple.scenekit.scnview-renderer (17): EXC_BAD_ACCESS (code=1, address=0xf000000010a10c10)
Here is a log of the error:
I can reproduce this error when I call the following function but only if this function gets called many times within a second. This would happen If the user rapidly taps the button to cycle to the next available car.
As you can see, I tried wrapping this in a DispatchQueue to solve my problem.
You'll also notice that I created a Bool alreadyCyclingCars to track whether the cycleCarNext() function is finished before allowing it to be called again.
This function essentially iterates through all the unlockedCars in the unlockedCars array.
If the type of car matches the one we are currently looking for, I break the loop.
Then we determine the index of the current car to see whether the next car I need to show is the next one in the array (if there is one) if not, we have arrived at the end of the array so I show the first car in the array.
Does anyone know more than I do about this?
Would really be appreciated thank you!
func cycleCarNext() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
if !self.alreadyCyclingCars {
self.alreadyCyclingCars = true
var indexOfCurrentCar = 0
for (index, car) in UserData.shared.unlockedCars.enumerated() {
if car.type == self.overlayScene.currentCarOnDisplay {
indexOfCurrentCar = index
break
}
}
if indexOfCurrentCar < UserData.shared.unlockedCars.count - 1 {
let nextCar = UserData.shared.unlockedCars[indexOfCurrentCar+1]
self.playerNode.removeFromParentNode()
self.playerNode = nextCar
self.playerNode.name = "player"
self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
self.scene.rootNode.addChildNode(self.playerNode)
self.overlayScene.currentCarOnDisplay = nextCar.type
self.overlayScene.updateGarageInterface()
} else {
guard let nextCar = UserData.shared.unlockedCars.first else { return }
self.playerNode.removeFromParentNode()
self.playerNode = nextCar
self.playerNode.name = "player"
self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
self.scene.rootNode.addChildNode(self.playerNode)
self.overlayScene.currentCarOnDisplay = nextCar.type
self.overlayScene.updateGarageInterface()
}
self.alreadyCyclingCars = false
}
}
}
It's my experience that those kind of errors occur when you attempt to modify SceneKit's scene graph (add/remove nodes, etc) outside the SCNSceneRendererDelegate delegate methods.
Imagine you have one thread that is performing rendering at 60fps, and another (eg; the main thread) that removes a node from what is to be rendered. At some point the rendering thread is going to be part way through rendering when what it is rendering is removed by the other thread. This is when the EXC_BAD_ACCESS occurs. The more times the scene is modified, the more likely you are to see this conflict, hence why button mashing could more readily reproduce the issue.
The fix is to only modify your scene in one of SCNSceneRendererDelegate delegate methods. I'd try something like...
func cycleCarNext() {
self.cycleNextCar = true
}
func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
if (self.cycleNextCar) {
self.doCycleNextCar()
self.cycleNextCar = false
}
}
func doCycleNextCar() {
var indexOfCurrentCar = 0
for (index, car) in UserData.shared.unlockedCars.enumerated() {
if car.type == self.overlayScene.currentCarOnDisplay {
indexOfCurrentCar = index
break
}
}
if indexOfCurrentCar < UserData.shared.unlockedCars.count - 1 {
let nextCar = UserData.shared.unlockedCars[indexOfCurrentCar+1]
self.playerNode.removeFromParentNode()
self.playerNode = nextCar
self.playerNode.name = "player"
self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
self.scene.rootNode.addChildNode(self.playerNode)
self.overlayScene.currentCarOnDisplay = nextCar.type
self.overlayScene.updateGarageInterface()
} else {
guard let nextCar = UserData.shared.unlockedCars.first else { return }
self.playerNode.removeFromParentNode()
self.playerNode = nextCar
self.playerNode.name = "player"
self.playerNode.position = SCNVector3(x: 17, y: 0.3, z: 0)
self.playerNode.eulerAngles = SCNVector3(x: 0, y: toRadians(angle: 45),z: 0)
self.scene.rootNode.addChildNode(self.playerNode)
self.overlayScene.currentCarOnDisplay = nextCar.type
self.overlayScene.updateGarageInterface()
}
}
cycleCarNext is to be called by your main thread as it currently is. You'll likely need to set the SCNView's delegate somewhere too (eg; sceneView.delegate = self)
The idea is that while the cycleCarNext boolean is set immediately in the main thread, the scene isn't changed. Instead the change occurs at the correct time/thread in the SceneKit rendering loop.
Faced with the same problem and figured out that this crash caused by personSegmentationWithDepth on devices with LiDAR
if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth) {
configuration.frameSemantics.insert(.personSegmentationWithDepth)
}
I've been struggling with this error for a while, and I just wanted to add a note in case it helps anyone using SCNRenderer, which is that I was using
.render(withViewport:commandBuffer:passDescriptor:)
but this does not call the delegate render method. Instead, use
.render(atTime:viewport:commandBuffer:passDescriptor:)
even if you are not using the time interval parameter, and then the delegate method renderer(_:updateAtTime:) will be called, where you can make the scene updates safely.
If "GPU Frame Capture" is enabled in your scheme disabling it fixes this issue:
In Xcode go to your current scheme -> select »Edit Scheme…« -> Run/Options: set »GPU Frame Capture« to Disabled.
Taken from here.

nsslider.integerValue requires me to focus on another app before updating the value

I have an NSSlider in my macos app, called wave_mode_slider. What I'm trying to do is update the value of said slider on input. So, what I did is this:
self.wave_mode_slider?.integerValue = ("\(params[2])" as NSString).integerValue
This sets the value of the slider (white dot) to the value of the input as intended. However, before I see any actual result, I have to click outside of the application, which causes the white dot of the slider to jump to it's new value. as shown here:
Is there a way to make the slider update immediately?
My slider is created like this:
self.wave_mode_slider = NSSlider(frame:CGRect(x: 10, y: 100, width: 20, height: 300))
self.wave_mode_slider?.cell = OWOWSliderVertical()
self.wave_mode_slider?.maxValue = 127
self.wave_mode_slider?.target = self
self.view?.addSubview(self.wave_mode_slider!)
I tried to set the isContinuous property of the slider to true, but that doen't change the outcome.
edit:
var midiClient : MIDIClientRef = 0
var inPort : MIDIPortRef = 0
let observer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
MIDIClientCreate("WobClient" as CFString, nil, nil, &midiClient)
MIDIInputPortCreate(midiClient, "WobClient_InPort" as CFString, {
(pktList: UnsafePointer<MIDIPacketList>, readProcRefCon: UnsafeMutableRawPointer?, srcConnRefCon: UnsafeMutableRawPointer?) -> Void in
let packetList : MIDIPacketList = pktList.pointee
var packet : MIDIPacket = packetList.packet
let mySelf = Unmanaged<Wob>.fromOpaque(srcConnRefCon!).takeUnretainedValue()
for _ in 1...packetList.numPackets {
let bytes = Mirror(reflecting: packet.data).children
var params : [UInt64] = []
var i = packet.length
for (_, attr) in bytes.enumerated() {
let string = String(format: "%02X ", attr.value as! UInt8)
params.append(UInt64(strtoul(string, nil, 16)))
i -= 1
if (i <= 0) {
break
}
}
// print(("\(params[2])" as NSString).integerValue)
mySelf.setWaveSliderValue(value: ("\(params[2])" as NSString).integerValue)
packet = MIDIPacketNext(&packet).pointee
}
}, nil, &inPort)
MIDIPortConnectSource(inPort, self.source, observer)
This is fro m where i get the value
In the end it was pretty easy, as soon as i saw Willeke's comment about the threading, I just used the main thread to set the value on:
DispatchQueue.main.async {
mySelf.wave_mode_slider?.floatValue = ("\(params[2])" as NSString).floatValue
}

swift error in didBeginContact if running newer iPhone in simulator

this is the Code in the "didBeginContact" method:
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask
{
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{
contact.bodyB.node!.removeFromParent()
}
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
contact.bodyB.node!.removeFromParent()
}
}
else
{
if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000003"{
contact.bodyA.node!.removeFromParent()
}
if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000004"{
contact.bodyA.node!.removeFromParent()
}
}
it works in "iPhone 4s" and "iPhone 5" simulation and fail in a higher version with this error message:
"fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)"
this is the line it marks red:
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
nice to know:
the object with the name "1000004" is a SKSpriteNode I create in the "GameScene" class: let TestPixel = SKSpriteNode(imageNamed: "6")
the property for this object are in the "touchesBegan" method.
here is the code for that:
TestPixel.name = "1000004"
TestPixel.anchorPoint = CGPointMake(0.5, 0.5)
TestPixel.userInteractionEnabled = false
TestPixel.zPosition = 1000003
TestPixel.size = CGSizeMake(1, 1)
TestPixel.position = CGPointMake(positionInScene.x, positionInScene.y)
TestPixel.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "6"), size: TestPixel.size)
TestPixel.physicsBody?.categoryBitMask = ClickOnCategory
TestPixel.physicsBody?.contactTestBitMask = BuildingsCategory
TestPixel.physicsBody?.affectedByGravity = false
TestPixel.physicsBody?.dynamic = true
TestPixel.physicsBody?.collisionBitMask = 0
addChild(TestPixel)
the error occur if this SpriteNode(name:"1000004") hit another SpriteNode which I create in the "didMoveToView" method, here is the code:
func addBG(){
let background = SKSpriteNode(imageNamed: "0")
background.name = "0"
background.anchorPoint = CGPointMake(0.5, 0.5)
background.zPosition = 1
background.position = CGPointMake(CGRectGetMinX(self.frame)+self.frame.width/4,CGRectGetMaxY(self.frame)-self.frame.height/4)
background.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "0"), size: background.size)
background.physicsBody?.categoryBitMask = BuildingsCategory
background.physicsBody?.affectedByGravity = false
background.physicsBody?.dynamic = true
background.physicsBody?.collisionBitMask = 0
self.addChild(background)
}
addBG()
and in the "didMoveToView" also is:
physicsWorld.contactDelegate = self
the categoryBitMask in the "GameScene" class is set like this:
class GameScene: SKScene, SKPhysicsContactDelegate{
let BuildingsCategory : UInt32 = 0x1 << 1
let ClickOnCategory : UInt32 = 0x1 << 2
yeah ok as I said it works in simulator with "iPhone 4s" && "iPhone 5" but not in higher versions... any ideas why?
thanks
Yes, I can tell you why:
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{
contact.bodyB.node!.removeFromParent() <----PROBLEM
}
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
contact.bodyB.node!.removeFromParent()
}
What is happening, is you are hitting your 1st if statement, which does the remove from parent, then you are trying to access it again after. Well if you remove from parent, what is maintaining the node in memory? Probably nothing, so at that first line, it nils out the node. Your code then continues into another if condition, and you are now trying to unwrap a nil. This is where you would use ELSE IF instead of if.
Something else I strongly recommend doing with sprite kit is to never remove nodes during the contact phase. You could have multiple contacts happening, and you may need to handle all of these contact situations, so it is best to keep the node alive.
Instead, whenever you want to remove nodes, place them into a queue (array or set), then on your didFinishUpdate method, loop through the queue and remove all the nodes.
Another trick I do, is I reserve bit 31 on the categoryBitMask to determine if a sprite is alive or dead, then on the didContact methods, I place a guard against it.
E.G.
func didBeginContact(contact: SKPhysicsContact!)
{
guard let bodies = (a:contact.bodyA,b:contact.bodyB) where a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
else
{
return
}
// do other work here
}
Seift 3.0
func didBeginContact(contact: SKPhysicsContact!)
{
guard let bodies = (a:contact.bodyA,b:contact.bodyB, a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
else
{
return
}
// do other work here
}