AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-917521

Deepak Sharma's questions

Martin Hope
Deepak Sharma
Asked: 2025-04-05 23:42:57 +0800 CST

SwiftUI ScrollView scrollTargetLayout não está funcionando

  • 5

Tenho a seguinte implementação de scrubber no SwiftUI. O +botão deve mover para ScrollViewcima em 1 tick (ou scrollPositionincrementado em 1), mas o problema é que não há rolagem até que eu clique 8-9 vezes. Isso é um bug no iOS ou um erro de programação?


struct BrokenVerticalScrubberDemo: View {
    @State private var scrollPosition: Int? = 0
    @State private var count: Int = 20

    var body: some View {
        VStack {
            Text("Scroll Position: \(scrollPosition ?? 0)")
                .font(.headline)

            ScrollView(.vertical, showsIndicators: true) {
                VStack(spacing: 8) {
                    ForEach(0..<count, id: \.self) { index in
                        Text("Tick \(index)")
                            .frame(height: 30)
                            .id(index)
                    }
                }
                .scrollTargetLayout()
                .padding(.vertical, 50)
            }
            .scrollTargetBehavior(.viewAligned)
            .scrollPosition(id: $scrollPosition)
            .frame(height: 300)
            .border(Color.gray)

            Button("+1") {
                withAnimation {
                    scrollPosition = min((scrollPosition ?? 0) + 1, count - 1)
                }
            }
            .padding(.top)
        }
        .padding()
    }
}

#Preview {
    BrokenVerticalScrubberDemo()
}

Por outro lado, se eu usar ScrollViewReadercomo solução alternativa, ele começa a rolar após 2 toques no botão '+'.

import SwiftUI

struct SomeWhatWorkingVerticalScrubberDemo: View {
    @State private var scrollPosition: Int = 0
    @State private var count: Int = 20

    var body: some View {
        VStack {
            Text("Scroll Position: \(scrollPosition)")
                .font(.headline)

            ScrollView(.vertical, showsIndicators: true) {
                ScrollViewReader { scrollViewProxy in
                    VStack(spacing: 8) {
                        ForEach(0..<count, id: \.self) { index in
                            Text("Tick \(index)")
                                .frame(height: 30)
                                .id(index)
                        }
                    }
                    .padding(.vertical, 50)
                    .onChange(of: scrollPosition) { newPosition in
                        withAnimation {
                            scrollViewProxy.scrollTo(newPosition, anchor: .center)
                        }
                    }
                }
            }
            .frame(height: 300)
            .border(Color.gray)

            Button("+1") {
                scrollPosition = min(scrollPosition + 1, count - 1)
            }
            .padding(.top)
        }
        .padding()
    }
}

#Preview {
    SomeWhatWorkingVerticalScrubberDemo()
}

  • 2 respostas
  • 50 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-28 21:44:13 +0800 CST

Implementação do depurador discreto SwiftUI

  • 5

Estou tentando implementar um scrubber discreto com marcações de texto no SwiftUI da seguinte forma. Meu problema é que não consigo determinar a altura do HStackinterior do ScrollViewapriori, então tentei usar onGeometryChangeo modificador, mas não funciona (ou seja, o texto de sobreposição é truncado). Uma maneira de consertar é usando GeometryReadere atribuindo a altura de HStackcom base no proxy de geometria, mas quero saber se há outra maneira de sair sem usar GeometryReader.

struct ScrollScrubber: View {
    var config:ScrubberConfig
    
    @State var viewSize:CGSize?
    
    var body: some View {
        let horizontalPadding = (viewSize?.width ?? 0)/2
        
        ScrollView(.horizontal) {
            HStack(spacing:config.spacing) {
                let totalSteps = config.steps * config.count
                
                ForEach(0...totalSteps, id: \.self) { index in
                    let remainder = index % config.steps
                    Divider()
                        .background( remainder == 0 ? Color.primary : Color.gray)
                        .frame(width: 0, height: remainder == 0 ? 20 : 10, alignment: .center)
                        .frame(maxHeight: 20, alignment: .bottom)
                        .overlay(alignment: .bottom) {
                            if remainder == 0 {
                                Text("\(index / config.steps)")
                                    .font(.caption)
                                    .fontWeight(.semibold)
                                    .textScale(.secondary)
                                    .fixedSize()
                                    .offset(y:20)
                            }
                        }
                    
                }
            }
            .frame(height:viewSize?.height)
            
        }
        .scrollIndicators(.hidden)
        .safeAreaPadding(.horizontal, horizontalPadding)
        .onGeometryChange(for: CGSize.self) { proxy in
            proxy.size
        } action: { newValue in
            viewSize = newValue
            print("View Size \(newValue)")
        }


    }
}

