2

I'm trying to get an HStack of stars for rating (1-5) to appear in a view that I've created, but I'm getting this warning Result of 'HStack<Content>' initializer is unused and the stars aren't appearing on the view.

AddMeal View Code:

import SwiftUI

class AddMeal: UIViewController {
    @State var stars = -1

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .red
        
        // Add Meal Title Label
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
        label.center = self.view.center
        label.center.x = self.view.center.x
        label.center.y = 75
        label.font = label.font.withSize(30);
        label.textAlignment = .center
        label.textColor = .white
        label.text = "Add Meal"
        self.view.addSubview(label)
        
        // Meal Title Label
        let food = UILabel(frame: CGRect(x: 22, y: 100, width: 200, height: 50))
        food.font = label.font.withSize(20);
        food.textColor = .white
        food.text = "Meal Title"
        self.view.addSubview(food)
        
        // Food Title Input Text Field
        let sampleTextField =  UITextField(frame: CGRect(x: 20, y: 150, width: 335, height: 40))
        sampleTextField.placeholder = "Enter the Name of the Food or Drink..."
        sampleTextField.font = UIFont.systemFont(ofSize: 15)
        sampleTextField.borderStyle = UITextField.BorderStyle.roundedRect
        sampleTextField.autocorrectionType = UITextAutocorrectionType.no
        sampleTextField.keyboardType = UIKeyboardType.default
        sampleTextField.returnKeyType = UIReturnKeyType.done
        sampleTextField.clearButtonMode = UITextField.ViewMode.whileEditing
        sampleTextField.contentVerticalAlignment = UIControl.ContentVerticalAlignment.center
        self.view.addSubview(sampleTextField)
        
        // Meal Calories Label
        let mealCalories = UILabel(frame: CGRect(x: 22, y: 200, width: 200, height: 50))
        mealCalories.font = label.font.withSize(20);
        mealCalories.textColor = .white
        mealCalories.text = "Meal Calories"
        self.view.addSubview(mealCalories)
        
        // Calories Input Text Field
        let sampleTextField2 =  UITextField(frame: CGRect(x: 20, y: 250, width: 335, height: 40))
        sampleTextField2.placeholder = "Enter the # of Calories..."
        sampleTextField2.font = UIFont.systemFont(ofSize: 15)
        sampleTextField2.borderStyle = UITextField.BorderStyle.roundedRect
        sampleTextField2.autocorrectionType = UITextAutocorrectionType.no
        sampleTextField2.keyboardType = UIKeyboardType.default
        sampleTextField2.returnKeyType = UIReturnKeyType.done
        sampleTextField2.clearButtonMode = UITextField.ViewMode.whileEditing
        sampleTextField2.contentVerticalAlignment = UIControl.ContentVerticalAlignment.center
        self.view.addSubview(sampleTextField2)
        
        // Meal Rating Label
        let mealRating = UILabel(frame: CGRect(x: 22, y: 300, width: 200, height: 50))
        mealRating.font = label.font.withSize(20);
        mealRating.textColor = .white
        mealRating.text = "Meal Rating"
        self.view.addSubview(mealRating)
        
        // Rating Stars
        HStack {
            ForEach(0..<5){ i in
                
                Image(systemName: "star.fill").resizable().frame(width: 30, height:30).foregroundColor(self.stars >= i ? .yellow : .gray).onTapGesture {
                    self.stars = i
                }
            }
        }
    }
    
}

Current Output Image:

Output

Does anyone know how I can address this warning and get my HStack of stars to appear on the screen properly?

pawello2222
  • 46,897
  • 22
  • 145
  • 209
ERACED
  • 19
  • 4
  • 1
    You can use SwiftUI code in SwiftUI structs only. You can't use them in UIViewController. See https://developer.apple.com/tutorials/swiftui/ – pawello2222 Dec 24 '20 at 21:44

2 Answers2

1

We can separate SwiftUI code into standalone view and then integrate it into view controller using UIHostingController.

