Swift - Computed Property Return - ios

I have array of dictionaries that I will use for cells in collectionView. I'm new to swift, so I try to find the best way to store that.
Now I use this code:
var collectionViewData: [collectionViewStruct] = {
var cell_1 = collectionViewStruct()
cell_1.title = "..."
cell_1.text = "..."
cell_1.firstColor = "C68CF2"
cell_1.secondColor = "EFA8CA"
var cell_2 = collectionViewStruct()
cell_2.title = "..."
cell_2.text = "..."
cell_2.firstColor = "C68CF2"
cell_2.secondColor = "EFA8CA"
return [cell_1, cell_2]
}()
Is there a way not to write every var in return?
How to return all the variables at once?
Or maybe there is a better way to store this data?
Thanks in Advance :)

If the suggestions data is never changing, just use the following struct:
struct collectinView {
let title: String
let text: String
let firstColor = "C68CF2"
let secondColor = "EFA8CA"
}
let collectionViewData = [
collectionView(title: "...", text: "..."),
collectionView(title: "other Title", text: "Other text")]

For achieving this you can use a private property and return that instead like:
private var _suggestions: [suggestionsStruct] = [suggestionsStruct]()
var suggestions: [suggestionsStruct] {
get{
if _suggestions.count > 0{
var suggestion_1 = suggestionsStruct()
suggestion_1.title = "..."
suggestion_1.text = "..."
suggestion_1.firstColor = "C68CF2"
suggestion_1.secondColor = "EFA8CA"
_suggestions.append(suggestion_1)
}else{
var suggestion_1 = suggestionsStruct()
suggestion_1.title = "..."
suggestion_1.text = "..."
suggestion_1.firstColor = "C68CF2"
suggestion_1.secondColor = "EFA8CA"
_suggestions = [suggestion_1]
}
return _suggestions
}
}

Related

Inserting an AnnotatedString into an EditText (Jetpack Compose)

I'm trying to solve the following issue. For example, I'm writing this text - "Hello *world*". After I stop writing, for example, after a second, the word "*world*" should be replaced by "world" in bold.
I've tried to do this, but so far it doesn't work.
val originalText = MutableStateFlow("")
val resultText = originalText
.debounce(1000)
.distinctUntilChanged()
.flatMapLatest { text ->
val result = formatText(text) // create AnnotatedString
flow { emit(result) }
}
And trying to insert to EditText:
val resultText by viewModel.resultText.collectAsState(AnnotatedString(""))
OutlinedTextField(
value = TextFieldValue(resultText),
onValueChange = {
viewModel.originalText.value = it.text
},
label = { Text("Description") },
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
)
The problem is that I can't achieve the following result: we write text to "EditText" and after a second it is formatted and inserted into the same "EditText".
Could someone tell me, please, how can I solve this issue?
I found out a solution, but I'm sorry for code. It's definitely worth improving.
ViewModel methods:
private var _wordList = mutableListOf<String>()
val wordList = _wordList
// Remove words that are not in the string
fun updateWordList(text: String) {
_wordList.forEach {
if(!text.contains(it)) {
_wordList.remove(it)
}
}
}
fun getWords(text: String) : List<String> {
val regex = Regex("\\*(.*?)[\\*]")
val matches = regex.findAll(text)
return matches.map { it.groupValues[1] }.toList()
}
fun addWords(text: String) {
val words = getWords(text)
words.forEach { word ->
if(!_wordList.contains(word)) _wordList.add(word)
}
}
A method which create an AnnotatedString:
fun getAnnotatedString(text: String, words: List<String>): AnnotatedString = buildAnnotatedString {
append(text)
words.forEach { word ->
if (text.contains(word)) {
val offsetStart = text.indexOf(word)
val offsetEnd = offsetStart + word.length
addStyle(
style = SpanStyle(fontWeight = FontWeight.Bold),
start = offsetStart,
end = offsetEnd
)
}
}
}
After that we need to create the following variables:
val words = viewModel.getWords(description)
viewModel.addWords(description)
val descResult = if (words.isEmpty()) description else description.replace("*", "")
val formattedString = formatString(descResult, viewModel.wordList)
var textFieldValueState by remember {
mutableStateOf(TextFieldValue(annotatedString = formattedString))
}
val textFieldValue = textFieldValueState.copy(annotatedString = formattedString)
And finally, we define the OutlinedTextField:
OutlinedTextField(
value = textFieldValue,
onValueChange = {
viewModel.updateWordList(it.text)
if (tmp == it.text) {
textFieldValueState = it
return#OutlinedTextField
}
description = it.text
textFieldValueState = it
},
label = { Text("Description") }
)

How to integrate PayUMoney in swift

