MetaWear : CLI application on MACOSX - swift

I am attempting to follow the MetaWear guide on starting a sample application, located here . The problem that I am quickly running into is that I am getting unexpected crashes. Here is how my code is structured
:
Lastly, my Podfile contains the following:
platform :osx, '10.12.6'
target 'meta-wear' do
use_frameworks!
pod 'MetaWear', '~> 2.9'
end
When I run the application, I get a Thread exception as follows on line 5 of the first image:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
While I am certainly a new Swift developer ( noob ), I have no idea why I am unable to reproduce their guide.
Xcode: 9.0
macOS Sierra Version 10.12.6 ( This is where I want to run this command line application )
Update after adding an infinite loop
I updated the main.swift class to ahve the following:
import Foundation
let runLoop = RunLoop.current;
let distantFuture = Date.distantFuture;
print("### we are in the create");
let starter = MetaWearStarter();
print("### we are after the create");
while (runLoop.run(mode: RunLoopMode.defaultRunLoopMode, before: distantFuture)){
print("### listening for a metawear device");
}
I created a class called MetaWearStarter.swift as follows:
import Foundation
import MetaWear
class MetaWearStarter : NSObject {
override init() {
super.init();
print("### we are in the init");
startConnection();
}
func startConnection() {
print("##### connection call was made");
let manager = MBLMetaWearManager.shared();
maanger.startScanForMetaWears() { array in
print("### connection scan was complete")
// Hooray! We found a MetaWear board, so stop scanning for more
MBLMetaWearManager.shared().stopScan()
// Connect to the board we found
if let device = array.first {
device.connectAsync().success() { _ in
print("#### we connected to a device");
}.failure() { error in
print("### unable to connect");
}
}
}
}
}
I get the previous error on this line:
let manager = MBLMetaWearManager.shared();
And my output never makes it past that line:
### we are in the create
### we are in the init
##### connection call was made

An infinite loop to keep the runloop running is not a good habit.
Add a completion handler to your class and stop the runloop on completion.
The usual way to handle the run loop in a CLI is this:
import Foundation
import MetaWear
class MetaWearStarter {
let manager = MBLMetaWearManager.shared()
func startConnection(completion: #escaping (String)->()) {
print("##### connection call was made");
manager.startScanForMetaWears() { array in
print("### connection scan was complete")
// Hooray! We found a MetaWear board, so stop scanning for more
manager.stopScan()
// Connect to the board we found
if let device = array.first {
device.connectAsync().success() { _ in
completion("#### we connected to a device")
}.failure() { error in
completion("### unable to connect, error: \(error.localizedDescription)")
}
} else {
completion("#### no device found")
}
}
}
}
let starter = MetaWearStarter()
let runLoop = RunLoop.current
starter.startConnection { (result) in
print(result)
CFRunLoopStop(runLoop.getCFRunLoop())
}
runLoop.run()
exit(EXIT_SUCCESS)

Related

Threading with Swift on Ubuntu 18.04

I've been trying to reproduce example from on NSCondition here using my Ubuntu 18.04 machine and it seems that threads won't start even though thread_object.start() is called.
Code of the example
import Foundation
let cond = NSCondition()
var available = false
var SharedString = ""
class WriterThread : Thread {
override func main(){
for _ in 0..<5 {
cond.lock()
SharedString = "😅"
available = true
cond.signal() // Notify and wake up the waiting thread/s
cond.unlock()
}
}
}
class PrinterThread : Thread {
override func main(){
for _ in 0..<5 { //Just do it 5 times
cond.lock()
while(!available){ //Protect from spurious signals
cond.wait()
}
Thread.sleep(forTimeInterval:100)
print(SharedString)
SharedString = ""
available = false
cond.unlock()
}
}
}
let writet = WriterThread()
let printt = PrinterThread()
printt.start()
writet.start()
What have I done:
inited project with swift init --type=executable
amended code in Sources/Project/main.swift with the code above
used swift build without any errors
run the compiled object using .build/x86_64-unknown-linux-gnu/debug/Project
And the output is empty, which seems like thread won't start, even if I put print statement as first command inside the threads main. Is there any problem with running threading with Swift on Ubuntu, or do I do something wrong?
The Swift version is 5.5.3

Xcode Trace/BPT trap: 5

