Swift UI: Building a custom image Guess Who game, struggling to access selected images for my Game view

149 Views Asked by At

I'm working on my final large portfolio project and I am attempting to create a Guess Who style game in Swift UI that allows you to upload your own images to create custom character cards. I have built an image picker that gives the app access to the users photo album but I'm unsure how to get my selected images to display on my Game view. Additionally, I need to make sure what ever order the images are selected in stays consistent. Currently I have an array of 24 rectangles on my Game view for reference. Everything except ImagePickerView and Game are part of the same file, PickerTool.

Any help and advice is greatly appreciated. Thanks in advance!

''' struct PickerTool : View {

@State var selected : [SelectedImages] = []
@State var show = false

var body: some View{
    
    ZStack{
        
        VStack{
            
            
            if !self.selected.isEmpty{
                
                ScrollView(.horizontal, showsIndicators: false) {
                    
                    HStack(spacing: 20){
                        
                        ForEach(self.selected,id: \.self){i in
                            
                            Image(uiImage: i.image)
                            .resizable()
                            .frame(width: UIScreen.main.bounds.width - 40, height: 250)
                            .cornerRadius(15)
                        }
                    }
                    .padding(.horizontal, 20)
                }
            }
            
            Button(action: {
                
                self.selected.removeAll()

                self.show.toggle()
                
            }) {
                
                Text("Open Photo Library \(Image(systemName: "camera.shutter.button.fill"))")
                        .font(.headline)
                        .frame(width: 200, height: 50)
                        .background(Color.blue)
                        
                        .foregroundColor(.white)
            }
            .background(Color.blue)
            .clipShape(Rectangle())
            .cornerRadius(5)
            .padding(.top, 25)
        }
        
        if self.show{
            
            CustomPicker(selected: self.$selected, show: self.$show)

        }
    }
}

}

struct CustomPicker : View {

@Binding var selected : [SelectedImages]
@State var grid : [[Images]] = []
@Binding var show : Bool
@State var disabled = false

var body: some View{
    
    GeometryReader{_ in
        
        VStack{
            

            if !self.grid.isEmpty{
                
                HStack{
                    
                    Text("Pick 24 Images of People")
                        .fontWeight(.bold)
                    
                    Spacer()
                }
                .padding(.leading)
                .padding(.top)
                
                ScrollView(.vertical, showsIndicators: false) {
                    
                    VStack(spacing: 20){
                        
                        ForEach(self.grid,id: \.self){i in
                            
                            HStack{
                                
                                ForEach(i,id: \.self){j in
                                    
                                    Card(data: j, selected: self.$selected)
                                }
                            }
                        }
                    }
                    .padding(.bottom)
                }
                
                Button(action: {
                    
                    self.show.toggle()
                    
                }) {
                    
                    Text("Select")
                        .foregroundColor(.white)
                        .padding(.vertical,10)
                        .frame(width: UIScreen.main.bounds.width / 2)
                }
                .background(Color.blue.opacity((self.selected.count != 0) ? 1 : 0.5))
                .clipShape(Rectangle())
                .cornerRadius(5)
                .padding(.bottom)
                .disabled((self.selected.count != 0) ? false : true)
                
            }
            else{
                
                if self.disabled{
                    
                    Text("Unable to load images: Please enable storage access in Settings")
                }
                if self.grid.count == 0{
                    
                    Indicator()
                }
            }
        }
        .frame(width: UIScreen.main.bounds.width - 40, height: UIScreen.main.bounds.height / 1.5)
        .background(Color.white)
        .cornerRadius(12)
    }
    .background(Color.black.opacity(0.01).edgesIgnoringSafeArea(.all)
    .onTapGesture {
    
        self.show.toggle()
        
    })
    .onAppear {
        
        PHPhotoLibrary.requestAuthorization { (status) in
            
            if status == .authorized{
                
                self.getAllImages()
                self.disabled = false
            }
            else{
                
                print("not authorized")
                self.disabled = true
            }
        }
    }
}

func getAllImages(){
    
    let opt = PHFetchOptions()
    opt.includeHiddenAssets = false
    
    let req = PHAsset.fetchAssets(with: .image, options: .none)
    
    DispatchQueue.global(qos: .background).async {

       let options = PHImageRequestOptions()
       options.isSynchronous = true
            
    // New Method For Generating Grid Without Refreshing....
        
      for i in stride(from: 0, to: req.count, by: 3){
                
            var iteration : [Images] = []
                
            for j in i..<i+3{
                
                if j < req.count{
                    
                    PHCachingImageManager.default().requestImage(for: req[j], targetSize: CGSize(width: 150, height: 150), contentMode: .default, options: options) { (image, _) in
                        
                        let data1 = Images(image: image!, selected: false, asset: req[j])
                        
                        iteration.append(data1)

                    }
                }
            }
                
            self.grid.append(iteration)
        }
        
    }
}

}

struct Card : View {

@State var data : Images
@Binding var selected : [SelectedImages]

var body: some View{
    
    ZStack{
        
        Image(uiImage: self.data.image)
        .resizable()
        
        if self.data.selected{
            
            ZStack{
                
                Color.black.opacity(0.5)
                
                Image(systemName: "checkmark")
                    .resizable()
                    .frame(width: 30, height: 30)
                    .foregroundColor(.white)
            }
        }
        
    }
    .frame(width: (UIScreen.main.bounds.width - 80) / 3, height: 90)
    .onTapGesture {
        
        
        if !self.data.selected{

            
            self.data.selected = true
            
            // Extracting Orginal Size of Image from Asset
            
            DispatchQueue.global(qos: .background).async {
                
                let options = PHImageRequestOptions()
                options.isSynchronous = true
                
                // You can give your own Image size by replacing .init() to CGSize....
                
                PHCachingImageManager.default().requestImage(for: self.data.asset, targetSize: .init(), contentMode: .default, options: options) { (image, _) in

                    self.selected.append(SelectedImages(asset: self.data.asset, image: image!))
                }
            }

        }
        else{
            
            for i in 0..<self.selected.count{
                
                if self.selected[i].asset == self.data.asset{
                    
                    self.selected.remove(at: i)
                    self.data.selected = false
                    return
                }
                
            }
        }
    }
    
}

}

struct Indicator : UIViewRepresentable {

func makeUIView(context: Context) -> UIActivityIndicatorView  {
    
    let view = UIActivityIndicatorView(style: .large)
    view.startAnimating()
    return view
}

func updateUIView(_ uiView:  UIActivityIndicatorView, context: Context) {
    
    
}

}

struct Images: Hashable {

var image : UIImage
var selected : Bool
var asset : PHAsset

}

struct SelectedImages: Hashable{

var asset : PHAsset
var image : UIImage

} '''

