How can I make this Stack struct define? - swift

I want to make this Stack struct properly.
How can I define 'topItem'?
Is it right to show above "newstack"?
struct Stack {
var Items:[String] = []
mutating func push (item:String){
Items += [item]
}
mutating func pop() -> String {
return Items.removeLast()
}
var topItem =`enter code here`
}
var newStack = Stack()
newStack.push("HistoryListController")
newStack.push("HistoryDetailViewController")
newStack.push("HistoryTimelineViewController")
newStack.push("HistoryChartViewController")
newStack.Items
if let topVC = newStack.topItem {
print("Top View Controller is \(topVC)")
//HistoryChartViewController
}
newStack.pop()
if let topVC = newStack.topItem {
print("Top View Controller is \(topVC)")
//HistoryTimelineViewController
}
I'm very beginner in Swift.
This is my first code

First, items should be lowercase. Second, it's not clear what you want topItem to return. If you want the most recent object, you could implement it like this:
struct Stack {
var items = [String]()
mutating func push (item:String){
items += [item]
}
mutating func pop() -> String {
let result = items[0]
items.removeLast()
return result
}
var topItem : String? {
return items.last
}
}
var newStack = Stack()
newStack.push("HistoryListController")
newStack.push("HistoryDetailViewController")
newStack.push("HistoryTimelineViewController")
newStack.push("HistoryChartViewController")
newStack.topItem // "HistoryChartViewController"
newStack.items
If you want the first object, change it to return items.first.

Related

How To Tell How Many Elements Are In A Swift Stack

I am using Swift stacks for my calculator app that I am making. But I need to tell if there is only one element in my stack for my calculator app to function correctly. Does anybody know how to count the number of elements in a Swift stack?
struct Stack {
fileprivate var operators: [String] = []
mutating func push(_element: String) {
operators.append(_element)
}
mutating func pop() -> String? {
return operators.popLast()
}
func peek() -> String? {
return operators.last
}
}
Swift doesn't have a built-in Stack type.
To reveal the size of your custom Stack struct, add a size property to your Stack that returns the number of items in the operators array:
struct Stack {
fileprivate var operators: [String] = []
mutating func push(_ element: String) {
operators.append(element)
}
mutating func pop() -> String? {
return operators.popLast()
}
func peek() -> String? {
return operators.last
}
var size: Int { return operators.count }
}
Example
var stack = Stack()
stack.push("+")
print(stack.size) // 1
_ = stack.pop()
print(stack.size) // 0

How to handle navigation with observables using Rx-MVVM-C

Hello I am trying to do a project with RxSwift and I am stuck trying to do in a properly way the connection between the Coordinator and the ViewModel.
Goal
Using observables, the Coordinator receives and event (in that case, when a row has been tapped) then does whatever.
Scenario
Giving a Post (String)
typealias Post = String
I have the following Coordinator:
class Coordinator {
func start() {
let selectedPostObservable = PublishSubject<Post>()
let viewController = ViewController()
let viewModel = ViewModel()
viewController.viewModel = viewModel
selectedPostObservable.subscribe { post in
//Do whatever
}
}
}
The selectedPostObservable is what I don't know how to connect it in a "clean" way with the viewModel.
As ViewModel:
class ViewModel {
struct Input {
let selectedIndexPath: Observable<IndexPath>
}
struct Output {
//UI Outputs
}
func transform(input: Input) -> Output {
let posts: [Post] = Observable.just(["1", "2", "3"])
//Connect with selectedindex
let result = input.selectedIndexPath
.withLatestFrom(posts) { $1[$0.row] }
.asDriver(onErrorJustReturn: nil)
return Output()
}
}
The result variable is what I should connect with selectedPostObservable.
And the ViewController (although I think is not relevant for the question):
class ViewController: UIViewController {
//...
var viewModel: ViewModel!
var tableView: UITableView!
//...
func bindViewModel() {
let input = ViewModel.Input(selectedIndexPath: tableView.rx.itemSelected.asObservable())
viewModel.transform(input: input)
}
}
Thank you so much.
Working with the structure you are starting with, I would put the PublishSubject in the ViewModel class instead of the Coordinator. Then something like this:
class ViewModel {
struct Input {
let selectedIndexPath: Observable<IndexPath>
}
struct Output {
//UI Outputs
}
let selectedPost = PublishSubject<Post>()
let bag = DisposeBag()
func transform(input: Input) -> Output {
let posts: [Post] = Observable.just(["1", "2", "3"])
//Connect with selectedindex
input.selectedIndexPath
.withLatestFrom(posts) { $1[$0.row] }
.bind(to: selectedPost)
.disposed(by: bag)
return Output()
}
}
class Coordinator {
func start() {
let viewController = ViewController()
let viewModel = ViewModel()
viewController.viewModel = viewModel
viewModel.selectedPost.subscribe { post in
//Do whatever
}
.disposed(by: viewModel.bag)
}
}

Property observers Swift 4

