How to create a var in an if statement with SwiftUI - swift

I've a ForEach loop in my var body: some View but the var isn't recognized after the if loop. Is there a way to fix this?
I've tried to remove the if loop and set it above the body item. But then I get some error that te isOldDate var is used before Self is available.
if self.Bol{
let OldDateType = self.OldDate.asDate
}else{
var OldDateType = isNewDay
}
var isOldDate = (OldDateType, formatter: ContentView.self.Day)
The expected result is that var isOldDate should be recognized

Try to write the if/else as
let oldDateType = self.Bol ? self.OldDate.asDate : isNewDay

Related

Getting a sub string from a string to show in Text for Swiftui

Greeting everyone. I just started my Swiftui journey.
I am trying to get a piece of string from a string variable to display as Text() in Swiftui. In my previous languages I would do something like var subVal = val[1] but it seem this method does not work here.
Is there a way to work around this problem?
//I want the "r" value which is the second element of val
var val = "orange"
#State var newVal = val[1]
.....
Text("\(newVal)"
you should read the basics at: https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html especially the section on Strings and Characters in Swift at: https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html and also do the tutorial at: https://developer.apple.com/tutorials/swiftui/
Without knowing the basics you will not go very far in coding your app.
struct ContentView: View {
var val = "orange"
#State var newVal = ""
var body: some View {
Text(newVal)
.onAppear {
let index = val.index(val.startIndex, offsetBy: 1)
newVal = String(val[index])
}
}
}
There are many possible ways that you can extract a substring from a string either to get a Character or a new String by using .prefix, .suffix, .index, etc.
var val = "orange"
//using prefix, you will receive a string back
var newVal = val.prefix(2) //"or"
//using suffix, you will receive a string back
var newVal = val.suffix(2) //"ge"
for your case, you can either use the given solution by #workingdog support Ukraine or create a custom extension for reuse
struct ContentView: View {
#State var val = "orange"
var body: some View {
//you can do String[index] directly
//the return value is Character, so you need to cast to String
Text(String(val[1])) //"r"
}
}
//reusable extension
extension StringProtocol {
subscript(offset: Int) -> Character {
self[index(startIndex, offsetBy: offset)]
}
}

Is there a better way to pass data to a custom keyboard view in SwiftUI?

I'm new to Swift and SwiftUI (and programming in general).
I'm trying to build an app about statistics, and because of these specific needs, I had to write a custom keyboard with numbers and basic operations. The problem is that I want to store the X values and Y values in two different arrays so I have to call my "ChartKeyboard" two times: one for writing the X values and other time for the Y values. Here is the code I use to call the keyboard:
Group {
if isXorYSelected == .x {
ChartKeyboard(isShown: $keyShown, txtInput: $sampleData.XValues[arrayPosition])
}
if isXorYSelected == .y {
ChartKeyboard(isShown: $keyShown, txtInput: $sampleData.YValues[arrayPosition])
}
}
The data is stored in a custom ChartData object:
struct ChartDataObject: Identifiable {
let id = UUID()
var name: String
let date: Date
var regType: regressionType
var dataX: [Double]
var dataY: [Double]
var regressionCoef: Double
var slope: Double
var origin: Double
}
And some of the state variables in case you wonder:
struct NewChart: View {
#State var keyShown = false
#State var sampleData = XYData(XValues: [" "], YValues: [" "])
var newChartType = ["Standard Addition", "External Standard","Internal Standard"]
#State private var selectedChartType = 0
/*
Types are:
1 = Standard Addition
2 = External Standard
3 = Internal Standard
*/
#State var newChartTitle = ""
#State var newChartDate = Date()
#State var isXorYSelected = isXorY.x
#State var arrayPosition = 0
(...)
The result is a weird animation when changing from isXorYSelected from .x to .y:
Thanks.
Having the view within the if clause is probably causing it to be redrawn. Instead, you can change the parameter with a ternary expression:
ChartKeyboard(isShown: $keyShown, txtInput: isXorYSelected == .x ? $sampleData.XValues[arrayPosition] : $sampleData.YValues[arrayPosition])

Generic Type array with UITableView and Realm

I am using realm for database. I have Favourite Object and History Object.
I want to show in TableViewController. However, I don't want to do duplicated code. For now, in FavouriteViewController , it has var favs: Results<OGFav>? and HistoryViewController, it has var history: Results<OGHistory>?
Most of the code are the same and different is data type.
Example: it only different like following
if let object:OGFav = self.favs?[indexPath.row] {
In some place , I use like
let fav:OGFav = favs[indexPath.row]
For History
if let object:OGHistory = self.history?[indexPath.row] {
History also use like below
let history:OGHistory = self.history[indexPath.row]
How can I clean the code ? I am using two viewcontroller and code are the same excepted OGFav and OGHistory.
Update:
OGFav and OGHistory have the same data.
class OGFav: Object {
dynamic var word = ""
dynamic var def = ""
}
class OGHistory: Object {
dynamic var word = ""
dynamic var def = ""
dynamic var updatedAt = NSDate()
}

Merging data from multiple Google Sheets into one using script with array

I have multiple projects that output daily data to their own Google spreadsheets. I would like to make one master sheet in which this data is captured. This is fairly easy to do using importrange, but the spreadsheet becomes very, very slow when a large quantity of data is imported like this, so I'm hoping to use a script to just copy and paste the data over.
I know how to do set up the script manually using the following code from another post:
var sourceSpreadsheetID = "ID HERE";
var sourceWorksheetName = "SHEET NAME HERE";
var destinationSpreadsheetID = "ID HERE";
var destinationWorksheetName = "SHEET NAME HERE";
function importData() {
var thisSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
var thisWorksheet = thisSpreadsheet.getSheetByName(sourceWorksheetName);
var thisData = thisWorksheet.getDataRange();
var toSpreadsheet = SpreadsheetApp.openById(destinationSpreadsheetID);
var toWorksheet = toSpreadsheet.getSheetByName(destinationWorksheetName);
var toRange = toWorksheet.getRange(1, 1, thisData.getNumRows(), thisData.getNumColumns())
toRange.setValues(thisData.getValues());
}
But ideally, I would like to make the list easy to expand using an array. I've set up an "import" table (see the figure below), so I would guess a for loop running through it would allow me to do this, but I'm not sure how.
Image of table
I'd really appreciate any help you guys can offer. Thanks!
To answer my own question, I've managed to cobble the following together and it seems to work:
function importData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var keysSheet = ss.getSheetByName("Keys")
var targetSheet = ss.getSheetByName("Test")
var keys = keysSheet.getRange("B2:B50").getValues();
var sheets = keysSheet.getRange("C2:C50").getValues();
var ranges = keysSheet.getRange("D2:D50").getValues();
var row, startcolumn = 1;
for (row = 1; row < 50; row++) {
if (keys[row-1] != '' && sheets[row-1] != '' && ranges[row-1] != '') {
var sourceSpreadsheetID = keys[row-1];
var sourceWorksheetName = sheets[row-1];
var sourceDataRange = ranges[row-1];
var thisSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
var thisWorksheet = thisSpreadsheet.getSheetByName(sourceWorksheetName);
var thisData = thisWorksheet.getRange(sourceDataRange);
var toRange = targetSheet.getRange(1, startcolumn, thisData.getNumRows(), thisData.getNumColumns());
toRange.setValues(thisData.getValues());
startcolumn = startcolumn + thisData.getNumColumns();
}
}
}
I am sure that this can be done more efficiently using arrays, a while loop (rather than a for loop), and a keys table range that updates automatically based on its size, but I couldn't figure out how to do that with my high school coding skills.
Hopefully what I've figured out so far will help someone else!

What does StringInterpolationSegment do? (swift)

I continued on my math question project, and it could now generate questions, so I need to try to use a global variable to use my answer's in generating the answer itself and putting the answer randomly into one of 4 choices. I decided to put a secret label outside of my view that shows the answer. Here's my code:
//important stuff
#IBOutlet var secretAnsarrrrr: UILabel!
//useless code
//declare the value of secretAnsarrrr
secretAnsarrrrr.text = String(answer)
numA.text = String(Int(randomNumber))
numB.text = String(Int(randomNumber2))
}
generateQuestion()
}
var optionAnswer:UInt32 = arc4random_uniform(4)
#IBAction func answerA(sender: UIButton) {
var otherAns:String = String(secretAnsarrrrr) //error
if optionAnswer == 0 {
optionA.text = secretAnsarrrrr.text
}
Doing so gives me the error of 'Missing argument label: StringInterpolationSegment in call'. It tells me to place it behind 'secretAnsarrrrr' in the parentheses. What does stringInterpolationSegment do and how do I fix this?
secretAnsarrrrr is not a string itself - it is a UILabel which also contains information like color and font. You need to tell Swift to use its text property:
var otherAns:String = String(secretAnsarrrrr.text)
I just encountered this error, and after some head scratching, I realised that I needed to unwrap an optional integer which I was trying to parse with String(...). As soon as I added the exclamation mark, the problem was solved:
var num: Int? = 1
var str = String(num!)
it is Better to write:
var num: Int? = 1
var str = num.map { String($0) } // if num == nil then str = nil else str = string representation