''' struct ImagePickerView: View {

@State private var showingSheet = false
@Environment(\.dismiss) var dismiss

var body: some View {
    NavigationView {
        VStack {
            HStack {
                Image(systemName: "exclamationmark.bubble.fill")
                    .resizable()
                    .frame(width: 30, height: 30)
                    .aspectRatio(contentMode: .fill)
                    .foregroundColor(.red)
                    .padding(.horizontal, 20)
                Text("Choose 24 images of people you and your friend both know!")
                Spacer()
            }
            HStack(alignment: .center, spacing: 10, content: {
                Spacer()
                PickerTool()
                Spacer()
            })
            
            Spacer()
            
            Button("Next") {
                showingSheet.toggle()
            }
            .font(.headline)
            .padding()
            .foregroundColor(.white)
            .frame(width: 200)
            .background(Color.blue)
            .cornerRadius(5)
            .sheet(isPresented: $showingSheet) {
                CreateChallenge()
            }
        }
        .background(Color.yellow)
        .navigationBarBackButtonHidden(false)
        .navigationTitle("Step One:")
        
        .toolbar {
            ToolbarItemGroup(placement: .navigationBarTrailing) {
                Button {
                    dismiss()
                } label: {
                    Image(systemName: "xmark.circle.fill")
                        .foregroundColor(.blue)
                        .padding()
                }
            }
        }
    }
}

} '''

''' struct Game: View {

@State var pickTool = PickerTool.self
@State var customPick = CustomPicker.self
@State var card = Card.self

private var equalLayout = [GridItem(.adaptive(minimum: 50))]

var body: some View {

        VStack {
            Rectangle()
                .overlay {
                    Text("Put image of opponent here with red frame card holder, view of looking at them from across a table.")
                        .foregroundColor(.red)
                        .multilineTextAlignment(.center)
                        .padding()
                }
                .foregroundColor(.white)
            
            LazyVGrid(columns: equalLayout, spacing: 2) {
                ForEach((1...24), id: \.self) {
                    Text("\($0)")
                        .font(.title)
                        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 100)
                        .background(Color.white)
                        .foregroundColor(.red)
                }
                .padding(2)
                
            }
            .background(Color.blue)
            Rectangle()
                .ignoresSafeArea()
                .frame(width: .infinity, height: 60)
                .foregroundColor(.blue)
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarBackButtonHidden(true)
        .background(Color.yellow)
}

} '''

0

There are 0 best solutions below