struct ScrubberConfig:Equatable {
    var count:Int
    var steps:Int
    var spacing:CGFloat
}

#Preview {
    ScrollScrubber(config: .init(count: 100, steps: 5, spacing: 5.0))
        .frame(height:60)
}


swiftui
  • 1 respostas
  • 32 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-28 19:20:58 +0800 CST

Modificador SwiftUI onGeometryChange com quadro

  • 5

O que há de errado com o código a seguir, que faz com que a viewSizealtura permaneça zero apesar de ter um framemodificador definido como altura 60?


struct TestGeometryModifierView: View {
    @State var viewSize:CGSize = .zero
    
    var body: some View {
        Color.red
            .onGeometryChange(for: CGSize.self) { proxy in
                proxy.size
            } action: { newValue in
                viewSize = newValue
                print("View Size \(newValue)")
            }
            .frame(height:viewSize.height)
    }
    
}

#Preview {
    TestGeometryModifierView()
        .frame(height:60)
}

A declaração print no console mostra apenas uma linha. Espero que ela mude quando a altura do quadro for definida na visualização.

View Size (402.0, 0.0)
swiftui
  • 1 respostas
  • 37 Views
Martin Hope
Deepak Sharma
Asked: 2025-03-09 05:01:55 +0800 CST

Deslocamento da visualização SwiftUI em relação à área segura

  • 5

O que exatamente está acontecendo neste código SwiftUI, eu me pergunto. Quero alinhar a visualização azul à borda inicial da área segura no modo paisagem. O código abaixo funciona, mas se eu remover o ajuste de -0,5 pontos no cálculo blueOffsetabaixo, ele simplesmente não funciona. Ele Blue Viewsimplesmente preenche toda a área segura na borda inicial. Eu me pergunto o que a mágica -0.5faz?

  @ViewBuilder
    var secondBody:some View {
        Color.green.opacity(0.3)
            .ignoresSafeArea()
            .onGeometryChange(for: CGRect.self) { proxy in
                proxy.frame(in: .global)
            } action: { newValue in
                viewSize = newValue.size
            }
            .background {
                Color.blue
                    .ignoresSafeArea()
                    .aspectRatio(verticalSizeClass == .regular ? 9.0/16.0 : 16.0/9.0, contentMode: .fit)
                    .onGeometryChange(for: CGRect.self) { proxy in
                        proxy.frame(in: .global)
                    } action: { newValue in
                        blueViewSize = newValue.size
//This line, why it works????
                        blueOffset = 
verticalSizeClass == .regular ? 0 :
 (viewSize.width - blueViewSize.width)/2 - 0.5
                        print("Blue offset \(blueOffset)")
                    }
                    .offset(x: -blueOffset)
            }
            .persistentSystemOverlays(.hidden)
    }
  • 1 respostas
  • 37 Views
Martin Hope
Deepak Sharma
Asked: 2025-02-27 02:21:34 +0800 CST

A visualização SwiftUI está sendo reinicializada na autorrotação [duplicado]

  • 5
Esta pergunta já tem uma resposta aqui :
SwiftUI (Mac) @Observable memory leak, related to an array, triggers App lifecycle (1 resposta)
Fechado ontem .

Tenho o seguinte código SwiftUI:

struct TestContentView: View {
    @Environment(\.verticalSizeClass) var verticalSizeClass
    @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
    var body: some View {
        TestView()
            .ignoresSafeArea()
    }
}

struct TestView: View { 
    @State var model:TestModel = TestModel()
    
    var body: some View {
        Text("Count \(model.counter)")
    }
}

@Observable
class TestModel {
    var counter:Int = 0
    
    deinit {
        print("Calling deinit on TestModel")
    }
}

Meu problema é que TestViewe TestModelestão sendo reinicializados na autorrotação do dispositivo, apesar TestModelde ser uma @Statevariável. Isso não é o que eu quero e eu entendo que o problema é que declarei variáveis ​​de ambiente de classe de tamanho que estão causando TestViewa redefinição para um novo valor. Uma maneira de resolver o problema é mover testModelpara superview e inicializá-lo, mas não tenho certeza se essa é sempre uma abordagem escalável se você tiver hierarquias de visualização mais profundas. Qual é a abordagem certa para resolver esse problema, especialmente se alguém pode ter horizontalSizeClassou verticalSizeClassestar profundamente na hierarquia de visualização?

  • 1 respostas
  • 71 Views
Martin Hope
Deepak Sharma
Asked: 2025-02-26 20:44:11 +0800 CST

Problema de loop infinito SwiftUI com variáveis ​​de tamanho @Environment

  • 6

Vejo o corpo do SwiftUI sendo repetidamente chamado em um loop infinito na presença de variáveis ​​de ambiente como horizontalSizeClassou verticalSizeClass. Isso acontece depois que o dispositivo é girado do modo retrato para paisagem e depois de volta para o modo retrato. O deinitmétodo de TestPlayerVMé repetidamente chamado. O código de exemplo minimamente reproduzível é colado abaixo.

O loop infinito não é visto se eu remover referências de ambiente de classe de tamanho OU se eu pular addPlayerObserversa chamada no TestPlayerVMinicializador.

import AVKit
import Combine

struct InfiniteLoopView: View {
       @Environment(\.verticalSizeClass) var verticalSizeClass
       @Environment(\.horizontalSizeClass) var horizontalSizeClass
    
       @State private var openPlayer = false
       @State var playerURL: URL = URL(fileURLWithPath: Bundle.main.path(forResource: "Test_Video", ofType: ".mov")!)
    
        var body: some View {
           PlayerView(playerURL: playerURL)
              .ignoresSafeArea()
        }
     }

struct PlayerView: View {
    @Environment(\.dismiss) var dismiss
    
    var playerURL:URL
    @State var playerVM = TestPlayerVM()
    
    var body: some View {
        VideoPlayer(player: playerVM.player)
            .ignoresSafeArea()
            .background {
                Color.black
            }
            .task {
                let playerItem = AVPlayerItem(url: playerURL)
                playerVM.playerItem = playerItem
            }
    }
  }

@Observable
class TestPlayerVM {
     private(set) public var player: AVPlayer = AVPlayer()

     var playerItem:AVPlayerItem? {
        didSet {
            player.replaceCurrentItem(with: playerItem)
        }
    }
    
    private var cancellable = Set<AnyCancellable>()
    
    init() {
        addPlayerObservers()
    }
    
    deinit {
        print("Deinit Video player manager")
        removeAllObservers()
    }
    
    private func removeAllObservers() {
        cancellable.removeAll()
    }
    
  
    private func addPlayerObservers() {
        
        player.publisher(for: \.timeControlStatus, options: [.initial, .new])
            .receive(on: DispatchQueue.main)
            .sink { timeControlStatus in
                print("Player time control status \(timeControlStatus)")
            }
            .store(in: &cancellable)
        
    }
}

  • 1 respostas
  • 53 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-12 17:07:50 +0800 CST

Atores locais vs. globais em objetos de modelo observáveis

  • 5

Tenho a seguinte classe de modelo SwiftUI Observable junto com variáveis ​​de ator local e global que falham ao construir com o erro Global actor 'MyGlobalActor'-isolated default value in a nonisolated context. Minha pergunta é o que há de especial no ator global que a construção falha, mas a construção é bem-sucedida para o ator local? O método init no ator local é executado no contexto padrão, mas o ator global é executado em contexto isolado?

import SwiftUI
    
@Observable
final class Model {
    let testActor = TestLocalActor() //This builds 
    let testGlobalActor = TestGlobalActor() //Build fails here
}

actor TestLocalActor {
    init() {
        
    }
}

@MyGlobalActor
final class TestGlobalActor {
    init() {
        
    }
}

@globalActor
actor MyGlobalActor: GlobalActor {
   static let shared = MyGlobalActor()
}
swift
  • 1 respostas
  • 47 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 18:49:33 +0800 CST

Erros de compilação do Swift 6 ao monitorar valores publicados de um ator em uma tarefa

  • 4

O código a seguir dá erro ao compilar na versão de linguagem Swift 6 no Xcode. Isso é um problema de arquitetura ou tem uma solução fácil? O tipo Boolé Sendable, mas seu publicador não é.

Non-sendable type 'Published<Bool>.Publisher' in implicitly asynchronous access to actor-isolated property '$isRecording' cannot cross actor boundary

import Foundation

final class Recorder {
    
    var writer = Writer()
    var isRecording = false
    