I want to integrate the PayUMoney SDK in my app using
I am using this link to integrate PayUMoney: How to integrate PayU Money in swift
I can see only the option to pay by credit card referring to the link's sample code however it is not showing up the net banking option. I don't understand what I am doing wrong in my code.
Here's what I have tried -
import UIKit
import PlugNPlay
import CommonCrypto
class PaymentVC: UIViewController {
var type = String()
var email = String()
var name = String()
var phone = String()
var address = String()
var state = String()
var zipcode = String()
var officetype = Int()
var TotalAmmount = String()
override func viewDidLoad() {
super.viewDidLoad()
continueWithCardPayment()
// Do any additional setup after loading the view.
}
#IBAction func backButtonAction(_ sender: UIButton) {
self.navigationController?.popViewController(animated: true)
}
func continueWithCardPayment()
{
var paymentParam = PUMTxnParam()
paymentParam.key = "Zegfsgh"
paymentParam.merchantid = "7085776"
paymentParam.txnID = "xyz"
paymentParam.phone = "8770338859"
paymentParam.amount = TotalAmmount
paymentParam.productInfo = "Nokia"
paymentParam.surl = "https://test.payumoney.com/mobileapp/payumoney/success.php"
paymentParam.furl = "https://test.payumoney.com/mobileapp/payumoney/failure.php"
paymentParam.firstname = "john"
paymentParam.email = "john#john.com"
paymentParam.environment = PUMEnvironment.test
paymentParam.udf1 = "udf1"
paymentParam.udf2 = "udf2"
paymentParam.udf3 = "udf3"
paymentParam.udf4 = "udf4"
paymentParam.udf5 = "udf5"
paymentParam.udf6 = ""
paymentParam.udf7 = ""
paymentParam.udf8 = ""
paymentParam.udf9 = ""
paymentParam.udf10 = ""
paymentParam.hashValue = self.getHashForPaymentParams(paymentParam)
// paymentParam. = ""
// Set this property if you want to give offer:
// paymentParam.userCredentials = ""
PlugNPlay.presentPaymentViewController(withTxnParams: paymentParam, on: self, withCompletionBlock: { paymentResponse, error, extraParam in
if error != nil {
UIUtility.toastMessage(onScreen: error?.localizedDescription, from: .none)
} else {
var message = ""
if paymentResponse?["result"] != nil && (paymentResponse?["result"] is [AnyHashable : Any]) {
print(paymentResponse!)
message = "Hello Asad sucess"
// message = paymentResponse?["result"]?["error_Message"] as? String ?? ""
// if message.isEqual(NSNull()) || message.count == 0 || (message == "No Error") {
// message = paymentResponse?["result"]?["status"] as? String ?? ""
// }
} else {
message = paymentResponse?["status"] as? String ?? ""
}
UIUtility.toastMessage(onScreen: message, from: .none)
}
})
PlugNPlay.presentPaymentViewController(withTxnParams: paymentParam, on: self, withCompletionBlock: .none)
}
func sha512(_ str: String) -> String {
let data = str.data(using:.utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
data.withUnsafeBytes({
_ = CC_SHA512($0, CC_LONG(data.count), &digest)
})
return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
}
func getHashForPaymentParams(_ txnParam: PUMTxnParam?) -> String? {
let salt = "vw8LigfjD"
var hashSequence: String? = nil
if let key = txnParam?.key, let txnID = txnParam?.txnID, let amount = txnParam?.amount, let productInfo = txnParam?.productInfo, let firstname = txnParam?.firstname, let email = txnParam?.email, let udf1 = txnParam?.udf1, let udf2 = txnParam?.udf2, let udf3 = txnParam?.udf3, let udf4 = txnParam?.udf4, let udf5 = txnParam?.udf5, let udf6 = txnParam?.udf6, let udf7 = txnParam?.udf7, let udf8 = txnParam?.udf8, let udf9 = txnParam?.udf9, let udf10 = txnParam?.udf10 {
hashSequence = "\(key)|\(txnID)|\(amount)|\(productInfo)|\(firstname)|\(email)|\(udf1)|\(udf2)|\(udf3)|\(udf4)|\(udf5)|\(udf6)|\(udf7)|\(udf8)|\(udf9)|\(udf10)|\(salt)"
}
let hash = self.sha512(hashSequence!).description.replacingOccurrences(of: "<", with: "").replacingOccurrences(of: ">", with: "").replacingOccurrences(of: " ", with: "")
return hash
}
func paymentResponseReceived(notify:NSNotification) {
print(notify)
}
}

How can I change a UILabel into a number programmatically? [duplicate]

