Setting variables with custom class using Websockets and vapor - swift

I am trying to setup a simple vapor web socket. My issue is that I need to maintain the web sockets that are open. In order to do that they need to be stored in a variable. Here is my current code:
import Vapor
var test = [Instance]()
final class Instance {
var socket:WebSocket
var message:String = ""
var id:String = ""
}
extension Droplet {
func setupRoutes() throws {
get("hello") { req in
var json = JSON()
try json.set("hello", "world")
return json
}
}
//Socket code goes here as well
}
I keep getting an error while trying to run my project saying, Use of unresolved identifier 'Instance', Why am I getting this error and how do I fix it? What is the best practicing while using web sockets with vapor?

Related

Trying to figure out Swift Clients for Thrift

I want to utilize thrift from within my new MacOS App. The app is working fine so far as a menubar app.. it takes in a string and lets you save it to memory somewhere... if you click on the clipboard button it saves your string to clipboard.
What I do not understand is.. if I've generated some Swift Client code via the
thrift --gen swift <name_of_thrift_file.thrift>
I get two .swift files, as expected.. AND instructions from the github to rig up the Client object.. here's my Client Object so far.. but I am seeing a error already with the example code. I want to add a status button to the menubar app (anywhere) .. which calls my thrift server for a ping() and goes green once response looks good.
Targeting : Mac OS 12.x+
Thrift Version : v0.16.0
XCode Version : 13.x
happily I hand rolled the library (Thrift) into my project.. for some reason I think the package mangement didn't work.. once added it was a breeze to generate my .thrift files
thrift --gen swift <my_thrift_service>.thrift
once I buttoned all that together in XCode.. the last part was getting a client that worked.. the example in git was showing an error but I got past it with this
AWSBotor3ThriftClient.swift
import Foundation
class AWSBoto3ThriftClient {
var boto3_thrift_client :aws_boto3_accessorClient?
var server_status :Int32
init() {
do {
let transport = try TSocketTransport(hostname: "localhost", port: 9090)
let proto = TBinaryProtocol(on: transport)
let client = aws_boto3_accessorClient(inoutProtocol: proto)
self.boto3_thrift_client = client
self.server_status = try self.boto3_thrift_client!.ping()
} catch {
print("init had a boo boo :(")
self.server_status = 333
self.boto3_thrift_client = nil
}
print(self.server_status)
}
}
S3SyncAppApp.swift
import SwiftUI
#main
struct S3SyncAppApp: App {
#NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#State var currentNumber: String = "1"
var my_little_client: AWSBoto3ThriftClient = AWSBoto3ThriftClient()
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

How to use Resolver when writing unit tests

I hope all is well and you are enjoying WWDC 2020 online. I have a question. I am using the pod 'Resolver' for dependency injection. It is working great. Until I write my unit tests to test my view models. I get this crash:
public final func resolve<Service>(_ type: Service.Type = Service.self, name: String? = nil, args: Any? = nil) -> Service {
if let registration = lookup(type, name: name ?? NONAME),
let service = registration.scope.resolve(resolver: self, registration: registration, args: args) {
return service
}
print("RESOLVER: '\(Service.self):\(name ?? "")' not resolved. To disambiguate optionals use resover.optional().")
fatalError()
}
The test:
import XCTest
import Resolver
class QuizRowViewModelModelTests: XCTestCase {
#Published var quizRepository: QuizRepository = Resolver.resolve()
I have debugged the section where it sets QuizRepository and this works fine.
register { TestDataQuizRepository() as QuizRepository }.scope(application)
Do you happen to have any idea as to why this would happen?
Thanks a million
I'd registered the Repository inside of the setUp function.
override func setUp() {
Resolver.register {
GetAllGuideShopsRepositoryMock(withSuccess: true)
}.implements(GetAllGuideShopsRepository.self)
}
Then, I'd resolved it inside of my test.
sut.getAllGuideShopsRepository = Resolver.resolve(GetAllGuideShopsRepositoryMock.self)
If you want to see more details, please check the Test Class on github.com

Unable to cast to protocol from framework during test cases

So I have a class that comes from one of our internal frameworks. It is defined as follows:
// This lives within a framework
class ExternalClass: ExternalClassProtocol {
// implementation here
}
// This lives within my test target
class MockExternalClass: ExternalClassProtocol {
// Mock implementation here
}
// This lives within the same external frame work as ExternalClass
protocol ExternalClassProtocol: AnyObject {
// Protocol methods here
}
During my test cases, if I try to cast MockExternalClass as? ExternalClassProtocol, the test case crashes.
However, during live app runtime, there is no problem casting ExternalClass as? ExternalClassProtocol.
Is this an issue with trying to implement a protocol from an external module? Is there a way around this?
The class is being accessed through dependency injection (see below dependency injection implementation). The crash occurs on the resolve function.
If you actually debug to this point, you can see that the mock dependency IS in my dependency root (the services array below).
So I know its not failing to cast due to the dependency being missing.
#propertyWrapper
struct Injected<Value> {
var key: String
var wrappedValue: Value {
get { return Dependency.root.resolve(key: self.key) }
set { Dependency.root.add(key: self.key, newValue) }
}
init(key: String) {
self.key = key
}
}
class Dependency {
static let root = Dependency()
var services: [String : Any] = [:]
func add<T>(key: String, _ service: T) {
services[key] = service
}
func resolve<T>(key: String) -> T {
guard let component: T = services[key] as? T else {
// The test crashes here. It works fine on other mocks that are internal to the project
fatalError("Dependency '\(T.self)' not resolved!")
}
return component
}
func clearDependencies() {
self.services.removeAll()
}
private init() {}
}
In my test case:
#testable import MyProject
import ExternalDependency
class TestCase: XCTestCase {
private var subject: ClassWithService!
private var mockInternalClass: MockInternalClassProtocol!
private var mockExternalClass: MockInternallClassProtocol!
func setUp() {
mockExternalClass = MockExternalClass() // This one crashes when trying to cast to its parent protocol
mockInternalClass = MockInternalClass() // This one does not crash when casting to parent protocol.
Dependency.root.add(key: "internal_class", mockInternalClass)
Dependency.root.add(key: "external_class", mockExternalClass)
}
}
Some things I've tried:
Adding AnyObject to the protocol (this fixed a similar issue for internally defined classes that I mock).
changing mockExternalClass type to be the protocol
changing mockExternalClass type to be the implementation
Aside from one protocol being defined in one of our pods, there is no difference between the external protocol and the one we have defined in our own project.
One thing I have noticed is that the cast does not fail if you set a break point inside one of my test case functions. But if you try the same cast within the Dependency.resolve function it crashes. Which leads me to believe there is an issue with the generics.
Any ideas?

Swift Realm getting stuck on re-adding an Object in a write block

I'm using Realm, the project is on version 1.0.0.
When I create a list of Realm Objects (with data obtained from a web API), then try to save them to the Realm using this utility function in a struct:
static func saveRealmObjects(objects: [Object]) {
defer {
// Never entered
}
for object in objects {
let realm = try! Realm()
do {
try realm.write {
print("TEST: 1: object: \(object)")
realm.add(object)
print("TEST: 2")
}
} catch {
// Never entered
}
}
}
(Please don't judge me on the exact structure, I've been toying around seeing if anything will work).
I can tell from liberal use of print statements (mostly removed above) that the function gets to TEST: 1 okay, but fails to make it to TEST: 2, for the very first Object in the list I pass to the function.
I should note this function does work the first time I use it with the data (say after wiping the simulator and launching the app afresh), but then if I recreate the Objects and try to save them again it gets stuck.
I assumed Realm would use the private key on the Objects and overwrite any if necessary. But it seems to just get stuck.
-
Then - after it's stuck - if I try and get another set of results from Realm (using a different Realm object) I get the following error:
libc++abi.dylib: terminating with uncaught exception of type realm::InvalidTransactionException: Cannot create asynchronous query while in a write transaction
FYI I'm creating a different Realm object using try! Realm()
-
For reference, here is the Object I'm trying to save:
import Foundation
import RealmSwift
class MyObject: Object {
// MARK: Realm Primary Key
dynamic var id: String = ""
override static func primaryKey() -> String? {
return "id"
}
// MARK: Stored Properties
dynamic var date: NSDate? = nil
dynamic var numA = 0
dynamic var numB = 0
dynamic var numC = 0
dynamic var numD = 0
dynamic var numE = 0
dynamic var numF = 0
dynamic var numG = 0
dynamic var numH = 0
// MARK: Computed Properties
var computedNumI: Int {
return numD + numE
}
var computedNumJ: Int {
return numF + numG
}
}
(The variable names have been changed.)
-
Hopefully I'm doing something obviously wrong - this is my first time using Realm after all.
If you have any ideas why it's sticking (perhaps it's a threading issue?), or want more info, please answer or comment. Thank you.
Being the clever clogs I am, I've literally just found the answer by reading the documentation:
https://realm.io/docs/swift/latest/#creating-and-updating-objects-with-primary-keys
The add to Realm line needed to look like this:
realm.add(object, update: true)
Where the update flag will update Objects already saved with that primary key.
-
Although it would have been nice if it either gave some sort of obvious warning or crash upon trying to add the same object, or didn't cause other queries and writes to Realm to crash.

Private var is accessible from outside the class

This was done in Playground, just to simplify.
class MyPrivateVar
{
private var priv: String?
}
var myInstance = MyPrivateVar()
myInstance.priv = "Something"
No compiler warning. In fact auto-complete is showing priv without a problem.
My understanding is that outside the boundaries of {} of the class, I'm not supposed to be able to see a private anything, func nor var.
Am I missing something?
Access modifiers in Swift are implemented differently than other languages. There are three levels:
private: accessible only within that particular file
internal: accessible only within the module (project)
public: accessible from anywhere
Unless marked otherwise, everything you write is internal by default.
The Swift blog had a post about access control when the features were introduced in beta 4, and Apple's documentation has a chapter as well.
Note: this answer is for Swift 2
The Swift Programming Language states:
Swift provides three different access levels for entities within your
code. These access levels are relative to the source file in which an
entity is defined, and also relative to the module that source file
belongs to.
If you wan't to test private access level with Swift, the following step by step may help you.
1/ Create a new Xcode project.
2/ Create a file, MyPrivateVar.swift, and add the following code in it:
class MyPrivateVar {
private var priv: String? = nil
}
3/ Create a second file, MySecondClass.swift, and add the following code in it:
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
Xcode will immediatly give you a Swift compiler error message:
'MyPrivateVar' does not have a member named 'priv'
4/ Now, remove the two previous files from your project and create a single file TwoClassesInAFile.swift with the following code in it:
class MyPrivateVar {
private var priv : String? = nil
}
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
This time, you will get no Swift compiler error message and you will be able to access MyPrivateVar's priv private property from MySecondClass because priv and MySecondClass are in the same file (your TwoClassesInAFile.swift file).
Furthermore, access levels also work for global variables. For example, Xcode won't give any compiler error if the following code is part of the same ViewController.swift file:
import UIKit
private var globalPrivate : String? = nil
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
globalPrivate = "some string"
println(globalPrivate)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
However, if you define globalPrivate outside of ViewController.swift, Xcode will generate an error message:
Use of unresolved identifier 'globalPrivate'