Here is a demo of possible solution. Tested with Xcode 12.1 / iOS 14.1 (of course you can tune layout as you need)

demo

class AddMeal: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .red
        
        // Add Meal Title Label
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
        label.center = self.view.center
        label.center.x = self.view.center.x
        label.center.y = 75
        label.font = label.font.withSize(30);
        label.textAlignment = .center
        label.textColor = .white
        label.text = "Add Meal"
        self.view.addSubview(label)
        
        // Meal Title Label
        let food = UILabel(frame: CGRect(x: 22, y: 100, width: 200, height: 50))
        food.font = label.font.withSize(20);
        food.textColor = .white
        food.text = "Meal Title"
        self.view.addSubview(food)
        
        // Food Title Input Text Field
        let sampleTextField =  UITextField(frame: CGRect(x: 20, y: 150, width: 335, height: 40))
        sampleTextField.placeholder = "Enter the Name of the Food or Drink..."
        sampleTextField.font = UIFont.systemFont(ofSize: 15)
        sampleTextField.borderStyle = UITextField.BorderStyle.roundedRect
        sampleTextField.autocorrectionType = UITextAutocorrectionType.no
        sampleTextField.keyboardType = UIKeyboardType.default
        sampleTextField.returnKeyType = UIReturnKeyType.done
        sampleTextField.clearButtonMode = UITextField.ViewMode.whileEditing
        sampleTextField.contentVerticalAlignment = UIControl.ContentVerticalAlignment.center
        self.view.addSubview(sampleTextField)
        
        // Meal Calories Label
        let mealCalories = UILabel(frame: CGRect(x: 22, y: 200, width: 200, height: 50))
        mealCalories.font = label.font.withSize(20);
        mealCalories.textColor = .white
        mealCalories.text = "Meal Calories"
        self.view.addSubview(mealCalories)
        
        // Calories Input Text Field
        let sampleTextField2 =  UITextField(frame: CGRect(x: 20, y: 250, width: 335, height: 40))
        sampleTextField2.placeholder = "Enter the # of Calories..."
        sampleTextField2.font = UIFont.systemFont(ofSize: 15)
        sampleTextField2.borderStyle = UITextField.BorderStyle.roundedRect
        sampleTextField2.autocorrectionType = UITextAutocorrectionType.no
        sampleTextField2.keyboardType = UIKeyboardType.default
        sampleTextField2.returnKeyType = UIReturnKeyType.done
        sampleTextField2.clearButtonMode = UITextField.ViewMode.whileEditing
        sampleTextField2.contentVerticalAlignment = UIControl.ContentVerticalAlignment.center
        self.view.addSubview(sampleTextField2)
        
        // Meal Rating Label
        let mealRating = UILabel(frame: CGRect(x: 22, y: 300, width: 200, height: 50))
        mealRating.font = label.font.withSize(20);
        mealRating.textColor = .white
        mealRating.text = "Meal Rating"
        self.view.addSubview(mealRating)
        
        // Rating Stars
        let stars = UIHostingController(rootView: StarsView())
        self.view.addSubview(stars.view)
        self.addChild(stars)
        stars.view.backgroundColor = .clear

        stars.view.translatesAutoresizingMaskIntoConstraints = false
        stars.view.sizeToFit()
        stars.view.topAnchor.constraint(equalTo: mealRating.bottomAnchor, constant: 25).isActive = true
        stars.view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
    }
}

struct StarsView: View {
    @State var stars = -1
    var body: some View {
        HStack {
            ForEach(0..<5){ i in
                Image(systemName: "star.fill")
                    .resizable().frame(width: 30, height:30)
                    .foregroundColor(self.stars >= i ? .yellow : .gray)
                    .onTapGesture {
                        self.stars = i
                    }
            }
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
0

You have to use UIStackView instead of HStack(SwiftUI) in UIKit Pattern.

UIStackView has axis that indicate horizontal or vertical.

stackView.axis = .Horizontal

Please reference this url. https://developer.apple.com/documentation/uikit/uistackview

Harry Jin
  • 54
  • 7