Situation
Hi there,
I am developing an iOS app and while building my project I run into the following error message:
Error: Trace/BPT trap: 5
I didn't find anything online to fix this problem, so I wanted to know, if anyone here might be able to help.
I also had issues with Cocoapods and my Silicon Mac, so I want to list my steps I've tried fixing:
Setup
M1 MacBook Pro, macOS 11.1
XCode Version 12.4
Cocoapods with Pods for Firebase Swift, Auth, Firestore and Storage
Steps I tried fixing
cmd + shift + k for cleaning the build folder
closing XCode and opening Terminal using Rosetta
delete ~/Library/Developer/Xcode/Derived Data - Folder
pod deintegrate in project directory
delete Podfile.lock, app.xcworkspace, Pods directory
pod install
in app and pods projects build settings setting Excluded Architectures for any iOS Simulator SDK to arm64
setting Build Active Architecture Only to yes
convert Pods Project to Swift 5
build Pods Project
build app project
And then the following error occurs:
Log
Log enty from Merge swiftmodule (x86_64):
https://pastebin.com/MiSKGxB7
(Log way to long, exceeds character limit).
Code
As the error somewhere tells, it occured while trying to serialize the class BaseViewModel, here's the code from the Base.swift file I wrote containing that class:
import SwiftUI
import Firebase
import FirebaseFirestore
import Combine
protocol BaseModel: Identifiable, Codable {
var id: String? { get set }
var collection: String { get }
init()
}
class BaseViewModel<T: BaseModel>: ObservableObject, Identifiable, Equatable {
#Published var model: T
var id: String {
didSet {
self.model.id = id
}
}
var cancellables = [AnyCancellable]()
private var db = Firestore.firestore()
required init(){
let model = T.init()
self.model = model
self.id = model.id ?? UUID().uuidString
}
required init(id: String) {
var model = T.init()
model.id = id
self.model = model
self.id = id
}
init(model: T) {
self.model = model
self.id = model.id ?? UUID().uuidString
}
static func ==(lhs: BaseViewModel<T>, rhs: BaseViewModel<T>) -> Bool {
lhs.model.id == rhs.model.id
}
func load(completion: #escaping (Bool) -> Void = {finished in}){
if let id = model.id {
self.id = id
db.collection(model.collection).document(id).getDocument { docSnapshot, error in
guard let doc = docSnapshot else {
print("Error fetching document: \(error!)")
return
}
do {
guard let data = try doc.data(as: T.self) else {
print("Document empty \(type(of: self.model)) with id \(id)")
return
}
self.model = data
self.loadSubData {finished in
if finished{
completion(true)
}
}
} catch {
print(error.localizedDescription)
}
}
}
}
func loadSubData(completion: #escaping(Bool) -> Void = {finished in}) {
fatalError("Must be overridden!")
}
func loadDataByIDs<T, S>(from list: [String], appender: #escaping (T) -> Void) where T: BaseViewModel<S>, S: BaseModel {
for id in list {
let viewModel = T.init(id: id)
viewModel.load{finished in
if finished {
appender(viewModel)
}
}
}
}
func save(){
do {
let _ = try db.collection(model.collection).addDocument(from: model)
} catch {
print(error)
}
}
func update(){
if let id = model.id {
do {
try db.collection(model.collection).document(id).setData(from: model)
} catch {
print(error.localizedDescription)
}
}
}
func delete(){
if let id = model.id {
db.collection(model.collection).document(id).delete() { error in
if let error = error {
print(error.localizedDescription)
}
}
}
}
}
I had the same problem, I am solved it after I updated Quick/Nimble.
I guess some pod project with x86 files meed to update to support M1
Well for the record, anybody who is experiencing these odd bugs on M1 must read exactly inside the excode compilation error.
If they are saying a specific class it means xcode can't compile your code and you should just remove the code and try to compile line by line.
I know that's very strange, looks like programming PHP and refreshing a webpage but I'm sure this type of bug can be related to the platform migration.
In my situation, I had a class that was OK, I started refactoring and instead of xcode showing me the compilation errors, it gave this cryptic BPT5, at reading exactly the description inside of the IDE I could find that my class was the root cause.
Just remove the code all over you changed and try to compile it again...
Sorry for the late update on that. But in my case it was either CocoaPods in general or the Firebase Pods, which were not compatible with Apple Silicon at that time.
I was just using Swift Package Manager and with that, it worked.
I do not know though, if the problem still exists, because I didn't build another app on the M1 MacBook.
I run into this issue after I accidently extract a view as variable without awareness. You shall check your recently committed code to figure it out.

iTunesLibrary get all music

