Skip to content

Instantly share code, notes, and snippets.

@DaisukeNagata
Created December 21, 2019 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DaisukeNagata/81fee237dcccf60e19a4f1da2829ac65 to your computer and use it in GitHub Desktop.
Save DaisukeNagata/81fee237dcccf60e19a4f1da2829ac65 to your computer and use it in GitHub Desktop.
SwiftUI_Combine
import Combine
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = OrientationModel()
var body: some View {
let first = Restaurant(id: 0 ,score: 0.0, login: "a")
let second = Restaurant(id: 1 ,score: 0.0, login: "b")
let third = Restaurant(id: 2 ,score: 0.0, login: "c")
let restaurants = [first, second, third]
if !viewModel.users.isEmpty {
return List(viewModel.users) { restaurant in
RestaurantRow(restaurant: restaurant, model: self.viewModel)
.onAppear {
self.viewModel.fetchImage(for: restaurant)
}
}
} else {
return List(restaurants) { restaurant in
RestaurantRow(restaurant: restaurant, model: self.viewModel)
.onAppear {
self.viewModel.fetchImage(for: restaurant)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Restaurant: Hashable, Identifiable, Decodable {
var id: Int64? = nil
var score: Double
var login: String? = nil
var avatar_url: URL? = nil
}
struct RestaurantRow: View {
var urlPath = "https://api.github.com/search/users"
var restaurant: Restaurant
@ObservedObject var model: OrientationModel
var body: some View {
Text("GitHub login Name \(String(describing: restaurant.login == "" ? "" : restaurant.login!))" +
"\n" +
"GitHub Score \(String(describing: self.restaurant.score.description == "" ? "" : self.restaurant.score.description))")
.onTapGesture {
// API Something
if self.restaurant.id == 0 {
self.model.search(urlPath: self.urlPath, name: self.restaurant.login ?? "")
} else if self.restaurant.id == 1 {
self.model.search(urlPath: self.urlPath, name: self.restaurant.login ?? "")
} else if self.restaurant.id == 2 {
self.model.search(urlPath: self.urlPath, name: self.restaurant.login ?? "")
}
}
}
}
final class OrientationModel: ObservableObject {
@Published private(set) var users = [Restaurant]()
@Published private(set) var userName = [String]()
private var cancellable: Cancellable? {
didSet { oldValue?.cancel() }
}
deinit {
cancellable?.cancel()
}
func search(urlPath: String, name: String) {
guard !name.isEmpty else {
return users = []
}
var urlComponents = URLComponents(string: urlPath)!
urlComponents.queryItems = [
URLQueryItem(name: "q", value: name)
]
var request = URLRequest(url: urlComponents.url!)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
print(request)
cancellable = URLSession.shared.dataTaskPublisher(for: request)
.map { $0.data }
.decode(type: SearchUserResponse.self, decoder: JSONDecoder())
.map { $0.items }
.replaceError(with: [])
.receive(on: RunLoop.main)
.assign(to: \.users, on: self)
}
func fetchImage(for user: Restaurant) {
guard let url = user.avatar_url else { return }
let request = URLRequest(url: url)
_ = URLSession.shared.dataTaskPublisher(for: request)
.map { $0.data}
.replaceError(with: nil)
.receive(on: RunLoop.main)
}
}
struct SearchUserResponse: Decodable {
var items: [Restaurant]
}
@DaisukeNagata
Copy link
Author

gifImage

@DaisukeNagata
Copy link
Author

add SceneDelegate
import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

    // Create the SwiftUI view that provides the window contents.
    let contentView = ContentView()
    let settings = OrientationModel() 

    // Use a UIHostingController as window root view controller.
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: contentView.environmentObject(settings))
        self.window = window
        window.makeKeyAndVisible()
    }
}

func sceneDidDisconnect(_ scene: UIScene) {
    // Called as the scene is being released by the system.
    // This occurs shortly after the scene enters the background, or when its session is discarded.
    // Release any resources associated with this scene that can be re-created the next time the scene connects.
    // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}

func sceneDidBecomeActive(_ scene: UIScene) {
    // Called when the scene has moved from an inactive state to an active state.
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}

func sceneWillResignActive(_ scene: UIScene) {
    // Called when the scene will move from an active state to an inactive state.
    // This may occur due to temporary interruptions (ex. an incoming phone call).
}

func sceneWillEnterForeground(_ scene: UIScene) {
    // Called as the scene transitions from the background to the foreground.
    // Use this method to undo the changes made on entering the background.
}

func sceneDidEnterBackground(_ scene: UIScene) {
    // Called as the scene transitions from the foreground to the background.
    // Use this method to save data, release shared resources, and store enough scene-specific state information
    // to restore the scene back to its current state.
}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment