no response from server: unknown: transportError - swift

I am getting the following error when querying my stitch remote collection in Swift: no response from server: unknown: transportError
This is my test query:
//var aircraftCollection: RemoteMongoCollection<Aircraft>!
var aircraftCollection: RemoteMongoCollection<Document>!
var mongoDb = MongoDB()
class MongoDB: ErrorListener {
init() {
do {
let client = try Stitch
.initializeDefaultAppClient(withClientAppID: "....")
let mongoClient = try client.serviceClient(
fromFactory: remoteMongoClientFactory, withName: "...."
)
client.auth.login(withCredential: UserPasswordCredential(withUsername: "....", withPassword: "....")) { result in
switch result {
case .success(let user):
// Get collections from database
aircraftCollection = mongoClient.db("database").collection("aircraft")
let aircraft = Document(dictionaryLiteral: ("_id", ObjectId()))
aircraftCollection.sync.insertOne(document: aircraft, { (result) in
switch result {
case .success(_):
print("inserted successfully")
case .failure(let e):
fatalError(e.localizedDescription)
}
})
aircraftCollection.find().first { result in
switch result {
case .success(let aircraft):
let aircraftList = aircraft.map { $0 }
print(aircraftList)
case .failure(let error):
// this is where error occurs
print(error.localizedDescription)
}
}
case .failure(let error):
print("Error in login: \(error)")
}
}
} catch let error {
print("do catch error")
print(error)
}
}
My connection seems to be fine, I have another stitch app built in JavaScript on localhost that performs the same query without any trouble.
I am using pod 'StitchSDK', '~> 5.0.0'

This shouldn't matter, but are you intentionally trying to utilize mobile sync, or would you rather just call aircraftCollection.insertOne()

Related

swift async await pause task and waiting for some data

I need to do infinity load while device not connected to the internet
Example: if user lost the internet connection when the app doing a request then app must waiting while internet connection will restore and trying again to do the request
I do it with the completions
func getData(completion: ((SomeData?) -> Void)?) {
apiService.getSomeData() { [weak self] result in
switch result {
case .success(let data):
return data
case .failure(let error):
switch error {
case .networkError:
let getDataTask: () -> Void = {
self?.getData()
}
// when internet connection will be restore then execute all tasks from onConnectionToTheInternetRestoredTasks
self?.onConnectionToTheInternetRestoredTasks.append(getDataTask)
default:
throw error
}
}
}
}
private func onConnectionToTheInternetRestored() {
onConnectionToTheInternetRestoredTasks.forEach { $0() }
onConnectionToTheInternetRestoredTasks = []
}
but now I need to refactor it in async/await
func getData() async throws -> SomeData {
let result = await apiService.getSomeData()
switch result {
case .success(let data):
return data
case .failure(let error):
switch error {
case .networkError:
// need to do wating for restore and try again
default:
throw error
}
}
}
I don't know how to process .networkError in getData() async throws to waiting for restore connection
Can u please explain it to me ?

AWS Amplify Auth.confirmSignIn cannot log out when entering the wrong verify code using custom flow

Amplify Framework Version: 2.1.0
Dependency manager: Swift PM
Swift version: 5.7
CLI version: 10.4.0
Xcode version: 14.1
I get the verify code and I find out I sign up the wrong email, In this case, I couldn't sign in again with the correct email or log out the wrong email.
swift code
func confirm(response: String) async {
do {
let verifyResponse = try await Amplify.Auth.confirmSignIn(challengeResponse: response)
print("Confirm sign in succeeded")
print("verifyResponse : \(verifyResponse.nextStep)")
switch verifyResponse.nextStep {
case .done:
print("Signin complete")
DispatchQueue.main.async {
Task{
print("confirm func")
self.authState = .test
}
}
case .confirmSignInWithCustomChallenge(_):
print("confirmSignInWithCustomChallenge")
DispatchQueue.main.async {
Task{
await self.signOut()
self.authState = .login
}
}
print("")
case .confirmSignInWithSMSMFACode(_, _):
print("")
case .confirmSignInWithNewPassword(_):
print("")
case .resetPassword(_):
print("")
case .confirmSignUp(_):
print("")
}
} catch let error as AuthError {
print("Confirm sign in failed \(error)")
self.authState = .login
} catch {
print("Unexpected error: \(error)")
}
}
lambda code (Verify Auth Challenge Response)
exports.handler = async(event) => {
const expectedAnswer = event.request.privateChallengeParameters.secretLoginCode;
if (event.request.challengeAnswer === expectedAnswer) {
event.response.answerCorrect = true;
}
else {
event.response.answerCorrect = false
}
return event
};

Failed to decode data coming from client

I am following Ray Wanderlich's book 'Server Side Swift with Vapor' and I am at chapter 26: Adding profile pictures.
First, I defined this struct:
struct ImageUploadData: Content {
var picture: Data
}
Then, in a route I try to decode it:
func postProfilePictureHandler(_ req: Request) throws -> EventLoopFuture<User> {
let data = try req.content.decode(ImageUploadData.self)
...
From the client side, I use Alamofire:
#discardableResult func uploadProfilePicture(for user: User, data: Data) async throws -> User {
enum Error: LocalizedError {
case missingUserID
}
guard let userID = user.id else {
throw Error.missingUserID
}
let appendix = "\(userID)/profilePicture"
let parameters = [
"picture": data
]
return try await withCheckedThrowingContinuation { continuation in
Task {
AF.request(baseUrl + appendix, method: .post, parameters: parameters).responseData { response in
switch response.result {
case .success(let data):
do {
let user = try JSONDecoder().decode(User.self, from: data)
continuation.resume(returning: user)
} catch {
continuation.resume(throwing: error)
}
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
}
In my integration tests, I create the picture's data like this:
guard let data = image?.pngData() else {
throw Error.missingPictureData
}
And then I pass it to the above method. The problem is that in the server side, the decoding fails with this error:
The data couldn’t be read because it is missing.
Just to understand if I was doing something else wrong, I tried the above methods with one difference: I replace the type 'Data' with 'String':
struct ImageUploadData: Content {
var picture: String
}
This wouldn't be useful for me because I need a data object, but just as a test to see if this doesn't produce an error, I tried and indeed this is decoded successfully. So I suspect that the problem is in how I encode the data before sending it to the server, but I don't know what's wrong.

Wrapping asynchronous code in Swift's Combine publisher

I have a class called QueryObserver that can produce multiple results over time, given back as callbacks (closures). You use it like this:
let observer = QueryObserver<ModelType>(query: query) { result in
switch result {
case .success(let value):
print("result: \(value)")
case .failure(let error):
print("error: \(error)")
}
}
(QueryObserver is actually a wrapper around Firebase Firestore's unwieldy query.addSnapshotListener functionality, in case you were wondering. Using modern Result type instead of a callback with multiple optional parameters.)
In an older project I am using ReactiveKit and have an extension that turns all this into a Signal, like so:
extension QueryObserver {
public static func asSignal(query: Query) -> Signal<[T], Error> {
return Signal { observer in
let queryObserver = QueryObserver<T>(query: query) { result in
switch result {
case .success(let value):
observer.receive(value)
case .failure(let error):
if let firestoreError = error as? FirestoreError, case .noSnapshot = firestoreError {
observer.receive([])
} else {
observer.receive(completion: .failure(error))
}
}
}
return BlockDisposable {
queryObserver.stopListening()
}
}
}
}
In a brand new project though, I am using Combine and am trying to rewrite this. So far as I have managed to write this, but it doesn't work. Which makes sense: the observer is not retained by anything so it's immediately released, and nothing happens.
extension QueryObserver {
public static func asSignal(query: Query) -> AnyPublisher<[T], Error> {
let signal = PassthroughSubject<[T], Error>()
let observer = QueryObserver<T>(query: query) { result in
switch result {
case .success(let value):
print("SUCCESS!")
signal.send(value)
case .failure(let error):
if let firestoreError = error as? FirestoreError, case .noSnapshot = firestoreError {
signal.send([])
} else {
signal.send(completion: .failure(error))
}
}
}
return signal.eraseToAnyPublisher()
}
}
How do I make the Combine version work? How can I wrap existing async code? The only examples I found used Future for one-off callbacks, but I am dealing with multiple values over time.
Basically I am looking for the ReactiveKit-to-Combine version of this.
Check out https://github.com/DeclarativeHub/ReactiveKit/issues/251#issuecomment-575907641 for a handy Combine version of a Signal, used like this:
let signal = Signal<Int, TestError> { subscriber in
subscriber.receive(1)
subscriber.receive(2)
subscriber.receive(completion: .finished)
return Combine.AnyCancellable {
print("Cancelled")
}
}

Not sure how to implement the SMB project into my app

I'm trying to implement SMB into my app and found this https://github.com/amosavian/AMSMB2. I'm not sure how to implement this code into the UI of my app. For example, do I connect the connect function to a button and if so how would I proceed to do so. What would I put into the parameters of connect() when I call it if I call it.
Here's the code from the repository:
import AMSMB2
class SMBClient {
/// connect to: `smb://guest#XXX.XXX.XX.XX/share`
let serverURL = URL(string: "smb://XXX.XXX.XX.XX")!
let credential = URLCredential(user: "guest", password: "", persistence: URLCredential.Persistence.forSession)
let share = "share"
lazy private var client = AMSMB2(url: self.serverURL, credential: self.credential)!
private func connect(handler: #escaping (Result<AMSMB2, Error>) -> Void) {
// AMSMB2 can handle queueing connection requests
client.connectShare(name: self.share) { error in
if let error = error {
handler(.failure(error))
} else {
handler(.success(self.client))
}
}
}
func listDirectory(path: String) {
connect { result in
switch result {
case .success(let client):
client.contentsOfDirectory(atPath: path) { result in
switch result {
case .success(let files):
for entry in files {
print("name:", entry[.nameKey] as! String,
", path:", entry[.pathKey] as! String,
", type:", entry[.fileResourceTypeKey] as! URLFileResourceType,
", size:", entry[.fileSizeKey] as! Int64,
", modified:", entry[.contentModificationDateKey] as! Date,
", created:", entry[.creationDateKey] as! Date)
}
case .failure(let error):
print(error)
}
}
case .failure(let error):
print(error)
}
}
}
func moveItem(path: String, to toPath: String) {
self.connect { result in
switch result {
case .success(let client):
client.moveItem(atPath: path, toPath: toPath) { error in
if let error = error {
print(error)
} else {
print("\(path) moved successfully.")
}
// Disconnecting is optional, it will be called eventually
// when `AMSMB2` object is freed.
// You may call it explicitly to detect errors.
client.disconnectShare(completionHandler: { (error) in
if let error = error {
print(error)
}
})
}
case .failure(let error):
print(error)
}
}
}
}
late but for reference as i couldnt find much when i tried
add the amsmb2 library and that template class file to your project
in the class file set serverurl, share, credential correctly for your smb server
then
declare a variable of class smb_client
then from your button or whatever
var myclient:smb_client=smb_client()
myclient.connect()
to connect to your smb server for example
you can extend that class templete to download/upload items etc
the operations are asynchronous