I'm trying to work out how to cast an Int into a String in Swift.
I figure out a workaround, using NSNumber but I'd love to figure out how to do it all in Swift.
let x : Int = 45
let xNSNumber = x as NSNumber
let xString : String = xNSNumber.stringValue
Converting Int to String:
let x : Int = 42
var myString = String(x)
And the other way around - converting String to Int:
let myString : String = "42"
let x: Int? = myString.toInt()
if (x != nil) {
// Successfully converted String to Int
}
Or if you're using Swift 2 or 3:
let x: Int? = Int(myString)
Check the Below Answer:
let x : Int = 45
var stringValue = "\(x)"
print(stringValue)
Here are 4 methods:
var x = 34
var s = String(x)
var ss = "\(x)"
var sss = toString(x)
var ssss = x.description
I can imagine that some people will have an issue with ss. But if you were looking to build a string containing other content then why not.
In Swift 3.0:
var value: Int = 10
var string = String(describing: value)
Swift 4:
let x:Int = 45
let str:String = String(describing: x)
Developer.Apple.com > String > init(describing:)
The String(describing:) initializer is the preferred way to convert an instance of any type to a string.
Custom String Convertible
Just for completeness, you can also use:
let x = 10.description
or any other value that supports a description.
Swift 4:
Trying to show the value in label without Optional() word.
here x is a Int value using.
let str:String = String(x ?? 0)
To save yourself time and hassle in the future you can make an Int extension. Typically I create a shared code file where I put extensions, enums, and other fun stuff. Here is what the extension code looks like:
extension Int
{
func toString() -> String
{
var myString = String(self)
return myString
}
}
Then later when you want to convert an int to a string you can just do something like:
var myNumber = 0
var myNumberAsString = myNumber.toString()
in swift 3.0 this is how we can convert Int to String and String to Int
//convert Integer to String in Swift 3.0
let theIntegerValue :Int = 123 // this can be var also
let theStringValue :String = String(theIntegerValue)
//convert String to Integere in Swift 3.0
let stringValue : String = "123"
let integerValue : Int = Int(stringValue)!
for whatever reason the accepted answer did not work for me. I went with this approach:
var myInt:Int = 10
var myString:String = toString(myInt)
Multiple ways to do this :
var str1:String="\(23)"
var str2:String=String(format:"%d",234)
let intAsString = 45.description // "45"
let stringAsInt = Int("45") // 45
Swift 2:
var num1 = 4
var numString = "56"
var sum2 = String(num1) + numString
var sum3 = Int(numString)
Swift String performance
A little bit about performance
UI Testing Bundle on iPhone 7(real device) with iOS 14
let i = 0
lt result1 = String(i) //0.56s 5890kB
lt result2 = "\(i)" //0.624s 5900kB
lt result3 = i.description //0.758s 5890kB
import XCTest
class ConvertIntToStringTests: XCTestCase {
let count = 1_000_000
func measureFunction(_ block: () -> Void) {
let metrics: [XCTMetric] = [
XCTClockMetric(),
XCTMemoryMetric()
]
let measureOptions = XCTMeasureOptions.default
measureOptions.iterationCount = 5
measure(metrics: metrics, options: measureOptions) {
block()
}
}
func testIntToStringConstructor() {
var result = ""
measureFunction {
for i in 0...count {
result += String(i)
}
}
}
func testIntToStringInterpolation() {
var result = ""
measureFunction {
for i in 0...count {
result += "\(i)"
}
}
}
func testIntToStringDescription() {
var result = ""
measureFunction {
for i in 0...count {
result += i.description
}
}
}
}
iam using this simple approach
String to Int:
var a = Int()
var string1 = String("1")
a = string1.toInt()
and from Int to String:
var a = Int()
a = 1
var string1 = String()
string1= "\(a)"
Convert Unicode Int to String
For those who want to convert an Int to a Unicode string, you can do the following:
let myInteger: Int = 97
// convert Int to a valid UnicodeScalar
guard let myUnicodeScalar = UnicodeScalar(myInteger) else {
return ""
}
// convert UnicodeScalar to String
let myString = String(myUnicodeScalar)
// results
print(myString) // a
Or alternatively:
let myInteger: Int = 97
if let myUnicodeScalar = UnicodeScalar(myInteger) {
let myString = String(myUnicodeScalar)
}
I prefer using String Interpolation
let x = 45
let string = "\(x)"
Each object has some string representation. This makes things simpler. For example if you need to create some String with multiple values. You can also do any math in it or use some conditions
let text = "\(count) \(count > 1 ? "items" : "item") in the cart. Sum: $\(sum + shippingPrice)"
exampleLabel.text = String(yourInt)
To convert String into Int
var numberA = Int("10")
Print(numberA) // It will print 10
To covert Int into String
var numberA = 10
1st way)
print("numberA is \(numberA)") // It will print 10
2nd way)
var strSomeNumber = String(numberA)
or
var strSomeNumber = "\(numberA)"
let a =123456888
var str = String(a)
OR
var str = a as! String
In swift 3.0, you may change integer to string as given below
let a:String = String(stringInterpolationSegment: 15)
Another way is
let number: Int = 15
let _numberInStringFormate: String = String(number)
//or any integer number in place of 15
If you like swift extension, you can add following code
extension Int
{
var string:String {
get {
return String(self)
}
}
}
then, you can get string by the method you just added
var x = 1234
var s = x.string
let Str = "12"
let num: Int = 0
num = Int (str)

