Sobes.tech

iOS

struct CustomButtonStyleView: View { var body: some View { VStack { Button("Button") { print("Tapped") } } .buttonStyle(CustomButtonStyle()) } } private struct CustomButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .padding() .foregroundColor(.white) .frame(maxWidth: .infinity) .background(Color.red) .clipShape(RoundedRectangle(cornerRadius: 8)) } }

Senior
Salmon
37

finale klasse Cache<T>: CacheProtocol { func getValue(forKey key: String) -> T? { return storage[key] } func fetchValue(forKey key: String, completion: @escaping (T?) -> Void) { let value = storage[key] completion(value) } } finale klasse CacheTests: XCTestCase { override func setUp() { super.setUp() } func testSetAndGetValue() { let cache = Cache<String>() let key: String = "key" let value: String = "value" cache.setValue(value, forKey: key) XCTAssertEqual(cache.getValue(forKey: key), value) cache.setValue(nil, forKey: key) XCTAssertTrue(cache.getValue(forKey: key) == nil) } func testCompletion() { } } CacheTests.defaultTestSuite.run()

Middle+
RevolutRevolut
37

Leg het verschil uit tussen een in-memory cache en een on-disk cache.

Middle+
RevolutRevolut
35

Vertel over nuttige Property Wrappers die je in het project hebt gebruikt

Senior
Salmon
35

protocol CacheProtocol { associatedtype Value func setValue(_ value: Value?, forKey key: String) func getValue(forKey key: String) -> Value? func fetchValue(forKey key: String, completion: @escaping (Value?) -> Void) } final class Cache<T>: CacheProtocol { private var storage: [String: T] = [:] func setValue(_ value: T?, forKey key: String) { storage[key] = value } func getValue(forKey key: String) -> T? { return storage[key] } func fetchValue(forKey key: String, completion: @escaping (T?) -> Void) { let value = storage[key] completion(value) } } import XCTest final class CacheTests: XCTestCase { override func setUp() { super.setUp() } func testSetAndGetValue() { let cache = Cache<String>() let key: String = "key" let value: String = "value" cache.setValue(value, forKey: key) XCTAssertEqual(cache.getValue(forKey: key), value) cache.setValue(nil, forKey: key) XCTAssertTrue(cache.getValue(forKey: key) == nil) } } CacheTests.defaultTestSuite.run()

Middle+
RevolutRevolut
34

Als je een nieuw scherm of een nieuwe functie implementeert, schrijf je dan meteen in SwiftUI, of zijn er discussies over de keuze tussen UIKit en SwiftUI?

Senior
Salmon
34

// Schrijft `data` naar een bestand genaamd `file`. func writeData(_ data: Data, to file: String) { let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectoryURL.appendingPathComponent(file) try? data.write(to: fileURL) } // Verwijdert het bestand genaamd `file`. func remove(file: String) { let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectoryURL.appendingPathComponent(file) try? FileManager.default.removeItem(at: fileURL) } // Leest `Data` uit een bestand genaamd `file`. Als het bestand niet bestaat, geeft het `nil` terug. func readData(from file: String) -> Data? { let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentDirectoryURL.appendingPathComponent(file) return try? Data(contentsOf: fileURL) } final class DiskCache<T>: CacheProtocol { func setValue(_ value: T?, forKey key: String) { } func getValue(forKey key: String) -> T? { } func fetchValue(forKey key: String, completion: @escaping (T?) -> Void) { } }

Middle+
RevolutRevolut
34

Vertel me over het gebruik van SwiftUI in het project — wat is het beleid, hoeveel schermen zijn geschreven in SwiftUI

Senior
Salmon
32

import UIKit protocol CacheProtocol { associatedtype Value func setValue(_ value: Value?, forKey key: String) func value(forKey key: String) -> Value? func fetchValue(forKey key: String, completion: @escaping (Value?) -> Void) }

Middle+
RevolutRevolut
32

Waarom hebt u aparte load- en getLastCities-methoden gemaakt, en wat moet er gebeuren als getLastCities wordt aangeroepen voordat de gegevens zijn geladen?

Senior
Uzum
31

Hoe zou je de geïdentificeerde problemen prioriteren als het project over een uur in productie moet gaan?

Senior
Uzum
31

import UIKit protocol CacheProtocol { associatedtype Value func setValue(_ value: Value?, forKey key: String) func getValue(forKey key: String) -> Value? func fetchValue(forKey key: String, completion: @escaping (Value?) -> Void) } final class Cache<T>: CacheProtocol { private var storage: [String: T] = [:] private let queue = DispatchQueue(label: "my.queue", attributes: .concurrent) func setValue(_ value: T?, forKey key: String) { queue.sync(flags: .barrier) { storage[key] = value } } func getValue(forKey key: String) -> T? { queue.sync { return storage[key] } } func fetchValue(forKey key: String, completion: @escaping (T?) -> Void) { queue.async { let value = self.storage[key] completion(value) } } }

Middle+
RevolutRevolut
28

Hoe begrijp je de term gestructureerde concurrency in Swift? Past Task.detached binnen dit begrip?

Senior
Salmon
27

Waarom een finale klasse gebruiken in plaats van een klasse voor de cache-implementatie?

Middle+
RevolutRevolut
22

// Service die verzoeken verzendt (get/post), url, opbouw van het verzoek afhankelijk van de semantiek (decode/encode)

Middle+
СБЕРСБЕР
14

enum HTTPMethod: String { case post = "POST" } enum Errors: Error { case invalidUrl case invalidQuery case invalidResponse case httpStatus(Int) } protocol MyDecoder { func decode<T: Decodable>(_: _ type: T.Type, from data: Data) throws -> T } final class NetworkService { private let session: URLSession private let encoder = JSONEncoder() private let decoder: MyDecoder init( session: URLSession = .shared, decoder: MyDecoder ) { self.session = session self.decoder = decoder } func request<Response: Decodable, Body: Encodable>( urlString: String, method: HTTPMethod, body: Body? = nil, headers: [String: String] = [:], query: [String: String] = [:] ) async throws -> Response { guard var components = URLComponents(string: urlString) else { throw Errors.invalidUrl } if !query.isEmpty { components.queryItems = query.map { URLQueryItem(name: $0.key, value: $0.value) } } guard let url = components.url else { throw Errors.invalidQuery } var request = URLRequest(url: url)

Middle+
СБЕРСБЕР
10
/206