    func startRecording() {
        Task { [writer] in
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task { [writer] in
            await writer.stopRecording()
            print("stopped recording")
        }
    }
    
    func observeValues() {
        
        Task {
            for await value in await writer.$isRecording.values {
                isRecording = value
            }
        }
    }
}

actor Writer {
    @Published private(set) public var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}

Consulte esta captura de tela para ver os erros reais que vejo no código de exemplo do AVCam (com a única modificação de colocar @preconcurrency) import AVFoundation.

Consulte esta captura de tela para ver os erros reais no código de exemplo do AVCam que vejo (sem modificações)

  • 1 respostas
  • 34 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 16:41:21 +0800 CST

Qual é o objetivo do protocolo `Sendable` em Swift

  • 5

Marcar uma classe ou função como Sendablegarante que é seguro passar por limites simultâneos, tipos de valor são seguros, pois implementam cópia na gravação, etc., todos nós encontramos na documentação da linguagem Swift. Mas meu ponto é que Sendablenão promete que uma variável esteja livre de corridas de dados. Podemos ter corridas de dados mesmo em tipos de valor básicos, como Intdemonstrado no código abaixo. Então Sendablenão equivale a estar seguro de dados contra acesso/modificação simultânea, significa apenas que o valor é seguro para copiar em diferentes threads. Mas minha pergunta é qual problema isso resolve ou qual é a importância de ter Sendablecomo uma construção então? Alguém pode explicar isso?

var num = 0

DispatchQueue.global(qos: .background).async {
    for _ in 0..<100 {
        num += 1 
    }
}

DispatchQueue.global(qos: .background).async {
    for _ in 0..<100 {
        num -= 1 
    }
}
  • 2 respostas
  • 59 Views
Martin Hope
Deepak Sharma
Asked: 2025-01-07 03:08:22 +0800 CST

Erro de simultaneidade do Swift 6 ao passar o encerramento de envio

  • 5

Estou recebendo esse erro em alguns lugares no meu código com o encerramento de tarefa após definir Swift 6 como versão de linguagem no XCode.

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure

Abaixo está um código de exemplo minimamente reproduzível.

import Foundation

final class Recorder {
    
    var writer = Writer()
    
    func startRecording() {
        Task {
            await writer.startRecording()
            print("started recording")
        }
    }
    
    func stopRecording() {
        Task {
            await writer.stopRecording()
            print("stopped recording")
        }
    }
}

actor Writer {
    var isRecording = false
    
    func startRecording() {
        isRecording = true
    }
    
    func stopRecording() {
        isRecording = false
    }
}
  • 1 respostas
  • 65 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-31 18:37:45 +0800 CST

Swift Actor e Executor de Fila de Despacho GCD

  • 5

Isto é com referência ao código de exemplo AVCam da Apple:

   actor CaptureService {

          // The app's capture session.
         private let captureSession = AVCaptureSession()

        // A serial dispatch queue to use for capture control actions.
         private let sessionQueue = DispatchSerialQueue(label: "com.example.apple-samplecode.AVCam.sessionQueue")

       // Sets the session queue as the actor's executor.
        nonisolated var unownedExecutor: UnownedSerialExecutor {
            sessionQueue.asUnownedSerialExecutor()
        }
     ...
  }

E mais tarde no código do Ator:

    // Set the controls delegate.
    captureSession.setControlsDelegate(controlsDelegate, queue: sessionQueue)

Se entendi corretamente, o efeito desse código é fazer com que todas as chamadas de método isoladas e modificações de estado mutável aconteçam efetivamente sessionQueuechamando implicitamente sessionQueue.sync(). Meu entendimento está correto ou há mais do que isso?

  • 1 respostas
  • 75 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-23 05:05:07 +0800 CST

Usando AsyncStream vs @Observable macro no SwiftUI

  • 3

Quero entender a utilidade de usar AsyncStreamquando o iOS 17 introduziu @Observablea macro onde podemos observar diretamente as mudanças no valor de qualquer variável no modelo (e o rastreamento de observação pode acontecer mesmo fora da visualização SwiftUI). Então, se eu estiver observando um fluxo contínuo de valores, como o progresso do download de um arquivo usando AsyncStreamuma visualização SwiftUI, o mesmo pode ser observado na mesma visualização SwiftUI usando onChange(of:initial)o progresso do download (armazenado como uma propriedade no objeto do modelo). Estou procurando benefícios, desvantagens e limitações de ambas as abordagens.

Especificamente, minha pergunta é com relação ao código de exemplo AVCam da Apple, onde eles observam alguns estados como segue. Isso é feito em CameraModelclasse que é anexada à visualização SwiftUI.

    // MARK: - Internal state observations

// Set up camera's state observations.
private func observeState() {
    Task {
        // Await new thumbnails that the media library generates when saving a file.
        for await thumbnail in mediaLibrary.thumbnails.compactMap({ $0 }) {
            self.thumbnail = thumbnail
        }
    }
    
    Task {
        // Await new capture activity values from the capture service.
        for await activity in await captureService.$captureActivity.values {
            if activity.willCapture {
                // Flash the screen to indicate capture is starting.
                flashScreen()
            } else {
                // Forward the activity to the UI.
                captureActivity = activity
            }
        }
    }
    
    Task {
        // Await updates to the capabilities that the capture service advertises.
        for await capabilities in await captureService.$captureCapabilities.values {
            isHDRVideoSupported = capabilities.isHDRSupported
            cameraState.isVideoHDRSupported = capabilities.isHDRSupported
        }
    }
    
    Task {
        // Await updates to a person's interaction with the Camera Control HUD.
        for await isShowingFullscreenControls in await captureService.$isShowingFullscreenControls.values {
            withAnimation {
                // Prefer showing a minimized UI when capture controls enter a fullscreen appearance.
                prefersMinimizedUI = isShowingFullscreenControls
            }
        }
    }
}

Se virmos a estrutura CaptureCapabilities, é uma estrutura pequena com dois membros Bool. Essas mudanças poderiam ter sido observadas diretamente por uma visualização SwiftUI. Gostaria de saber se há uma vantagem ou razão específica para usar AsyncStreamaqui e iterar continuamente sobre as mudanças em um loop for.

   /// A structure that represents the capture capabilities of `CaptureService` in
  /// its current configuration.
struct CaptureCapabilities {

let isLivePhotoCaptureSupported: Bool
let isHDRSupported: Bool

init(isLivePhotoCaptureSupported: Bool = false,
     isHDRSupported: Bool = false) {
    self.isLivePhotoCaptureSupported = isLivePhotoCaptureSupported
    self.isHDRSupported = isHDRSupported
}

  static let unknown = CaptureCapabilities()
}
  • 1 respostas
  • 115 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-12 01:27:32 +0800 CST

SwiftUI "mascara" as partes esquerda e direita de uma visualização

  • 5

Tenho um retângulo arredondado e desejo mascarar as partes esquerda e direita dele (cujas larguras podem ser definidas como Statevariáveis). O que eu quero é que o retângulo arredondado preserve seu formato de retângulo arredondado conforme aplico máscaras esquerda e direita. Digo máscara para fins de explicação, mas a implementação real pode não usar .masko modificador se criar problemas no teste de acerto para reconhecedores de gestos em toda a visualização.

Aqui está o código para mascarar as partes esquerda e direita de um retângulo arredondado.

struct MaskTesting: View {

  @State var rectWidth:CGFloat = 300
  @State var leftMaskWidth:CGFloat = 100
  @State var rightMaskWidth:CGFloat = 100

  var body: some View {
    
    Rectangle()
        .fill(Color.orange)
        .frame(maxHeight:70)
        .frame(width: rectWidth)
        .clipShape(RoundedRectangle(cornerRadius: 5))
        .overlay(alignment: .leading) {
            Rectangle()
                .fill(Color.purple)
                .frame(maxHeight:70)
                .frame(width: leftMaskWidth)
        }
        .overlay(alignment: .leading) {
            Rectangle()
                .fill(Color.purple)
                .frame(maxHeight:70)
                .frame(width: rightMaskWidth)
                .offset(x:rectWidth - 100)
        }
    
}

A saída é algo como isto. Mas eu quero que a visualização laranja principal seja um retângulo arredondado do que um retângulo simples na saída. Como eu implemento isso no SwiftUI?

insira a descrição da imagem aqui

  • 1 respostas
  • 48 Views
Martin Hope
Deepak Sharma
Asked: 2024-12-02 04:09:07 +0800 CST

Detectando evento SwiftUI drag Began