Failed to create NSDictionary when reading from plist in swift 2

I am trying to read info from plist, (PetList.plist) but I don't know why it failed. The variable path is correct, however myDict is nil, the else part is executed. What I want to do is load info form plist, then assign values to pets array.
var pets = Pet
func loadGameData() {
let path = NSBundle.mainBundle().pathForResource("PetList", ofType: "plist")
let myDict = NSDictionary(contentsOfFile: path!)
if let dict = myDict {
//loading values
for i in 0..<pets.count {
pets[i].petName = dict.objectForKey("petName")!.absoluteString!
pets[i].health = dict.objectForKey("health")!.absoluteString!
pets[i].experience = dict.objectForKey("experience")!.absoluteString!
pets[i].hungry = dict.objectForKey("hungry")!.absoluteString!
pets[i].energy = dict.objectForKey("energy")!.absoluteString!
pets[i].level = dict.objectForKey("level")!.absoluteString!
pets[i].status = dict.objectForKey("status")!.absoluteString!
pets[i].searchKey = dict.objectForKey("searchKey")!.absoluteString!
pets[i].cleanliness = dict.objectForKey("cleanliness")!.absoluteString!
pets[i].isChoosed = dict.objectForKey("isChoosed")!.absoluteString!
pets[i].skill = dict.objectForKey("skill")!.absoluteString!
pets[i].imageName = dict.objectForKey("imageName")!.absoluteString!
}
} else {
print("WARNING: Couldn't create dictionary from PetList.plist! Default values will be used!")
}
}
There are a few issues.
The top level object is an array
absoluteString will cause an compiler error.
There must be a Pet struct or class to create instances from the array.
Something like this
struct Pet {
var petName = "", health = "", experience = "", hungry = ""
var energy = "", level = "", status = "", searchKey = ""
var cleanliness = "", isChoosed = "", skill = "", imageName = ""
}
var pets = [Pet]()
func loadGameData() {
let path = NSBundle.mainBundle().pathForResource("PetList", ofType: "plist")
if let myArray = NSArray(contentsOfFile: path!) as? [[String:String]] {
//loading values
for anItem in myArray {
var pet = Pet()
pet.petName = anItem["petName"]!
pet.health = anItem["health"]!
pet.experience = anItem["experience"]!
pet.hungry = anItem["hungry"]!
pet.energy = anItem["energy"]!
pet.level = anItem["level"]!
pet.status = anItem["status"]!
pet.searchKey = anItem["searchKey"]!
pet.cleanliness = anItem["cleanliness"]!
pet.isChoosed = anItem["isChoosed"]!
pet.skill = anItem["skill"]!
pet.imageName = anItem["imageName"]!
pets.append(pet)
}
} else {
print("WARNING: Couldn't create array from PetList.plist! Default values will be used!")
}
}
The top-level node of PetList.plist is an array, not a dictionary, which is why it's not loading.

SWIFT : Basic Loops and Arrays

Can I put this in a loop instead of having to manually code it in for each chapter?
var chp1 = Array(Chapters[0].componentsSeparatedByString("\n"))
var chp2 = Array(Chapters[1].componentsSeparatedByString("\n"))
var chp3 = Array(Chapters[2].componentsSeparatedByString("\n"))
var chp4 = Array(Chapters[3].componentsSeparatedByString("\n"))
var chp5 = Array(Chapters[4].componentsSeparatedByString("\n"))
var chp6 = Array(Chapters[5].componentsSeparatedByString("\n"))
var chp7 = Array(Chapters[6].componentsSeparatedByString("\n"))
var chp8 = Array(Chapters[7].componentsSeparatedByString("\n"))
Yes you can use
var chp = []
for chapter in Chapters
{
chp.append(chapter.componentsSeparatedByString("\n")))
}
now you can access to the chapters like
chp[0]
chp[1]
chp[2]
Also you don't need to cast return value to Array.
for range in 0...8 {
var chp = Chapters[range]
let result = chp.componentsSeparatedByString("\n"))
}
Or
for (_, chapter) in Chapters.enumerate() {
let result = chapter.componentsSeparatedByString("\n"))
}

Resources