Randomly select an instantiation of a class and display it? - arrays

Goal: Randomly select a member of a class containing people, and display the information in an alert.
Here is what I am doing: I have a class called Entrepreneurs. Inside the class are variables for name, networth etc. I have instantiated the class with several Entrepreneurs as follows:
//Class for entrepreneurs
class Entrepreneurs {
var name:String?
var netWorth = (0.0, "")
var company:String?
var summary: [String]
var age: Int?
init() {
name = ""
company = ""
summary = [""]
age = 1;
}
}
let markZuckerBerg = Entrepreneurs()
markZuckerBerg.name = "Mark Zuckerberg"
markZuckerBerg.age = 19
markZuckerBerg.company = "Facebook"
markZuckerBerg.netWorth = (35.7, "Billion")
I have several instantiations (more than 5) and I now want to randomly access a member from the Entrepreneur class and display its properties.
I know I will need an Array to hold the class members but I don't think adding each member of the class in an array is the most efficient way to go about it, since I plan on adding hundreds of entrepreneurs eventually.
Any Suggestions?
(Side question: is this the best way to structure such a problem? In other words, If my goal is to have a list of entrepreneurs with information about them, and I want them to display randomly on the screen of a phone as an alert, is creating a class of entrepreneurs the best way?)

Seems to me like you want to randomly select objects from a group of them. To do this you need an array and a random number between 0 and the amount of elements in the array.
Code
let array: [Entrepreneurs] = [a,b,c,...]
let random: Int = Int(arc4random_uniform(UInt32(array.count)))
let selection: Entrepreneurs = array[random]
As far as showing them through and alert I need more details on the question.

Related

how do I get rid of this simple SwiftUI error?

I just wanna get all the records from the transaction variable and save it to an array.i tried and all I am getting is this constant error. please help me, I just wanna all models(records) to be saved on an array.
Type '()' cannot conform to 'View'
#State private var transactions: [Transactions] = [Transactions]()
ForEach(transactions, id: \.self) { transaction in
timexxx[0] = transaction.timexx ?? "0"
Text(timexxx[0] ?? "0")
}
enter image description here
Like what #multiverse has suggested
ForEach loop expects some sort of View but you are giving it or attempting to give an "array" (it only wants View)
Here is an updated code where you give the ForEach what it wants and you append to your timexxx array
ForEach(Array(transactions.enumerated()), id: \.offset) { (offset, transaction) in
Text(transaction.timexx ?? "\(offset)")
.onAppear {
timexxx[offset] = transaction.timexx ?? "\(offset)"
}
}
Update
for your question
"how do I do this with a simple "For" loop ? let's say I wanna do this operation in a simple class."
This is how it's done.
I removed the view Text.
for (i, transaction) in transactions.enumerated() {
timexxx[i] = transaction.timexx ?? "0"
}
Ok , so this is an error i faced as well, when i was learning SwiftUI( i am still a beginner), so now we need to understand , what does this error actually means, in this case the ForEach loop expects some sort of View but you are giving it or attempting to give an "array" (it only wants View)....
If you want values to be transferred to an array just simply create a function and do it .....
say you have a class and inside of which you do
#Published var song = [Song]()
then what you do is inside a function like loadData()
objects is the array whose elements you want transferred and most likely those elements belong to a Struct like Song here(if not its even simpler just use what ever type it has like Int, String etc.), this way all your elements will get transferred to song from objects
func loadData() {
song = objects.map {
artist in
Song(album: artist.album, artistImage: artist.artistImage)
}
}
Here i add the simplest possible way to transfer from one array to other
var objects = [1,2,3,4,5]
var song = [Int]()
func loadData() {
song = objects.map { $0 }
}
loadData()
print(song)
//[1,2,3,4,5]

Swift : multi-dimensional structure organization and init

There are two simple problems here in initializing this structure.
One is the enunumerated value TS (I get error : Cannot convert value of type 'TournNames' to expected argument type 'TournamentName')
the other is initializing an array of strings (I get the error : Cannot convert value of type '[String]' to expected argument type 'TouramentScores'
Suppose I am trying to set up a structure to model the scores of tennis players and all of their matches in each of the major tournaments (just for fun). Each tournament has a name (e.g. Wimbledon) and a series of scores for that player (for example, in the opening match, their score might be "4-6, 6-4, 7-6, 6-2")... upto 7 matches in each tournament. Each player should have an array of four tournaments (names and array of scores), and eventually there should be an array of players. I am also trying to use enums not too successfully. Ideally, if I want to find how Roger Federer did in his third match of wimbledon this year, I would access something like player.tournament.wim.Roundof32 or something roughly like that. But before I can even get to playing with that, I can't seem to init dummy data for even a single tournament.
Any ideas? I don't think this is that hard of question but I just don't know each. See "*** this line" below for two lines that are problematic
// tournament name enum
enum TournNames : String {
case wim = "Wimbledom"
case fo = "French Open"
case ao = "Australian Open"
case uo = "US Open"
}
//
struct TournamentName {
var Tname : TournNames // = .wim
}
// This is the structure for a tournament score array with some dummy values.
struct TouramentScores {
var Match1 : String = "7-6, 6-4, 3-6, 7-6"
var Match2 : String = "7-6, 6-4, 3-6, 7-6"
}
// This is one entire Tournament record for one player = tournament name + array of scores ... the next goal but not used here until I get over these hurdles
struct TournamentResult {
var TournamentName : TournNames = .wim
var Scores : TouramentScores
}
// ... finally the structure of a player ...
struct DummyTennisPlayer {
var LastName : String // last name
var FirstName : String //first name
var TN : TournamentName
var TS : TouramentScores
// var WimRes : TournamentResult // to start a single tournament
// var SeasonResults : [TournamentResult] // ultimately should be an array of 4 tournaments
}
// trying to initialize some dummy data without success after trying several things
extension DummyTennisPlayer {
static var dummyResults : [DummyTennisPlayer] {
[
DummyTennisPlayer.init(
LastName : "Federer",
FirstName: "Roger",
TN : TournNames.wim // **** this line
,
TS : ["XX", "yy"] /// *** this line
)
]
}
}
As I think you're discovering, a simple series of nested types is unlikely to cut it here. As soon as you get to entities like players, tournaments, matches and lookups like "how Roger Federer did in his third match of wimbledon this year", you've become a candidate for using a database where you can manipulate one-to-many and many-to-many relationships. I can't tell you what database to use, and anyway that's a matter of opinion; from what you've said so far, SQLite would be sufficient (and I am personally not a fan of Core Data just for this kind of thing).
I guess your code is a kind of exercise, so before you go on later to Core Data or SQLite,
extension DummyTennisPlayer {
static var dummyResults: [DummyTennisPlayer] = [
DummyTennisPlayer(LastName: "Federer", FirstName: "Roger", WimbledomResult: TournamentResult(Scores: TouramentScores()))
]
}
should answer your question.
1 - To initialize a Swift struct, use the following syntax:
MyStruct(property1: "my property1 value", property2: "my property2 value")
2 - the tournament name property in TournamentResult is already set to .wim so you just need to initialize the Scores. As your TournamentScores properties are already all set, you just need to pass an instance of TournamentScores() to TournamentResult(Scores:).
By the way, only use lowercases for the first letter of the name of your variables or struct properties: var lastName or TournamentResult(scores:).
I think you are confusing the term "multi-dimensional (array) structures" (which are just arrays nested inside other arrays, like that: [ [1, 2, 3], [2, 3, 4], [3, 4, 5]]) with the struct objects. You are probably not supposed to use structs so extensively here.
Don't hesitate to review the way you decide to use enums, structs, or arrays. Your code may work but will be difficult to read and use (example: how would you access a specific set score if you put all of the set scores in a single String? Why not use an array?)

How do I update unlockable characters in SpriteKit game with Swift 3?

I have currently made a game featuring one player. I also made a character screen where the user can choose which character he/she wants to play with. How do I make it so that a certain high score unlocks a certain character, and allows the user to equip this character to use in the game?
Right now my player has his own swift file that defines all the properties of him:
import SpriteKit
class Player: SKSpriteNode, GameSprite {
var initialSize = CGSize(width:150, height: 90)
var textureAtlas: SKTextureAtlas = SKTextureAtlas(named: "Rupert")
let maxFlyingForce: CGFloat = 80000
let maxHeight: CGFloat = 900
var health:Int = 1
var invulnerable = false
var damaged = false
var damageAnimation = SKAction()
var dieAnimation = SKAction()
var forwardVelocity: CGFloat = 190
var powerAnimation = SKAction()
init() {
super.init(texture:nil, color: .clear, size: initialSize)
createAnimations()
self.run(soarAnimation, withKey: "soarAnimation")
let bodyTexture = textureAtlas.textureNamed("pug3")
self.physicsBody = SKPhysicsBody(texture: bodyTexture, size: self.size)
self.physicsBody?.linearDamping = 0.9
self.physicsBody?.mass = 10
self.physicsBody?.allowsRotation = false
self.physicsBody?.categoryBitMask = PhysicsCategory.rupert.rawValue
self.physicsBody?.contactTestBitMask = PhysicsCategory.enemy.rawValue | PhysicsCategory.treat.rawValue | PhysicsCategory.winky.rawValue | PhysicsCategory.ground.rawValue
func createAnimations() {
let rotateUpAction = SKAction.rotate(toAngle: 0.75, duration: 0.475)
rotateUpAction.timingMode = .easeOut
let rotateDownAction = SKAction.rotate(toAngle: 0, duration: 0.475)
rotateDownAction.timingMode = .easeIn
let flyFrames: [SKTexture] = [
textureAtlas.textureNamed("pug1"),
textureAtlas.textureNamed("pug2"),
textureAtlas.textureNamed("pug3"),
textureAtlas.textureNamed("pug4"),
textureAtlas.textureNamed("pug3"),
textureAtlas.textureNamed("pug2")
]
let flyAction = SKAction.animate(with:flyFrames, timePerFrame: 0.07)
flyAnimation = SKAction.group([SKAction.repeatForever(flyAction), rotateUpAction])
let soarFrames:[SKTexture] = [textureAtlas.textureNamed("pug5")]
let soarAction = SKAction.animate(with: soarFrames, timePerFrame: 1)
soarAnimation = SKAction.group([SKAction.repeatForever(soarAction), rotateDownAction])
This is not all the code but you get the point.
I then say: let player = Player() in my Gamescene file which essentially attaches all the attributes in the player file to my player that will be seen in the Gamescene. Even if I am able to replace the initial player with a certain different player, there are so many animations that I don't know how to replace everything at once. I want to set a condition that spans over both the gamescene class and the player class so that it can just sub out certain images for other ones and keep the same actions.
Thank you for any help!
Here are some techniques you can use for making things like this more manageable:
Have a naming convention for your character images and/or sprite sheets, so that you can pass in a name to your Player() constructor. Then, instead of loading texturenamed("pug3"), you load up texturenamed("\(playerName)3"). If the only difference between your characters are the sprite sheets, this is actually all you need on the Player end.
If your characters are more complex, with differences beyond just the images, like being larger or having more health, then you will probably want to go with a more data-oriented approach. There are a couple of approaches to this, but a handy one is to read your texture names, hitbox sizes, health levels, etc., out of a .plist file instead of hard-coding them. Then just pass in the name of the .plist file to load for the character you want. Then, to create a new character, you just create a new .plist file. Another approach would be to create a "character definition" struct that you could pass to the Player constructor that contains the information you need to construct the player (this, in turn, could be loaded from a .plist file, as well, but you could also hard-code them or save them directly using codable serialization).
If neither of the above approaches are sufficient, say if you need different behavior between characters, you could always go the subclassing route - pull the various parts and pieces out into functions, and then override those functions to add the specific functionality you need for more complex characters.

Appending Class Objects to Array [Swift]

I have a RestAPI that pulls JSON data from a webpage, and because I want to follow MVC programming standards, I want to fetch this data through a "Data List" class that instantiates the RestAPI Class.
I have a class called "Card", which provides the basic structure of a type of data object. I have a class called "CardList" whose initialization creates an Array of the "Card" Classes.
However, I'm having trouble appending Card Class data to my CardList Array.
Here is the code for CardList Class:
class CardList {
var cards: [Card]
static var sharedInstance = CardList()
//MARK - Initalize
private init(){
//Dummy Data
let helm = Card(name: "Helm of Testing", cost: 10, type: "Equipment", subType: "Head Armor", description: "Some say the Helmet of Testing helps keep it's wearers mind clear.")
//Add to Array
var c = [helm]
let items: NSMutableArray = []
//Get API Array
RestApiManager.sharedInstance.getElements { (json: JSON) in
let results = json["results"]
for (_, subJson) in results {
let card:AnyObject = subJson["card"].object
items.addObject(card)
}
for var i = 0; i < items.count; ++i{
let data:JSON = JSON(items[i])
let newCard = Card(name: data["title"].stringValue, cost: Int(data["cost"].string!)!, type: data["type_id"].stringValue, subType: data["subtype_id"].stringValue, description: data["description"].stringValue)
c.append(newCard)
}
}
cards = c.sort { $0.cost < $1.cost }
}
//END Class
}
So basically on initialization, this class creates a dummy Card, adds it to an array called "c". An array called "items" is created. There RestApiManager returns JSON data, for every type of data returned in the results, it gets added into the "items" array.
We then loop through the "items" array, reading it as JSON (I'm using the SwiftyJSON plugin/code snip) and creating a new "Card" Class for each item in the array. We then append the "Card" to the "c" Array.
Finally we take the Card Array "cards" and set it equal to the "c" Array sorted by it's value cost.
The Problem:
After running the code, the "cards" Array only returns the dummy card named "helm", and none of the data added to the "c" array.
Notes:
Yes, my Api is working, if I print the values in the "for var i = 0" loop, it is printing correct values. If I print the "c.count" in the same loop, I get two (The API is only returning 1 other data set, or "Card"). If I print the "c.count" outside of that loop, after the loop, it says there is only 1 item in the Array when there should be two (the dummy data and the data returned from the JSON call).
So, it's clearly something with my syntax. Or maybe I'm making things more complicated than they need to. I'm fairly new to Swift and slightly confused. I just need someone else to look at my code.
Thank you in advance.
RestApiManager.sharedInstance.getElements works asynchronously.
The block containing the data is executed after the init function exits.
Move the code to assign and sort the array into the block.
...
for var i = 0; i < items.count; ++i{
let data:JSON = JSON(items[i])
let newCard = Card(name: data["title"].stringValue, cost: Int(data["cost"].string!)!, type: data["type_id"].stringValue, subType: data["subtype_id"].stringValue, description: data["description"].stringValue)
c.append(newCard)
}
cards = c.sort { $0.cost < $1.cost }
}
}

Populating a tableView based on user distance form venue Location in Swift+Parse

I was wondering how you would go about making a tableView that is based on distance between User and a location. My current way of going about it is to load the PFObjects from Parse (includes 1. Venue Name, 2. Venue Image, 3. Venue Location) and then using the information from the PFObjects to make tuples based on [(Name), (Image), (Distance)]. The distance value is determined through finding the distance from current user location and venue location.
Afterwards I would sort the tuples out by distance ( distance < 10 would be 'near' , distance > 10 would be 'far'). After sorting out the 'near' tuples and 'far' tuples I would append these values into their specific arrays (e.g. nearNameLabel, nearImageLabel) and use these arrays to populate the table.
So far I have been having trouble with properly filling the data into their designated arrays due to concurrency issues (placing things in the right threads). I was wondering if there is a better way of going about this issue? Thanks for your time guys.
Instead of using separate arrays you can design it in object level. Like create a class Venue,
class Venue: NSObject {
var name : String?
var location : CLLocation?
var image : UIImage?
}
Load PFObjects as Venue in a single venueArray.
Then sort it with user location,
func sortArray(venueArray : Array<Venue>, myLocation : CLLocation) -> Array<Venue> {
var sortedArray = sorted(venueArray) {
(obj1, obj2) in
// The downcast to Person is only needed if persons is an NSArray or a Swift Array of AnyObjects
let v1 = obj1 as Venue
let v2 = obj2 as Venue
let distance1 = v1.location?.distanceFromLocation(myLocation)
let distance2 = v2.location?.distanceFromLocation(myLocation)
return distance1 < distance2
}
return sortedArray
}

Resources