How do I resolve this build issue - cannot assign to property: 'date' is a get only property
Your date is actually a computed property
that only has a getter
So it can only be read, not written too.
In contrast your FullDate
is a stored property
.
computed properties
are often used to hide functionality from other classes or expose buried data in a convenient way.
Below there is some illustration in the SomeClass
object.
stored properties
are just regular old propertiescomputed properties
aregetters
and maybe alsosetters
. A good example isheight
andwidth
ofCGRect
, these are actually fromCGRect.size
but are implemented asconvenience getters
property observers
are functions executed whenstored properties
change value.didSet
andwillSet
access control
onget
andset
allows you to createstored properties
that are read or write only depending on access.
class SomeClass {
// just a variable
var storedProperty : Int = 10
// just a variable but the setter is hidden from other "files"
private(set) var storedPropertyWithPartialAccessControl : Int = 0
// only calculates when set
var derivedProperty : Int = 0 {
didSet {
storedProperty = doStuffs(derivedProperty)
}
}
// calculates every get and set
var computedProperty : Int {
get { // get is needed
return doStuffs(storedProperty)
}
set(value) { // set is not needed, using only get gives you a read only property
storedProperty = doReverseStuffs(value)
}
}
// hidden functions that are used in the computed property
private func doStuffs(value:Int) -> Int {
return value * 10
}
private func doReverseStuffs(value:Int) -> Int {
return value / 10
}
}
Because NSDateFormatter
is very inefficient, it is very bad to use it in a computed property
. One will be created every get. A lot of time and energy will be wasted because the resulting value might be the same most of the time.
Best practice :
- Use
computed properties
toget
stored properties
andset
to do calculations. - Use a Singleton to store the
NSDateFormatter
A much much better way to go:
class SomeEvent {
// Store calculated results.
// This is private to make the class cleaner in use.
private var storedDate : NSDate?
private var storedFormattedDate : String = ""
// get returns stored values without calculations
// set updates both stored values after calculations
var date : NSDate? {
get {
return storedDate
}
set(value) {
storedFormattedDate = format(date: value)
storedDate = value
}
}
var formattedDate : String {
get {
return storedFormattedDate
}
set(value) {
storedDate = readDateFrom(dateString: value)
storedFormattedDate = format(date: storedDate)
}
}
// hidden functions, again to make the class cleaner in use.
private func format(date maybeDate:NSDate?) -> String {
guard let date = maybeDate else {
return ""
}
guard let dateFormatter = MyDateFormatter.shared().dateFormatter else {
return ""
}
return dateFormatter.stringFromDate(date)
}
private func readDateFrom(dateString string:String) -> NSDate? {
// get detector
if let detector = MyDateFormatter.shared().dateReader {
// results
let matches = detector.matchesInString(string, options: [], range: NSRange(location: 0, length: string.characters.count))
// first result
if let match = matches.first, let date = match.date {
return date
}
}
// just format if there is no detector
if let dateFormatter = MyDateFormatter.shared().dateFormatter {
if let date = dateFormatter.dateFromString(string) {
return date
}
}
// everything failed
return nil
}
}
Singleton to store the NSDateFormatter
and NSDataDetector
:
Google: Swift Singleton
class MyDateFormatter {
private static var privateShared : MyDateFormatter?
var dateFormatter : NSDateFormatter?
var dateReader : NSDataDetector?
class func shared() -> MyDateFormatter {
guard let uwShared = privateShared else {
privateShared = MyDateFormatter()
return privateShared!
}
return uwShared
}
class func destroy() {
privateShared = nil
}
private init() {
dateReader = try? NSDataDetector(types: NSTextCheckingType.Date.rawValue)
dateFormatter = NSDateFormatter()
dateFormatter!.dateFormat = "EEEE MMM dd"
}
}
Tests:
let event = SomeEvent()
event.formattedDate = "tomorrow"
event.formattedDate // "Friday Dec 04"
event.formattedDate = "25/02/2010"
event.formattedDate // "Thursday Feb 25"
event.formattedDate = "Sunday Mar 13"
event.formattedDate // "Sunday Mar 13"
Cannot assign to property: 'xxxx' is a get-only property
The error occurs because you did not tell the compiler what to do if the value of currentBook
is mutated. The compiler assumes it is immutable.
Just add a setter so that the compiler knows what to do when you set the value:
var currentBook: Book {
get { return books[books.count - 1] }
set { books[books.count - 1] = newValue }
}
Or, consider using books.last!
:
books.last!.position = CGPoint.zero
Cannot assign to property: 'selectedDealClosingDate' is a get-only property - SwiftUI
Think about what happens when the user changes the selection using the date picker - you would want selectedDealClosingDate
to be set to the newly selected value, don't you? But look at the way you have declared selectedDealClosingDate
! You've only defined how to compute its value, but not how to set its value.
var selectedDealClosingDate: Date {
var dealClosingDate = deal.dealClosingDate
dateFormatter.dateFormat = "dd/MM/YY"
return dateFormatter.date(from: dealClosingDate) ?? Date.now
}
You should add a setter:
var dateFormatter = {
let formatter = DateFormatter()
formatter = .dateFormat = "dd/MM/yy"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}()
var selectedDealClosingDate: Date {
get {
var dealClosingDate = deal.dealClosingDate
return dateFormatter.date(from: dealClosingDate) ?? Date.now
}
set {
deal.dealClosingDate = dateFormatter.string(from: newValue)
}
}
Also, I find it a bit weird that you are storing a deal closing date in Core Data as a string. You might want to reconsider that.
Cannot assign to property: 'outputs' is a get-only property
The issue is that ViewModelOutputsType
can either be a value or reference type. If it is a value type, then mutating any of its properties mutates the instance itself. You can resolve the issue by making the protocol class constrained and hence guaranteeing it to be a reference type.
protocol ViewModelOutputsType: class {
var didReceiveServiceError: ((Error) -> Void) { get set }
var reloadData: (() -> Void) { get set }
}
Cannot assign to property: 'b0' is a get-only property
Here's my first attempt at a fix. The extension currently only has a getter, so we'll edit that extension to replace the lines to something like this:
var b0 : Bool {
get {return ((self & 0x1) == 0) ? false : true}
set {self = newValue ? self & 0x1 : self ^ 0x1}
}
var b1 : Bool {
get {return ((self & 0x2) == 0) ? false : true}
set {self = newValue ? self | 0x2 : self ^ 0x2}
}
Hopefully I got the bitset stuff right (it's not my strong suit).
how to assign value to a get-only property
You have two problems.
First, as you have discovered, you can't modify vote
because it is a computed property. Its value is determined by the code in its getter method. Assigning a value doesn't make sense.
I guess you have used a computed property because your JSON source is, frankly, awful. Integers should be sent as integers, not strings.
Assuming you can't change the JSON to something more sensible, then you will just need to update the underlying DOUBAN_VOTES
property in your upVote
function. You will need to make DOUBAN_VOTES
a var
, not a let
.
This will reveal your second problem; Structs are immutable. In order to allow a function to change a value, it must be flagged as a mutating
function.
var DOUBAN_VOTES:String
mutating func upVote(newVote: Int) {
self.DOUBAN_VOTES = "\(newVote)"
}
Swift error saying it cannot assign to property due to it being a 'let' constant
You are accessing the local variable captureDevice
, not the struct's captureDevice
variable.
Just replace the line causing the error to the following:
self.captureDevice?.exposureMode = .continuousAutoExposure
Note the self.
before captureDevice
.
You might think of changing the conditional binding to using var
instead of let
, but that won't actually work. This is because you are just mutating a local copy. It will fix the compile error but the logic won't work.
Cannot assign to property: 'desc' is a 'let' constant
class infoViewController: UIViewController {
var result:Data1!
override func viewDidLoad() {
saveToJsonFile(result2 : &result!)
}
func saveToJsonFile(result2 : inout Data1) {
result2.data[1].monday[1].desc = "cos"
}
}
struct Data1{
var data: [Monday]
}
struct Monday {
var monday: [Desc]
}
struct Desc{
let desc: String
}
If you try as above you will get "Cannot assign to property: 'desc' is a 'let' constant" error.
So you need to change the let into var, because let is immutable.
class infoViewController: UIViewController {
var result:Data1!
override func viewDidLoad() {
saveToJsonFile(result2 : &result!)
}
func saveToJsonFile(result2 : inout Data1) {
result2.data[1].monday[1].desc = "cos"
}
}
struct Data1{
var data: [Monday]
}
struct Monday {
var monday: [Desc]
}
struct Desc{
var desc: String
}
Related Topics
In Swift, Does Resetting the Property Inside Didset Trigger Another Didset
Difference Between Awakefromnib() and Viewdidload() in Swift
Aws S3 Transfer Manager ${Cognito-Identity.Amazonaws.Com:Sub} Policy Variable Access Denied
Cannot Read the Nfc Chip of the Epassport Using iOS13
What Is the Usecase for Ignored Parameters in Swift
Calling a Global Function Which Has the Same Name as a Member Function
Dispatchqueue.Main.Asyncafter Is Inaccurate
Error: Bool Is Not Convertible to Void:
Can't Use Concrete Subclass to Implement a Property in Protocol in Swift
Clearing Uiwebview's Cache in Swift
Alternate Approach to Inheritance for Swift Structs
Key-Value Coding (Kvc) with Array/Dictionary in Swift
What Is an Example of Drawing Custom Nodes with Vertices in Swift Scenekit