  • 5

Quero detectar onde o gesto de arrastar começou. Tenho uma subvisualização com apenas 20 pontos de largura. Adiciono um gesto de arrastar à supervisualização e quero me mover por essa subvisualização somente se o local de início do gesto de arrastar no início do gesto estiver a 20 pontos do local dessa subvisualização. Não quero adicionar o gesto de arrastar a essa subvisualização, pois isso causou outros problemas no código (relatados em outras perguntas do SO e sem solução limpa). Então, tento adicionar o gesto à supervisualização.

Tentei o seguinte código, mas ele não funciona porque não detecta quando e onde o gesto COMEÇOU.

  DragGesture(minimumDistance: 0)
                    .updating($scrubberSeeking, body: { value, state, _ in
                        
                        if abs(value.startLocation.x - scrubberOffset) > 20.0  {
                            state = false
                            return
                        }
                        
                        state = true
                    })
                    .onChanged({ value in
                        
                            if scrubberSeeking {
                                ...
                                ...
                            }
                       

                    })
                    .onEnded { value in
                        
                    }
  • 1 respostas
  • 63 Views
Martin Hope
Deepak Sharma
Asked: 2024-11-26 19:09:06 +0800 CST

Comportamento de centralização da visualização SwiftUI ao usar o novo modificador de quadro

  • 5

Tenho o seguinte código SwiftUI:

    Rectangle()
        .fill(Color.blue.opacity(0.5))
        .frame(width: 130)
        .frame(maxWidth: .infinity)
        .background(Color.orange.opacity(0.5))
        .padding()
        .frame(maxHeight:100)

Aqui está o resultado.

insira a descrição da imagem aqui

Claramente pode ser visto que o retângulo interno em azul foi colocado no centro do retângulo externo. Eu tentei experimentar com o alinhamento de frames e posso ver que o alinhamento do retângulo interno só pode ser alterado alterando o alinhamento do frame do retângulo externo como segue:

  .frame(maxWidth: .infinity, alignment: .trailing)

Mas nada muda se eu alterar a propriedade de alinhamento do quadro do retângulo interno.

Quero entender esse comportamento mais claramente: se a visualização é centralizada por padrão e por que a modificação do alinhamento do quadro interno não altera nada.

  • 2 respostas
  • 35 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-29 04:40:11 +0800 CST

Alinhar imagens no HStack

  • 5

Tenho o seguinte código no SwiftUI:

  HStack(spacing: 0) {
        ForEach(images) { thumbImage in
            Image(uiImage: thumbImage.image)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 50, height: 50)
                .clipped()
        }
    }
    .frame(width: 330, alignment: .center)
    .clipped()

Vejo a seguinte saída:

insira a descrição da imagem aqui

Efetivamente, ele está recortando conteúdo tanto à esquerda quanto à direita do HStack. O que eu quero é que o recorte aconteça apenas no lado direito (à direita), não no lado esquerdo. Qual é a maneira correta de fazer isso?

  • 1 respostas
  • 35 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-21 04:12:44 +0800 CST

O SwiftUI mantém o fundo parado enquanto a visualização é arrastada

  • 4

Implementei uma linha do tempo de edição de vídeo de exemplo usando SwiftUI e estou enfrentando problemas. Então, estou dividindo o problema em partes e postando cada problema como uma pergunta separada. No código abaixo, tenho uma linha do tempo simples usando um HStackespaçador esquerdo, espaçador direito (representado como cor preta simples) e uma IU de aparador no meio. O aparador é redimensionado conforme as alças esquerda e direita são arrastadas. Os espaçadores esquerdo e direito também se ajustam em largura conforme as alças do aparador são arrastadas.

Problema : Quero manter as miniaturas de fundo (implementadas atualmente como retângulos simples preenchidos em cores diferentes) no aparador estacionárias enquanto o aparador é redimensionado. Atualmente, elas se movem conforme o aparador é redimensionado, como visto no gif abaixo. Como faço para consertar isso?

insira a descrição da imagem aqui

import SwiftUI

struct SampleTimeline: View {
    
    let viewWidth:CGFloat = 340 //Width of HStack container for Timeline
   
    @State var frameWidth:CGFloat = 280 //Width of trimmer
    
    var minWidth: CGFloat {
        2*chevronWidth + 10
    } //min Width of trimmer
    
    @State private var leftViewWidth:CGFloat = 20
    @State private var rightViewWidth:CGFloat = 20
    
    var chevronWidth:CGFloat {
        return 24
    }
    
