I have 3 views in a "Page" stack view with proportional heights ("Title" 0.07, "Contents" 0.88, and "Controls" 0.05). Page is constrained to the safe area and everything works fine until I add another stack view within the Contents view. I get conflicts on all three of the height constraints previously mentioned, and four automatic constraints come up in conflicts. I am guessing the problem comes from the lower two views in the stack, because they get an automatic constraint with a +1 at the end. But that means they are adding a pixel to my views whose heights are proportional to the Page stack view.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am creating horses in a horse simulator by appending an array with:
Horses.append(Horse(
//Genotype (two letters)
ext: ["E", "e"][Int.random(in:0...1)]+["E", "e"][Int.random(in:0...1)],
			//Phenotype (an image)
basePhenotype: [bayArray.randomElement()],
But the basePhenotype property is set to be a UIImage. Even though bayArray is only images, it won't accept this array as an input. How can I write it differently?
I have a Navigation bar with a title and a button on the right. Is it possible to add a vertical stack of two labels on the left? I can't seem to drag any labels there in storyboard
I have an array of horses that I am appending with the following code with a UIButton:
myHorses.append(Horse(
name: "New Horse",
gender: ["Mare", "Stallion"][Int.random(in:0...1)],
age: Int.random(in:1...19)
)
This is the array I am adding to:
var myHorses = [
Horse(name: "Donnerhall", gender: "Stallion", age: 5
]
I can add a random horse to the array, but if I click it again it adds the same horse again. I want it to be so that every time I click it, a new, different horse appears in the array. If I restart the app, though, I get a new horse when I click the button the first time (but the same if I click it again)
I am following a tutorial to create reusable headers in my app, but I get the following error: "Thread 1: EXCBADACCESS (code=2, address=0x7ffeeb1eaff8)". I have tried everything but can't seem to get it working in my app. The example project works fine on its own but my app underlines "instantiate" as the problem
The swift file for the header:
import UIKit
class HeaderView: UIView {
@IBOutlet weak var containerView: UIView!
@IBOutlet weak var headerText: UILabel!
let nibName = "HeaderView"
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
func commonInit() {
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
self.addSubview(view)
}
func loadViewFromNib() -> UIView? {
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
}
View controller:
import UIKit
class StableViewController: UIViewController {
@IBOutlet weak var header: HeaderView!
@IBOutlet weak var viewButtons: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
I have a view controller that was originally a single view, but as my app has expanded, it has turned into a tabbed view. I have an array that stores information about horses that gets imported to the TabbedHorseViewer when a button with the horse's name is clicked. The app works fine when it is just one VC, but now it is 5 different VCs connected the code doesn't really know how to handle it.
in the model:
var myHorses = [
Horse(name: "Donnerhall", idNumber: 1, gender: "Stallion")
My Horses: This is the VC with a list of horses in the form of buttons
for horse in myHorses {
let button = UIButton()
button.addTarget(self, action: #selector(self.lookupHorse(sender:)), for: .touchUpInside)
button.setTitleColor(.white, for: UIControl.State.normal)
button.setTitle(horse.name, for: UIControl.State.normal)
button.backgroundColor = colorLiteral(red: 0.005273803137, green: 0.4785152674, blue: 0.3960535526, alpha: 1)
buttonsStack.addArrangedSubview(button)
}
buttonsStack.translatesAutoresizingMaskIntoConstraints = false
}
private var horseSelected: Horse?
@objc func lookupHorse(sender: UIButton){
let horseName = sender.title(for: .normal)
if let theHorse = myHorses.first(where: {$0.name == horseName}) {
horseSelected = theHorse
self.performSegue(withIdentifier: "horseViewerSegue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "horseViewerSegue":
let horseVC = segue.destination as! HorseViewController
horseVC.horsePassed = horseSelected
default:
print("Unknown segue: \(segue.identifier ?? "nil")")
}
}
HorseViewController - This is the VC where some of the horse data is shown (there are 4 other VCs controlled by this tabbed view with more info)
import UIKit
class HorseViewController: UIViewController {
@IBOutlet weak var horseNameOutlet: UILabel!
@IBOutlet weak var horseGenderOutlet: UILabel!
var horsePassed: Horse?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
if let theHorse = horsePassed {
horseNameOutlet.text = theHorse.name
horseGenderOutlet.text = theHorse.gender
}
}
}
When I run the app and try to click on a horse on the list, I get a "Thread 1: signal SIGABRT" error on line 32. The horseViewerSegue is pointing to the tab view controller. The app doesn't crash when I point the segue to the item within the tabbed view controller (the original setup that the code was written for) but in that case the tab bar at the bottom disappears. I want to be able to navigate to the VC and use the tabs, and I want all five tabs to collect different data about the same horse that was clicked in the first VC, fetching data from the array.
Thanks in advance!
Currently, I use the horse name to lookup data in the myHorses array. However, the app won't if the user uses the same name for multiple horses. Is it possible to use the array index instead? I want the app to create a stack of buttons equal to the number of horses created, then set the title for button one as the name of the horse at index [0], then the next button with the name of the horse at index [1] etc for all horses. Then when the user presses a button, the app uses the index instead of the name to lookup data for that horse. Not sure how to do this in practice
Thanks in advance for any tips :)
model
var myHorses = [
Horse(name: "Donnerhall", idNumber: 1",
	Horse(name: "Mischa", idNumber: 2"
]
func countHorses() -> Int {
myHorses.count
}
	var horseNumber = countHorses()
var currentHorse = myHorses[0]
view controller 1
import UIKit
class HerdViewController: UIViewController {
//Buttons stack
for horse in myHorses {
let button = UIButton()
button.addTarget(self, action: #selector(self.lookupHorse(sender:)), for: .touchUpInside)
button.setTitle(horse.name, for: UIControl.State.normal)
buttonsStack.addArrangedSubview(button)
}
buttonsStack.translatesAutoresizingMaskIntoConstraints = false
}
//change currentHorse var and segue to horse viewer
@objc func lookupHorse(sender: UIButton){
currentHorse = myHorses[1] //I put in the index for horse 2, but I want the app to figure this out based on the button pressed
let horseName = sender.title(for: .normal)
if let theHorse = myHorses.first(where: {$0.name == horseName})
}
performSegue(withIdentifier: "horseViewerSegue", sender: self)
}
}
VC 2
class HorseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
horseNameOutlet.text = currentHorse.name
		 horseIdOutlet.text = currentHorse.idNumber
}
I have a swipe gesture to scroll through horses in an array, but the updateHorse() function doesn't work unless I close the VC and load it again. I have looked at countless tutorials and demos but I can't seem to get the VC to refresh, even though the horseIndex is updating correctly. I would like it to update after the swipe gesture is used, maybe even with the sideways animation (even though it is the same VC, just changing the data displayed)
model
var currentHorse = myHorses[horseIndex]
var horseIndex = 0
var horseNumber = countHorses()
func countHorses() -> Int {
myHorses.count
}
var myHorses = [
Horse(name: "Donnerhall", idNumber: 1, gender: "Stallion"),
Horse(name: "Mischa", idNumber: 2, gender: "Mare"),
Horse(name: "Selena", idNumber: 3, gender: "Mare"),
Horse(name: "Celeste", idNumber: 4, gender: "Mare")
]
@IBAction func swipeRight(_ sender: Any) {
if horseIndex < horseNumber {
horseIndex -= 1
print("previous horse")
}
if horseIndex == horseNumber {
horseIndex -= 1
print("previous horse")
}
if horseIndex == -1 {
horseIndex = horseNumber
print("ran out of horses")
}
updateHorse()
}
update function
func updateHorse(){
horseNameOutlet.text = currentHorse.name
horseGenderOutlet.text = currentHorse.gender
I want to add an item to an array, where one element depends on the result of another. Not sure if this can even work, but I haven't been able to test it since I'm not sure how to formulate an If statement to appending an array. Any help appreciated :)
appending the array
myHorses.append(Horse(
//genotype
gre: ["G", "g"][Int.random(in:0...1)]+["G", "g"][Int.random(in:0...1)],
//phenotype
greyPhenotype : UIImage //this is where I would add the if statement
))
the if statement
if gre == "Gg" {
greyPhenotype : greyArray.randomElement()
}
if gre == "GG" {
greyPhenotype : greyArray.randomElement()
}
if gre == "gg" {
greyPhenotype : blankImage
}
I have an array:
var myHorses = [
Horse(name: "Donnerhall", idNumber: 1, gender: "Stallion"),
Horse(name: "Mischa", idNumber: 2, gender: "Mare")]
I want to make a picker view with only the names from the array showing. I have previously used button.tag in another VC to find the horseIndex. Is there a way to list only the names in the picker view?
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return myHorses[row]
//pasted from another VC, maybe something like this can work here
var horseName = for horseIndex in myHorses.indices {
let horse = myHorses[horseIndex]
button.tag = horseIndex
}
Thanks in advance!
Hi! I am working on a pickerView with two components. I have an array (myHorses) with one stallion and two mares. If I run the app I get an "out of range" error at line 33. If I add another stallion to the array this goes away. Also, the image outlets are showing the images for the stallion on both outlets. How can I make the app work when there is just one member of a gender, and also show the correct images?
class BreedingViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
let myStallions = myHorses.filter({ $0.gender == "Stallion" })
let myMares = myHorses.filter({ $0.gender == "Mare" })
var sireIndex = 0
var damIndex = 0
@IBOutlet weak var horsePicker: UIPickerView!
@IBOutlet weak var sireBaseLayer: UIImageView!
@IBOutlet weak var damBaseLayer: UIImageView!
var recievedString: String = ""
func numberOfComponents(in sirePicker: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return myStallions.count
}
else {
return myMares.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let stallions = myStallions[row]
let mares = myMares[row]
if component == 0 {
return "\(stallions.name), health: \(stallions.health)"
}
else {
return "\(mares.name), health: \(mares.health)"
}
}
func pickerView(_ horsePicker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
var chosenSire = myHorses[sireIndex]
var chosenDam = myHorses[damIndex]
if component == 0 {
let theSire = myHorses[row]
sireNameOutlet.text = theSire.name
chosenSire = theSire
sireBaseLayer.image = chosenSire.basePhenotype
}
else {
let theMare = myHorses[row]
damNameOutlet.text = theMare.name
chosenDam = theMare
damBaseLayer.image = chosenDam.basePhenotype
}
}
override func viewDidLoad() {
super.viewDidLoad()
horsePicker.delegate = self
horsePicker.dataSource = self
}
}
I have this var:
//genes
var extGene = "ee"
var agoGene = "aa"
var creGene = "crcr"
//genotype
var genotype = extGene + agoGene + creGene
The genotype can appear in different variations like "eeaacrcr", "EeAaCrcr" or "EEAACrCr", but there are a lot more combinations. Sometimes the letters in the genes can appear in random order, for example "Ee" or "eE". I am using this switch statement which is getting too complex:
switch (extGene, agoGene, creGene) {
case
("EE", "aa", "crcr"),
("Ee", "aa", "crcr"),
("eE", "aa", "crcr"):
basPhenotype = (blackArray.randomElement()!)
case
("ee", "aa", "crcr"),
("ee", "Aa", "crcr"),
("ee", "aA", "crcr"),
("ee", "AA", "crcr"):
basPhenotype = (chestnutArray.randomElement()!)
case
("EE", "AA", "crcr"),
("Ee", "AA", "crcr"),
("eE", "AA", "crcr"),
("EE", "Aa", "crcr"),
("EE", "aA", "crcr"),
("Ee", "Aa", "crcr"),
("eE", "Aa", "crcr"),
("Ee", "aA", "crcr"),
("eE", "aA", "crcr"):
basPhenotype = (bayArray.randomElement()!)
Instead it would be nice to just search the genotype for single letters, irrespective of what order they are in, maybe something like this
if genotype contains "e" + "E" {
uiImage = image1
}
if genotype contains "ee" {
uiImage = image2
}
Does anyone know of a way to simplify the code?
I have a function that calculates a random genotype. At the moment all genes are equally likely. In reality, some genes are more likely than others. How can I change my function to be more realistic? I have attached some example percentages (they don't add up yet)
//grey 10% of "G" appearing, 90% chance of "g" appearing
greGenotype = ["G", "g"][Int.random(in:0...1)]+["G", "g"][Int.random(in:0...1)]
//single tobiano 5% of "To" appearing, 95% of "to" appearing
tobGenotype = ["To", "to"][Int.random(in:0...1)]+["To", "to"][Int.random(in:0...1)]
}
I want to find a random number in a range that goes 1-100. I want the number to be the average of these two:
var firstNumber = 20
var secondNumber = 30
but I want it to have some "variability"
var variability = Int.random(in:-12...12)
result: Int.random(in: (firstNumber)...(secondNumber) + variability)
The problem is, the result cannot go beyond 1-100. If the first number is close to the end of the range, variability could make the result go beyond 1-100. I tried using an If statement, but this involves writing a lot of extra code for each factor I am adding variability to. Any suggestions?
I want to change some properties in my array. I recently discovered that I am only able to do this if I directly specify the number of the element in the array I am working with. This is tricky because I always assumed you could edit an array using a variable. I have been using a variable to save myself a lot of code. In some view controllers, the array can have hundreds of items... my var is a workaround that uses the button tag to identify the horse that is selected for editing
import UIKit
struct Horse{
var name: String
var age: Int
}
var myHorses = [
Horse(name: "Billy", age: 3),
Horse(name: "Merc", age: 5)
]
//horse selected for editing
var currentHorse = myHorses[0]
//tag of the button that is pressed
var horseIndex = sender.tag
//trying to edit age
currentHorse.age = 10
//I thought these would be the same
print(myHorses[1].age)
print(merc.age)