I'm new on swift 4.
I'm trying to develop a simple mac program to get all music songs from iTunesLibrary. I did sign my code and import iTunesLibrary.framework to the project. But I get an error about iTlib XPC connection error:
2018-05-29 19:51:16.277312+0700 KODE[2325:47137] ITLib received
XPC_ERROR_CONNECTION_INTERRUPTED connection error (can be ignored).
2018-05-29 19:51:16.277410+0700 KODE[2325:47137] ITLib xpc error:
Connection interrupted
2018-05-29 19:51:16.277441+0700 KODE[2325:47072] Assertion failure:
status == noErr (100005)
Here is my code
override func viewDidLoad() {
super.viewDidLoad()
let library: ITLibrary
do {
library = try ITLibrary(apiVersion: "1.0")
} catch {
print("Error occured!")
return
}
let tracks = library.allMediaItems
for track in tracks {
print(track.album.title!)
}
// Do any additional setup after loading the view.
}
If you have a sandboxed app, go to Capabilites/"App Sandbox"/"File Access"/"Music Folder". Change "None" to "Read Only". It helped me. Also app must be properly signed.

NEVPNManager saveToPreferences/loadFromPreferences callbacks never called

I am trying to setup a IPSec VPN connection but when I try to run
manager.saveToPreferences
or
manager.loadFromPreferences
The callback functions are never called and so I cannot start the VPN Tunnel, and "123" is never printed. The program just ends. What am I doing wrong?
I am testing this in MacOS 10.13.4
import NetworkExtension
import Foundation
let manager = NEVPNManager.shared()
let p = NEVPNProtocolIPSec()
p.authenticationMethod = NEVPNIKEAuthenticationMethod.sharedSecret
p.remoteIdentifier = remoteID
p.localIdentifier = localID
KeychainWrapper.standard.set("SECRET", forKey: "SECRET")
p.sharedSecretReference = KeychainWrapper.standard.dataRef(forKey: "SECRET");
manager.protocolConfiguration = p
manager.onDemandRules = [NEOnDemandRuleConnect()]
manager.isOnDemandEnabled = true
manager.isEnabled = true
manager.saveToPreferences { completionHandler in
manager.loadFromPreferences { completionHandler in
print(123)
do {
try manager.connection.startVPNTunnel()
} catch (let exception) {
print(exception)
}
}
}
I am also having issues configuring the VPN, but this question is more about why those callbacks never get called.
Also, as a side note. When I run
do {
try manager.connection.startVPNTunnel()
} catch (let exception) {
print(exception)
}
outside of saveToPreferences and loadFromPreferences I get the following error:
Error Domain=NEVPNErrorDomain Code=1 "(null)"
Any help would be greatly appreciate, thanks.
Is this just in a .swift file by itself? Try putting the code in a simple application, like inside applicationDidFinishLaunching(). It probably won’t do anything without a running runloop

What is the best practice for terminating a Swift-Server using Perfect during server startup?

I'm using Perfect server-side Swift, and have some conditions in the main.swift where the server should be terminated before actually starting up. Is there a best-practice for handling this termination?
Currently, I'm throwing an error because a return doesn't work-- because it's not in the context of a function (see This is the error I'm throwing and concerned about. below). Here's what I have so far:
//
// main.swift
//
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
enum ServerStartupError : Error {
case FailedUserControllerSetup
}
if !UserController.setup() {
// This is the error I'm throwing and concerned about.
throw ServerStartupError.FailedUserControllerSetup
}
let server = HTTPServer()
let serverRoutes = ServerRoutes()
serverRoutes.addRoutes(server: server)
server.serverPort = 8181
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: \(err) \(msg)")
}
Sorry, my fault, I misunderstood you! Please note that throw in the top level of main.swift is meaningless because the only process who will catch that error is the OS. Please try the code below:
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
if UserController.setup() {
let server = HTTPServer()
let serverRoutes = ServerRoutes()
serverRoutes.addRoutes(server: server)
server.serverPort = 8181
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: \(err) \(msg)")
} catch (let panic) {
print("panic: \(panic)")
} //end server starting
} else {
// here is the code that prompting user to finish the setup
// before running the server. The program will display this
// message and automatically exit the process (end of program)
print("Setup is not completed.")
}//end if
Alternatively, you can also use the exit() function to preform a quit from the main.swift, with importing Foundation (the standard library), as below:
//
// main.swift
//
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import Foundation
if !UserController.setup() {
// This is the error I'm throwing and concerned about.
print("ServerStartupError.FailedUserControllerSetup")
exit(-1)
}//end if
let server = HTTPServer()
let serverRoutes = ServerRoutes()
serverRoutes.addRoutes(server: server)
server.serverPort = 8181
do {
// Launch the HTTP server.
try server.start()
} catch PerfectError.networkError(let err, let msg) {
print("Network error thrown: \(err) \(msg)")
} catch (let panic) {
print("Panic: \(panic)")
}
exit(0)
Both methods have pros and cons. The first one doesn't require anything else while the second one needs Foundation Library; Also I would say that the second one is more traditional and could provide an exit code, which allows you catch the error by wrapping it up in a customize boot loader or something. Unix / Linux uses exit code to check out the application process information and in some cases you can see these exit codes in system log, if available.