    var body: some View {
        
        HStack(spacing:0) {
            Color.black
                .frame(width: leftViewWidth)
                .frame(height: 70)
            
            HStack(spacing: 0) {
            
                Image(systemName: "chevron.compact.left")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged({ value in
                                leftViewWidth = max(leftViewWidth + value.translation.width, 0)
                                
                                if leftViewWidth > viewWidth - minWidth - rightViewWidth {
                                    leftViewWidth = viewWidth - minWidth - rightViewWidth
                                }
                                   
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                                
                            })
                            .onEnded { value in
                               
                            }
                    )
        
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged({ value in
                                rightViewWidth = max(rightViewWidth - value.translation.width, 0)
                                
                                if rightViewWidth > viewWidth - minWidth - leftViewWidth {
                                    rightViewWidth = viewWidth - minWidth - leftViewWidth
                                }
                                
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                            })
                            .onEnded { value in
                              
                            }
                    )
                 
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
          
            .background {
                
                HStack(spacing:0) {
                    Rectangle().fill(Color.red)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.cyan)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.orange)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.brown)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.purple)
                        .frame(width: 70, height: 60)
                }
                
            }
            .frame(width: frameWidth)
            .clipped()
            
            Color.black
                .frame(width: rightViewWidth)
                .frame(height: 70)
        }
        .frame(width: viewWidth, alignment: .leading)
    }
}

#Preview {
    SampleTimeline()
}

Atualização : consegui resolver o problema da seguinte forma, mas ainda sinto que é meio que uma solução alternativa (pois configurei um deslocamento para a visualização de miniaturas). Por favor, poste uma solução melhor e mais precisa se você acha que há alguma (como usar uma máscara que também reduz a largura do quadro do aparador ao mesmo tempo).


import SwiftUI

struct SampleTimeline: View {
    
    let viewWidth:CGFloat = 340 //Width of HStack container for Timeline
   
    @State var frameWidth:CGFloat = 280 //Width of trimmer
    
    var minWidth: CGFloat {
        2*chevronWidth + 10
    } //min Width of trimmer
    
    @State private var leftViewWidth:CGFloat = 20
    @State private var rightViewWidth:CGFloat = 20
    @GestureState private var leftEndPanned = false
    @GestureState private var rightEndPanned = false
    
    var chevronWidth:CGFloat {
        return 24
    }
    
    var body: some View {
        
        HStack(spacing:0) {
            Color.clear
                .frame(width: leftViewWidth)
                .frame(height: 70)
            
            HStack(spacing: 0) {
            
                Image(systemName: "chevron.compact.left")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($leftEndPanned, body: { _, state, _ in
                                state = true
                            })
                            .onChanged({ value in
                                leftViewWidth = max(leftViewWidth + value.translation.width, 0)
                                
                                if leftViewWidth > viewWidth - minWidth - rightViewWidth {
                                    leftViewWidth = viewWidth - minWidth - rightViewWidth
                                }
                                   
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                                
                            })
                            .onEnded { value in
                               
                            }
                    )
        
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                    .frame(width: chevronWidth, height: 70)
                    .background(Color.blue)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($rightEndPanned, body: { _, state, _ in
                                state = true
                            })
                            .onChanged({ value in
                                rightViewWidth = max(rightViewWidth - value.translation.width, 0)
                                
                                if rightViewWidth > viewWidth - minWidth - leftViewWidth {
                                    rightViewWidth = viewWidth - minWidth - leftViewWidth
                                }
                                
                                frameWidth = max(viewWidth - leftViewWidth - rightViewWidth, minWidth)
                            })
                            .onEnded { value in
                              
                            }
                    )
                 
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
            .background {
                
                HStack(spacing:0) {
                    Rectangle().fill(Color.red)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.cyan)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.orange)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.brown)
                        .frame(width: 70, height: 60)
                    Rectangle().fill(Color.purple)
                        .frame(width: 70, height: 60)
                }
                .frame(width: viewWidth - leftViewWidth - rightViewWidth, alignment: .leading)
                .offset(x: -leftViewWidth)
                .background(Color.yellow)
                .clipped()
                
            }
            
            
            Color.clear
                .frame(width: rightViewWidth)
                .frame(height: 70)
        }
        .frame(width: viewWidth, alignment: .leading)
    }
}

#Preview {
    SampleTimeline()
}

  • 1 respostas
  • 62 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-16 03:36:57 +0800 CST

SwiftUI reduz a visualização ao arrastar bordas

  • 5

