I have something like
#property(nonatomic,retain) UIImageView *whiteBfFillUp;
#end
#synthesize locationManager;
I am new to swift coding. Can anyone tell me the equivalent code in swift.
There is no equivalent.
In Swift when you write a varor let in a class or struct declaration you already declaring a property.
Define properties to store values
This is what is written in Swift documentation.
If you are concerned about access control you can use private or public modifiers.
public var somePublicVariable = 0
If you'd like to override properties such as you did in Objective-C you will find useful properties observers such as didSet{} willSet{}.
If you need a a readonly properties you can make the setter private.
public private(set) var hours = 0
If you are only looking for equivalent of property, then you just need to create your class level variables. All class level variables are by default 'strong' or 'retain'. If, however, you want them to be weak then use weak.
This would be something like
var whiteBfFillUp: UIImageView? = nil
The ? at the end means that this is an optional type. If it's not, you would need to assign it some value in the init method, or right there.
Related
I'm building an app in Swift, and I have a a view controller which I am going to use in 2 places to display very similar screens but with some minor differences.
I have a protocol called myProtocol, and I've a view controller with a property called viewModel which adheres to this protocol. The viewModel can be an instance of aViewModel or bViewModel, but they both have the same methods from the protocol, but return different values depending on where the view controller is used.
Now, in objective-c I can do
#property (nonatomic, strong) id <myProtocol>viewModel
and then can set it as viewModel = [aViewmodel new] or viewModel = [bViewmodel new]. How can I achieve something similar in swift?
I've tried adding the property as let viewModel: myProtocol? = nil, but this is giving an error saying it can't infer a type. Just wondinerg if you guys could give me some advice. I'm new enough to swift, but have been using Objective-c for a few years
Assuming you are using Swift 3:
protocol MyProtocol {
//...
}
var viewModel:MyProtocol?
class ViewModel: MyProtocol {
//...
}
viewModel = ViewModel()
As a preface, this might be an incredibly simple and/or ignorant question.
In ReactiveCocoa 2.x, we were able to use RACObserve and RAC to observe properties of an object. From the documentation I can find in Reactive 3 and 4, we now use PropertyType to observe changes to an object property. I have so far been unsuccessful in being able to observe any property change when using MutableProperty or DynamicProperty.
class TempObject {
var property: String
}
let tempObject = TempObject()
let propertyObserver: MutableProperty<String> = MutableProperty(tempObject.property)
From what I understand, I should be able to use propertyObserver to view changes to tempObject.property. I tried adding a map function to the signal producer from propertyObserver to see if it was firing, but don't see anything when updating tempObject.property. Again, could be a trivial thing that I am missing, thanks so much.
Edit
NachoSoto nailed it - I needed to make my property KVO compliant. I also ended doing this:
let tempObjectSignal: MutableProperty<TempObject> = MutableProperty(tempObject)
let propertyObserver: MutableProperty<String> <~ tempObjectSignal.producer.map({ $0.property })
And whenever tempObject.property is updated I make sure to call
tempObjectSignal.value = tempObject
This fires off all the necessary signals. I don't know if this breaks any best practices, though. Let me know what you think!
MutableProperty(value) creates a mutable property but only with value that as the initial value.
What you want to use is DynamicProperty, which will use the Objective-C runtime and KVO to detect changes to an object's property:
let property = DynamicProperty(tempObject, "property")
For that reason, however, you need to make sure that the property you want to observe is part of the Objective-C runtime, by making the class a subclass of NSObject, and by either using the dynamic keyword:
class TempObject: NSObject {
dynamic var property: String
}
Or using #objc to ensure that it gets exported to the runtime:
class TempObject: NSObject {
#objc var property: String
}
I'm implementing a protocol from an Obj-C library in a Swift class that defines two properties as:
#property (nonatomic, assign, getter = isLoading) BOOL loading;
#property (nonatomic, readonly) UIExpansionStyle expansionStyle;
Although I'm not sure how to conform to these requirements in my Swift class.
I've looked at the Obj-C examples, but I haven't gleaned any solutions from that. I've tried declaring class variables with the same name, but that hasn't worked. Any suggestions on how I would go about this?
PS, the library in question is https://github.com/OliverLetterer/SLExpandableTableView
I think you're making this harder than it needs to be. With a protocol defined like this:
#protocol MyProtocol
#property (nonatomic, assign, getter = isLoading) BOOL loading;
#property (nonatomic, readonly) UIExpansionStyle expansionStyle;
#end
the following class conforms:
class Conformer : MyProtocol {
var loading: Bool
var expansionStyle: UIExpansionStyle
init(loading: Bool, expansionStyle: UIExpansionStyle) {
self.loading = loading
self.expansionStyle = expansionStyle
}
}
Prefixing boolean getters with is is a Cocoa convention, so Swift already knows about it and doesn't require you to do anything special on the swift side.
The confusing part might be all the modifiers to the Objective C property declaration. Let's go through them one by one.
nonatomic has no equivalent in Swift, nothing to do here.
assign is automatic for value types, nothing to do here either.
getter = isLoading is a Cocoa convention which Swift understands and needs nothing from you in order to make this work.
readonly you can do this in Swift (just use the get{ } syntax) but it is not necessary. This is because you are allowed to expand on the contract made by the protocol. MyProtocol requires there be a property called expansionStyle that can be read from, it does NOT say that it must not be possible to write to that property in the type that implements the protocol, just like it doesn't say you can't have other properties/methods on that same class.
Lance's answer didn't work for me, this is how I got isLoading to conform to the protocol (Swift 2.2)
var expansionStyle: UIExpansionStyle = UIExpansionStyle(0)
var _loading: Bool = false
var loading:Bool {
#objc(isLoading) get {
return self._loading
}
set(newValue){
_loading = newValue
}
}
I'm trying to play a little bit with swift and iOS 8.
The question is, I'm trying to create this setter in a view controller:
- (void)setViewController:(UIViewController *)viewController
{
_viewController = viewController;
method do something
}
This code below is in Objective-C so I'd like to create it in swift.
I think, I should use willSet, but I know how do it if it's defined when you have your own variable, how can I define that willSet method if that property is a ViewController property.
Thanks
Something like this:
var viewController: UIViewController? {
willSet {
//method to do something
}
}
You can actually access what viewController will be set to with the variable "newValue" if you need that in the method call.
Note: I made the property optional here just to get rid of compiler warnings about needing initialization
An alternate way different from #Eric's answer is by using a computed property, which mimics objective-c properties more closely, consisting on defining a pseudo-private data member and a computed property implementing a getter and a setter:
class MyClass {
var _viewController: UIViewController?
var viewController : UIViewController? {
get {
return self._viewController
}
set {
self._viewController = newValue
// Do something else
}
}
}
I defined the property pseudo-private because swift doesn't have access modifiers (yet), so everything is public - but when I see an underscore prefixing a variable or property name, that to me means private (It's a convention I use it a lot in javascript for instance).
I have 2 classes as per below:
Class ModelA.h
#interface ModelA : NSObject
#property (nonatomic, strong) NSArray *arrayA;
#end
Class ControllerA.m
#interface ControllerA()
# property (nonatomic, copy, readonly) ModelA *modelProperty;
#end
#implementation ControllerA
- (void)someMethod:(NSArray *)sampleArray
{
self.modelProperty.arrayA = sampleArray;
}
If I try to assign something to self.modelProperty, I get a build error which says I cannot since its a readonly property. But I assign something to its property it XCode doesn't give any error i.e. self.modelProperty.arrayA = sampleArray just builds fine. However when I debug through it and print self.modelProperty.arrayA I get nil even though sampleArray has data in it.
Question: Is it possible to assign values to a property of a readonly object?
Is it possible to assign values to a property of a readonly object?
Er, sort of. The language you used is slightly confusing. It isn't a readonly object; it's a readonly property. And it is possible to assign values to the object stored in a readonly property.
readonly just means that you can't set that property -- there is no setModelProperty: setter method.
It does not mean that the target of the object is immutable. It's not analogous to const. All it means is that you can't set the property.
The reason you're seeing nil is that any message sent to nil returns nil.
self.modelProperty.arrayA
Is the same as:
[[self modelProperty] arrayA]
If modelProperty is nil (which it is, from the code you've shown), this is the same as:
[nil arrayA]
Which returns nil -- in the same way that [nil anyMethod] returns nil.
Final note: you have copy set as the memory policy for the modelProperty property, but the ModalA class doesn't appear implement the NSCopying protocol. Are you sure you don't want strong?
Try: _modelProperty = sampleArray