struct Kitchen // Coordinator
{
var foodItems = [FoodItem] () // Collection of FoodItem objects.
var wastedItems = [WastedItem]() // Collection of WastedItem
var totalSpend = Double()
var currentSpend = Double()
var weeklyHouseholdFoodBudget = Double()
var wastageCost = Double()
init(aTotal:Double,aCurrent:Double,aBudget:Double,aWastage:Double)
{
self.totalSpend = aTotal
self.currentSpend = aCurrent
self.weeklyHouseholdFoodBudget = aBudget
self.wastageCost = aWastage
}
struct FoodItem : Equatable
{
var itemName = String()
var itemQuantity = Double()
var dateOfUse = String()
var unitOfMeasurement = String()
init(aName:String,aQuantity:Double,aDateOfUse:String,aUnit:String)
{
self.itemName = aName
self.itemQuantity = aQuantity
self.dateOfUse = aDateOfUse
self.unitOfMeasurement = aUnit
}
mutating func listFoodItems()
{
for item in foodItems
{
print("Item Name:", item.getName(),",",
"Qunatity:",item.getItemQuantity(),",",
"Unit:",item.getUnitOfMeasurement(),",",
"Date of use:",item.getDateOfUse())
}
}
mutating func removeFoodItem(aFood:FoodItem)
{
if let anIndex = foodItems.index(of: aFood)
{
foodItems.remove(at: anIndex)
print(aFood.getName(),"Has been removed")
}
}
mutating func useFood(aFoodItem:inout FoodItem,inputQty:Double)
{
if (aFoodItem.getItemQuantity()) - (inputQty) <= 0
{
self.removeFoodItem(aFood: aFoodItem)
}
else
{
aFoodItem.useFoodItem(aQty: inputQty)
}
}
***Updated****
The issue I am having is when I use a func listFoodItems() the updated attribute itemQuantity does not change. I would like to know how to update the collection so when I call the func listFoodItems() it displays value changes.
The removal is ok, when the func runs the collection removes the object.
The issue must be because I am using for item in foodItems to display, I need to reload it with updated values before I do this?
Thank you for any assistance.
Property observers are used on properties.
The simplest example of a property observer.
class Foo {
var bar: String = "Some String" {
didSet {
print("did set value", bar)
}
}
}
Now if you want to display some changes, you will need your own code in didSet method in order to do that. For example call reloadData().

How to use one variable/property instead assigning same property three times?

Let's assume that myVar has same functionality in every implementation of view. I am trying to figure out how to declare/expose some kind of set-only property instead of assigning them n-times (with every new view created), but nothing comes to my head. How could I refactor into one line & one time assignment?
var myVar: (()-> Void)?
private func callBack() {
someClass.view1.myVar = self.myVar
someClass.view2.myVar = self.myVar
someClass.view3.myVar = self.myVar
}
// MARK: - someClass pseudocode
someClass: class {
let view1: CustomView: = CustomView
let view2: CustomView: = CustomView
let view3: CustomView: = CustomView
}
// MARK: - customView pseudocode
class CustomView: UIView {
var myVar: (()-> Void)?
}
something like this, but having all CustomViews in an array is good idea and could be implemented here as well
var a: (() -> Void)?
class CustomView: UIView {
var myVar: (() -> Void)?
}
class SomeClass {
let view1 = CustomView()
let view2 = CustomView()
let view3 = CustomView()
var myVar: (() -> Void)? {
set {
self.view2.myVar = newValue
self.view1.myVar = newValue
self.view3.myVar = newValue
}
get {
return self.myVar
}
}
}
let b = SomeClass()
b.myVar = ({print(3)})
b.view1.myVar!()
Is this what you are trying to do?
[someClass.view1, someClass.view2, someClass.view3].forEach { $0.myVar = self.myVar }
This is how I tend to deal with these issues:
class OtherClass {
var text: String?
init(text: String?) {
self.text = text;
}
}
class TestClass {
var thing1: OtherClass?
var thing2: OtherClass?
var thing3: OtherClass?
var allTheThings: [OtherClass?] { return [thing1, thing2, thing3]}
var ownText: String? {
didSet {
allTheThings.forEach { $0?.text = ownText }
}
}
}
Depending on how much you expect things to change you could make the array property a constant you set in your init rather than a computed property.
If you want to get fancy you could also do something like this for setting:
private var allTheThings: [OtherClass?] {
get {
return [thing1, thing2, thing3]
}
set {
guard newValue.count == 3 else {
//probably should put an assertion in here
return
}
thing1 = newValue[0]
thing2 = newValue[1]
thing3 = newValue[2]
}
}
init() {
self.allTheThings = Array(repeating: OtherClass(text: "Test"), count: 3)
}

Access to stored properties of a struct from a extension in Swift

I'm trying to implement a Stack struct in Swift and making it comply to Generator and Sequence.
class Stack<T> {
var items:Array<T>
var depth : Int{ return items.count}
init(){
items = Array<T>()
}
func push(elm:T){
items += elm
}
func pop()->T?{
if depth > 0{
return items.removeLast()
}else{
return nil
}
}
}
I get into trouble when trying to make it comply to Generator. I tried adding a nested type through an extension, that's when I get an error:
extension Stack{
struct StackGenerator: Generator{
var current = 0
mutating func next() -> T?{
let rc = items[current] // Get an error here: can't access items in Stack
}
}
}
The compiler won't let me access the Stack.items property form within StackGenerator. Is this to be expected? How can I work around this?
Generic types can't have nested types - you need to either build StackGenerator outside of your Stack declaration, or use the GeneratorOf<T> type in your generate function.
The first option could look like this:
class Stack<T> : SequenceType {
var items: Array<T>
var depth: Int { return items.count }
init(){
items = Array<T>()
}
func push(elm:T){
items += [elm]
}
func pop()->T?{
if depth > 0 {
return items.removeLast()
} else {
return nil
}
}
func generate() -> StackGenerator<T> {
return StackGenerator(stack: self)
}
}
struct StackGenerator<T>: GeneratorType {
typealias Element = T
var current = 0
var stack: Stack<T>
init (stack: Stack<T>) {
self.stack = stack
}
mutating func next() -> T? {
if current < self.stack.items.count {
return self.stack.items[current++] // Get an error here: can't access items in Stack
}
return nil
}
}