Estou tentando implementar uma interface de usuário de corte de vídeo no SwiftUI da seguinte maneira:

 struct SimpleTrimmer: View {
    @State private var startPosition: CGFloat = 0
    @GestureState private var isDragging: Bool = false
    
    @State private var lastStartPosition: CGFloat = .zero
    @State private var frameWidth:CGFloat = 300
    
    var body: some View {
        HStack(spacing: 10) {
                Image(systemName: "chevron.compact.left")
                    .frame(height:70)
                    .frame(width:20)
                    .padding(.horizontal, 5)
                    .background(Color.blue)
                    .offset(x: startPosition)
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .updating($isDragging, body: { value, out, transaction in
                                out = true
                                
                            })
                            .onChanged { value in
                                let translation = value.translation.width
                                startPosition = translation + lastStartPosition
                            }.onEnded { _ in
                                lastStartPosition = startPosition
                                NSLog("Last start position \(lastStartPosition)")
                            }
                    )
            
                
                Spacer()
                
                Image(systemName: "chevron.compact.right")
                .frame(height:70)
                .frame(width:20)
                .padding(.horizontal, 5)
                .background(Color.blue)
            }
            .foregroundColor(.black)
            .font(.title3.weight(.semibold))
            .padding(.horizontal, 7)
            .padding(.vertical, 3)
            .background(.yellow)
            .clipShape(RoundedRectangle(cornerRadius: 7))
            .frame(width: frameWidth)
          //  .offset(x: startPosition)
            .onGeometryChange(for: CGFloat.self) { proxy in
                proxy.size.width
            } action: { width in
                print("width = \(width)")
            }
    }
}

insira a descrição da imagem aqui

Isso funciona para mover a mão esquerda do trimmer quando arrastado. O que eu preciso também é encolher a SimpleTrimmervisualização conforme as extremidades são arrastadas. Simplesmente não funciona, não importa o que eu faça (como ajustar o deslocamento e a largura do HStack principal, etc.).

  • 1 respostas
  • 26 Views
Martin Hope
Deepak Sharma
Asked: 2024-09-14 18:27:36 +0800 CST

Preenchendo apenas uma parte do SwiftUI com cor de fundo

  • 7

Estou tentando projetar uma visualização de aparador de vídeo no SwiftUI da seguinte forma. O resultado é este. Minha pergunta é se posso ter a parte do meio (ou seja, tudo, exceto 20 pontos à esquerda e à direita e 5 pontos para cima e para baixo) transparente para que eu possa mostrar miniaturas atrás delas (talvez tendo um formato de clipe personalizado)?

insira a descrição da imagem aqui

  var body: some View {
    HStack(spacing: 10) {
        Image(systemName: "chevron.compact.left")
            .frame(height:70)
        
        Spacer()
        
        Image(systemName: "chevron.compact.right")
    }
    .foregroundColor(.black)
    .font(.title3.weight(.semibold))
    .padding(.horizontal, 7)
    .padding(.vertical, 3)
    .background(.yellow)
    .clipShape(RoundedRectangle(cornerRadius: 7))
    .frame(width: 300)
    .onGeometryChange(for: CGFloat.self) { proxy in
        proxy.size.width
    } action: { width in
        print("width = \(width)")
    }

}
  • 2 respostas
  • 82 Views
Martin Hope
Deepak Sharma
Asked: 2024-01-22 21:37:29 +0800 CST

Problema de rotação automática do SwiftUI Video Player

  • 5

Estou incorporando o SwiftUI VideoPlayerem um VStacke vejo que a tela fica preta (ou seja, o conteúdo desaparece mesmo que o player de vídeo seja girado automaticamente) quando o dispositivo é girado. O problema acontece mesmo quando eu uso AVPlayerViewController(as UIViewControllerRepresentable). Isso é um bug ou estou fazendo algo errado?

var videoURL:URL
let player = AVPlayer()

var body: some View {
    VStack {
        VideoPlayer(player: player)
                        .frame(maxWidth:.infinity)
                        .frame(height:300)
                        .padding()
                        .ignoresSafeArea()
                        .background {
                            Color.black
                        }
                        .onTapGesture {
                            player.rate = player.rate == 0.0 ? 1.0 : 0.0
                        } 
       
        Spacer()
    }
    .ignoresSafeArea()
    .background(content: {
        Color.black
    })
    .onAppear {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: AVAudioSession.CategoryOptions.duckOthers)
        } catch {
            NSLog("Unable to set session category to playback")
        }
        
        let playerItem = AVPlayerItem(url: videoURL)
        player.replaceCurrentItem(with: playerItem)
    }

 }
  • 1 respostas
  • 22 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve