swift - мой протокол и делегат не работают - PullRequest
0 голосов
/ 06 апреля 2020

Я создал протокол под названием TermProtocol с функцией внутри, которая называется gotTerm. Всякий раз, когда пользователь нажимает эту кнопку в моем представлении (CategoryView), делегат должен получить обратный вызов и выполнить код, который я установил. Делегатом в моем случае будет AppDelegate. Я поместил оператор print в функцию с именем gotTerm в делегате приложения, чтобы я мог видеть, действительно ли работает код, но я так и не увидел фразу, которую я вставил в оператор print, в консоли. Я не думаю, что мой делегат получает обратный вызов. Кто-нибудь может мне помочь, пожалуйста?

Вот мой код:

TermProtocol:

protocol TermProtocol: class{
    func gotTerm()
}

CategoryView.Swift

struct CategoryView: View {
var foodCategory: String
let appDelegate = UIApplication.shared.delegate as? AppDelegate
var delegate: TermProtocol?
var body: some View {
    NavigationView {

            NavigationLink(destination: RestrauntView()) {
                Image("Find Button")
                    .renderingMode(.original)

            }.simultaneousGesture(TapGesture().onEnded{
                    print("didtapallow 4")
                self.appDelegate!.terms = self.foodCategory
                self.delegate?.gotTerm()
            })
            Spacer()


    }
}
}

struct CategoryView_Previews: PreviewProvider {
    static var previews: some View {
        CategoryView(foodCategory: "Chinese Food")
    }
}

AppDelegate.swift

import UIKit
import CoreData
import Moya
import Alamofire
import CoreLocation

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, TermProtocol {


func gotTerm() {
    print("did get term")
            let lat = self.locationService.setup(latOrLong: "lat")
            let long = self.locationService.setup(latOrLong: "long")
            self.locationService.lat = lat
            self.locationService.long = long

    self.loadBusinesses(lat: lat, long: long, theTerm: self.terms)
}



var theViewModels = [RestrauntListViewModel]()
let locationService = LocationService()
var terms = ""
var categoryView = CategoryView(foodCategory: "indian")
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    categoryView.delegate = self


    let dataSource = DataSource()
    print("this is the view models in appDelegate: \(theViewModels)")


    locationService.didChangeStatus = { [weak self] success in
        print("did tap allow 1")
        if success {
            self?.locationService.getLocation()
        }
    }

    locationService.newLocation = { [weak self] result in
        print("did tap allow 2")
        switch result {
        case .success(let location):
            self?.loadBusinesses(lat: location.coordinate.latitude, long: location.coordinate.longitude, theTerm: "chinese")
        case .failure(let error):
            assertionFailure("Error getting the users location \(error)")
        }
    }
    locationService.setup(latOrLong: "lat")
    return true
}
func loadBusinesses (lat: Double, long: Double, theTerm: String) {

           let service = MoyaProvider<YelpService.BusinessProvider>()
           let jsonDecoder = JSONDecoder()

           let restrauntView = RestrauntView()
        let appDelegate = AppDelegate()
           print("The latitude of u is \(lat) and the long of you is \(long)")


           if CLLocationManager.locationServicesEnabled() {

            switch CLLocationManager.authorizationStatus() {
                   case .notDetermined, .restricted, .denied:
                       print("No access")


                   case .authorizedAlways, .authorizedWhenInUse:
                       print("Access")

                       service.request(.search(lat: lat, long: long, term: theTerm)) { (result) in
                                       switch result{
                                       case.success(let response):
                                           print("yaya")
                                           let root = try? jsonDecoder.decode(Root.self, from: response.data)
                                           let viewModels = root?.businesses.compactMap(RestrauntListViewModel.init)
                                           let dataSource = DataSource()
                                           dataSource.arrayOfImages.removeAll()



                                           for image in viewModels! {

                                                       Alamofire.request(image.imageURL).responseImage { response in
                                                           if let image = response.result.value {
                                                               print("image downloadedline 59 appdelegate")
                                                               dataSource.arrayOfImages.append(image)
                                                               print(dataSource.arrayOfImages)
                                                           } else {
                                                               print("ERROR: image does not = response.result.value")
                                                           }
                                                       }
                                                   }

                                           self.theViewModels = (root?.businesses.compactMap(RestrauntListViewModel.init))!


                                           print(" restrauntView.theViewModels is here \(restrauntView.theViewModels)")

                                           print("the constant theViewModels in the appdelegate has \(appDelegate.theViewModels.count) values")

                                       case .failure(let error):
                                           print("Error: \(error)")
                                       }
                   }

                   @unknown default:
                   break
               }



               } else {
                   print("Location services are not enabled")
           }


       }




// MARK: UISceneSession Lifecycle

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    /*
     The persistent container for the application. This implementation
     creates and returns a container, having loaded the store for the
     application to it. This property is optional since there are legitimate
     error conditions that could cause the creation of the store to fail.
    */
    let container = NSPersistentContainer(name: "Actrual_Food_Circle")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

}

1 Ответ

0 голосов
/ 07 апреля 2020

Я начну с того, что вам не следует использовать делегаты и закрытия таким образом в SwiftUI. Вот довольно хорошее введение в чистую архитектуру MVVM с использованием SwiftUI - https://nalexn.github.io/clean-architecture-swiftui/.

Я полагаю, что вы захотите добавить ViewModel для обработки этих состояний в вашем приложении.

Возвращаясь к ответу на ваш вопрос - я думаю, что в этом контексте добавление замыканий будет быть самым быстрым (не обязательно правильным) решением:

struct ContentView: View {
    var gotTermCallback: (()->())?
    var body: some View {
        NavigationView {
            NavigationLink(destination: Text("test")) {
                ...
                }.simultaneousGesture(TapGesture().onEnded{
                    ...
                    self.gotTermCallback?()
                })
                ...
        }
    }
}

И затем вы можете добавить его к какому-либо обработчику или обработчику побочных эффектов, просто вызвав следующий код:

var contentView: ContentView = ContentView()
contentView.gotTermCallback = {
  print("[DEBUG] - terms callback")
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...