This error keeps appearing in my code and I can't figure out how to fix it - swift3

I'm making an ios game app in Xcode 8 using swift 3 and I keep getting an error that says "Thread 1: EXC_BAD_INSTRUCTION (codeEXC_1386_INVOP, subcode=0x0)" and a console message that says fatal error: "Index out of range (lldb)". Does anyone know how to fix this?
Here's the section of code with the error. I get it on the line that says 'let nodeB = cableSegments[i]'
for i in 1..<length {
let nodeA = cableSegments[i - 1]
let nodeB = cableSegments[i]
let joint = SKPhysicsJointPin.joint(withBodyA: nodeA.physicsBody!, bodyB: nodeB.physicsBody!,
anchor: CGPoint(x: nodeA.frame.midX, y: nodeA.frame.minY))
scene.physicsWorld.add(joint)
}

The "out of range" error is common in many programming languages. It indicates to you that the loop is trying to access a position in the array that is out of the array range.
Per your code above it's not possible to figure out where are you obtaining the length value, but it should be the array length.
May the code below could work:
var counter = 0
for i in 0..<cableSegments.count {
counter += 1
if counter == cableSegments.count {
break
}
let nodeA = cableSegments[i]
let nodeB = cableSegments[i + 1]
let joint = SKPhysicsJointPin.joint(withBodyA: nodeA.physicsBody!, bodyB: nodeB.physicsBody!,
anchor: CGPoint(x: nodeA.frame.midX, y: nodeA.frame.minY))
scene.physicsWorld.add(joint)
}

Related

XCUIElementQuery in SwiftUI testing returns inconsistent count

I'm doing UI testing of a SwiftUI view, and I have the following code to fetch a List element to check the count of staticTexts in it:
let pred = NSPredicate(format: "identifier == 'detailViewTable'")
let detailViewTable = app.descendants(matching: .any).matching(pred).firstMatch
let arrOfTexts = detailViewTable.staticTexts
let ct = arrOfTexts.count
print("Count is: \(ct)") // This prints 0
print("Count is now: \(detailViewTable.staticTexts.count)") // Also prints 0
The count always prints as 0.
The SwiftUI view basically looks like this:
List {
Section(header: Text("Item list")) {
HStack {
Text("Number")
Spacer()
Text(rec.recNum)
}
}
// Lots more Sections/HStacks/Texts/etc here
// ...
// ...
}
.accessibility(identifier: "detailViewTable")
.listStyle(.grouped)
When I put a breakpoint as shown,
and use po in the Debug Console, I get 0 for ct, but 21 if calling count directly:
(lldb) po ct
0
(lldb) po detailViewTable.staticTexts.count
21
Pic here:
Why is the var ct set to 0, but calling the count directly gives me the correct number 21?
It makes me wonder if the XCUIElementQuery takes a moment to run and returns the answer in some kind of implicit callback, and the data isn't ready at the moment the variable ct is set, but will return the correct answer in the debug console because it waits for the response. However, I don't see any discussion of a callback in the Apple documentation:
https://developer.apple.com/documentation/xctest/xcuielementquery
This answer
https://stackoverflow.com/a/37320452
pointed me in the right direction. The fix is to put a pause in the form of sleep(1), to give the query time to do its fetch, I assume.
let pred = NSPredicate(format: "identifier == 'detailViewTable'")
let detailViewTable = app.descendants(matching: .any).matching(pred).firstMatch
let arrOfTexts = detailViewTable.staticTexts
sleep(1) // <-- Add this
let ct = arrOfTexts.count
print("Count is: \(ct)") // Now prints 21
print("Count is now: \(detailViewTable.staticTexts.count)") // Also prints 21

"Cannot call value of non-function type 'CGVector'" error

I am currently trying to create a Flappy Bird clone on Swift 3. I have run into an error while finishing up with my physics for my "Cow". The error I am getting is "Cannot call value of non-function type 'CGVector'"
This is for a school project. I have already tried looking at top forums on the question and adding dx: and dy: before my numbers.
This is the line of code which is getting the error:
Cow.physicsBody?.velocity(CGVector(dx: 0, dy: 0))
This is my whole code for touchesBegan:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
Cow.physicsBody?.velocity(CGVector(dx: 0, dy: 0))
Cow.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 60))
}
I expect for CGVector to work. To summarize, I am using Swift 3 and am getting this error on my physics code for a Flappy Bird clone.
Please read the documentation:
Unlike function applyImpulse
func applyImpulse(_ impulse: CGVector)
velocity is a property
var velocity: CGVector { get set }
You have to assign the value
Cow.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
Or shorter
Cow.physicsBody?.velocity = CGVector.zero
Or shortest
Cow.physicsBody?.velocity = .zero

Swift 2 to 3 conversion error with Value of type '[Any]' has no member

I'm having a problem with a Swift 2 to 3 conversion piece of work and some of the remains syntax giving: Value of type '[Any]' has no member errors.
I was hoping someone could point me at a good solution.
Swift 2 code
Swift 2 code
func search() {
epsonPrinters = [Printer]()
starPrinters = [Printer]()
epson_startSearching()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [unowned self] in
let devices = SMPort.searchPrinter()
self.starPrinters = devices.map { portInfo -> Printer in
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
if let name = portInfo.modelName as? String {
p.emulation = name.containsString("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}
}
}
Swift 3 Code (I've added comments above areas with errors)
func search() {
epsonPrinters = [Printer]()
starPrinters = [Printer]()
epson_startSearching()
DispatchQueue.global(qos: .background).async { [unowned self] in
let devices = SMPort.searchPrinter()
self.starPrinters = [devices.map { portInfo -> Printer in
// id, model and portName in below fails with messages like:
// Value of type '[Any]' has no member 'modelName'
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
// error on portInfo.modelName
// Value of type '[Any]' has no member 'modelName'
if let name = portInfo.modelName as? String {
p.emulation = name.containsString("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}!]
}
}
I know that I can replace the 'id:...' part with the likes of:
id: ((portInfo[0] as AnyObject).modelName) ?? "",
But this isn't correct because PortInfo can have none, 1 or multiples depending on the number of printers we find.
I'd appreciate any suggestions for refactoring this in an elegant way that is good Swift 3 syntax and likely to survive into Swift 4.
I'm working in Xcode 8.3.2
When you get some errors about types, you'd better check what type each variable has. When you select devices in the line let devices = ..., Quick Help of Xcode will show you something like this:
Declaration let devices: [Any]?
First, it's an Optional and you need to unwrap it, before using the actual content.
Second, the type of the elements in devices is Any, to which you cannot apply any methods (including property accessors). You need to cast it to an appropriate type at an appropriate place.
To solve the two things above, you can write something like this:
guard let devices = SMPort.searchPrinter() as? [PortInfo] else {
fatalError("This may never happen")
}
With guard statement above, Quick Help will show you:
Declaration let devices: [PortInfo]
Non-Optional, simple Array of PortInfo, so you can use any methods of PortInfo for the elements of this devices.
I would translate your Swift 2 code into Swift 3 like this:
func search() {
epsonPrinters = []
starPrinters = []
epson_startSearching()
DispatchQueue.global(qos: .default).async {
guard let devices = SMPort.searchPrinter() as? [PortInfo] else {
fatalError("This may never happen")
}
self.starPrinters = devices.map { portInfo -> Printer in
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
if let name = portInfo.modelName {
p.emulation = name.contains("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}
}
}
You may need some fixes (not many, I believe) to use this code, as you are not showing all relevant things such as the definition of Printer.

Got error of advancedBy on Swift3 conversion

I'm converting my Swift2.3 code to Swift3, and got an error at the line where I used advancedBy. XCode showing me a replacing code that using offsetBy, but I still don't understand.
func unhideEmaimage(_ imageFile: String) {
let dotLocation = imageFile.characters.index(of: ".")
self.emaImage.texture = SKTexture(imageNamed: imageFile)
if dotLocation != nil {
let filenameInitial = imageFile.startIndex
let filenameLast = dotLocation!.advancedBy(-1)
let filenamePart:String = imageFile[filenameInitial...filenameLast]
}
And, following is the code that XCode showing me how to fix the error. However, I still don't know how to modify.
let filenameLast = "String.CharacterView corresponding to your index".index(dotLocation!, offsetBy: -1)
Please let me know the way to fix this error. Thank you in advance.
You should Write this:
let filenameLast = imageFile.index(dotLocation!,offsetBy: -1)

selecting attitude reference frame in IOS 10 coremotion using swift 3

I am trying to use CMMotionManager to update the attitude of a camera viewpoint in scenekit. I am able to get the following code using the default reference to work.
manager.deviceMotionUpdateInterval = 0.01
manager.startDeviceMotionUpdates(to: motionQueue, withHandler:{ deviceManager, error in
if (deviceManager?.attitude) != nil {
let rotation = deviceManager?.attitude.quaternion
OperationQueue.main.addOperation {
self.cameraNode.rotation = SCNVector4(rotation!.x,rotation!.y,rotation!.z,rotation!.w)
}
}
})
I am however unable to get startDeviceMotionUpdates to work with a selected reference frame as shown below:
manager.deviceMotionUpdateInterval = 0.01
manager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrameXMagneticNorthZVertical, to: motionQueue, withHandler:{ deviceManager, error in
if (deviceManager?.attitude) != nil {
let rotation = deviceManager?.attitude.quaternion
OperationQueue.main.addOperation {
self.cameraNode.rotation = SCNVector4(rotation!.x,rotation!.y,rotation!.z,rotation!.w)
}
}
})
The error i receive is:
Use of unresolved identifier 'CMAttitudeReferenceFrameXMagneticNorthZVertical'
I get similar error messages for other reference frames as well. Can anyone shed any light on the use of the "using:" parameter for the startDeviceMotionUpdates function? All the examples i have found are for older versions of swift or objective c so it is quite possible that it is simply an issue with not understanding Swift 3 syntax.
After some additional fiddling i figured out that the using argument expects a member of the new CMAttitudeReferenceFrame struct. i.e. it should be passed as:
manager.deviceMotionUpdateInterval = 0.01
manager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xMagneticNorthZVertical
,to: motionQueue, withHandler:{
deviceManager, error in
if (deviceManager?.attitude) != nil {
let rotation = deviceManager?.attitude.quaternion
OperationQueue.main.addOperation {
self.cameraNode.rotation = SCNVector4(rotation!.x,rotation!.y,rotation!.z,rotation!.w)
}
}
})
This is a change from earlier version that allowed the direct use of constants such as "CMAttitudeReferenceFrameXMagneticNorthZVertical"