Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I'm new to Swift and iOS and I'm trying to figure out what is the recommended approach for setting and getting values. I've noticed that in the build in classes there is a lot of direct access compared to Android (where I come from). So what does iOS veterans do and why? And is there some kind of recommended approach?
In spite of being syntactically identical, accessing Swift properties is not the same as accessing Java variables, When you expose a variable in Java, like this
class MyClass {
public int val = 123;
}
you have no way of protecting it at some later time without breaking everyone else's code that reads and writes c.val variable.
Swift properties, on the other hand, let you add custom getters and setters to something that looks like a variable at the beginning:
class MyClass {
public var val = 123
}
If you decide that you want a setter later, you can change this to
class MyClass {
private var _val = 123
public var val : Int {
get {
return _val
}
set (newVal) {
precondition(newVal >= 0, "Negative values are not allowed")
_val = newVal
}
}
}
This is because when you write c.val = -321 Swift executes the code of the setter, i.e. what looks like a direct access is actually a method call.
What looks like an assignment is actually a setter, and what looks like reading a member is actually a getter. The class usually has a primitive setter that just assigns or reads values, but that can be overridden with any code you want. In addition, there are didSet / willSet where the class can add code to react to changes.
You never write code that looks like you are calling a setter or getter, but you are actually calling them.
If you find that you are executing a lot of code when a getter or setter is called, which would be unexpected to a caller, you use a function instead.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
My architecture is as follows:
We create a singleton BusinessLogic instance which contains several categories, represented by classes defined in extensions.
class BusinessLogic {
static let shared = BusinessLogic()
private(set) var foo: FooCategory = FooCategory()
}
In a different file we define the category.
extension BusinessLogic {
class FooCategory {
var hasNewItems: Bool = false
}
}
In reality the class is much bigger, but these are the relevant parts.
From my view controllers I access the properties like
BusinessLogic.shared.foo.hasNewItems
This is done throughout the app, and usually works without problems. In this example though, we access the hasNewItems property on viewDidLoad of our UITabBarController, which sometimes leads to crashes. This is unexplainable to me.
Does anyone have an idea what might lead to the crash? We access the BusinessLogic class even on appStart inside the AppDelegate, where everything works fine.
It seems like one property was in fact nil (as #Rishabh suggested). I don't think posting the whole solution is of any use for you, since it's very specific to my app.
This question already has answers here:
Computed read-only property vs function in Swift
(11 answers)
Closed 6 years ago.
In swift I can create a method like -
#1
func baseURL() -> String {
#if DEBUG
return "https://debug.myserver.url.com"
#else
return "https://production.myserver.url.com"
#endif
}
I can also write it in this way -
#2
var baseURL:String {
#if DEBUG
return "https://debug.myserver.url.com"
#else
return "https://production.myserver.url.com"
#endif
}
The requirement of declaring a get only property is met by both methods. Personally I find the second method better cos of readablility.
I know its not too much of a difference, but I'd still like to know which one is better? Does either method have any advantage over the other?
Does either method have any advantage over the other?
Not internally, no. A computed property is a function, so there is no difference in implementation under the hood.
If you are simply getting a value with minimal computation, such as your example, then a getter is a good option.
If getting the value could do some heavy computation or modifies any members on the class, then a function is preferable.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
This is a basic question about the best practice in swift to declare a swift class with instance variable, all the values will be received from Firebase callback. What is the best approach among these choices or let me know if there another better way:
Solution 1:
class User: NSObject {
var name:String = ""
override init() {
super.init()
}
}
Solution 2:
class User: NSObject {
var name:String!
override init() {
super.init()
}
}
Solution 3:
class User: NSObject {
var name:String?
override init() {
super.init()
}
}
Solution 4:
class User: NSObject {
var name:String
override init() {
super.init()
// Now I need to init name variable here
}
}
Using implicitly unwrapped optionals is almost never a good idea. You should be thinking like this: If you are sure that you will always have name of the User you should initialize object with name string like this:
class User: NSObject {
let name: String
init(name: String) {
self.name = name
super.init()
}
}
If you are not sure that you will get name in the callback use optional string property:
class User: NSObject {
var name: String?
}
This will enable you to use if let to check if name has a value.
If you use String!, your application will almost certainly crash at one point because you accessed nil.
var name: String = "" is also misleading because you would have to implement checking if string is empty or contains name.
using something like
var name:String = ""
Is saying that you have the variable name that will be initialized to "" for all objects
var name:String?
Is saying that you know for a fact that the variable name will be in this object and that this name property can contain the value nil. Acknowledging its existence this way means you must initialize it before you use it. This gives you a bit more control. In most cases just having something like
String name;
In other languages means that if you were to use name without explicitly initializing it then you'll get an empty string. That's not the case here. With ? you're saying that this property name definitely exists for all objects but it may or may not contain data, but since you explicitly created it using ? then you know for a fact that at some point it should contain data.
var name:String!
This is kinda like var name:String = "" at the top of the file. With ! you're saying that the moment you create an object you'll be able to use the name property because it's already been initialized. That's why IBOutlets have ! and not ?. The reason is because it's already been set up for you. It's initialized before you use it
The confusion between ? and ! come from not using them correctly. If you have total control of the project and you know when things are coming in and out of use and you're in control of when things are being created then it may be best to use !. In a perfectly controlled self-contained environment you'd want to use ! because it'll be like the programming you're used to
But what if you start adding in interactions between view controllers that are conditional, and you know that at some point you're going to need a name property but you just don't know exactly when? Well you may say:
"Hey I could just use ! and check to see if it contains "" or not"
and that could work and it'd be just fine but that takes up space if you go through the entire app without actually using that property in that instance. You're basically programming for all situations when most views are conditional.
That's why you'd go for ?. ? is saying that you need this property. You may not know when exactly but it definitely has a purpose. And you can still write logic with this property even if it doesn't exist because it allows you to check existence without checking for data. This fact is what makes optionals so great because when you compile your app, Xcode will be able to comb through it and see the optional flag. It'll then begin to handle the optional. This is important because what does
var name:String
Tell you about name? Has it been initialized? Will it be?
So then what would
print(name)
Mean to the compiler when it runs? Well, you won't know until you actually run it. This is an issue, but
print(name!)
Forces an unwrap of the optional var name:String?. This allows the compiler to prevent runtime errors because someone created a property that turned out to be optional.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
When I was learning other languages such as Java, all the sample code tells you that you should always mark a field private. And the methods that do the internal stuff are also marked private or protected.
But when it comes to Swift, I see that the sample code from a lot of the tutorials (such as raywenderlich.com) seldom marks something as private. They just leave it internal (without adding any modifiers).
In contrast, all the android tutorials mark some of the fields as private and provide no getters or setters for them.
For example, I read this search bar tutorial a while ago:
https://www.raywenderlich.com/113772/uisearchcontroller-tutorial
When I was reading through it, I was thinking about: "Why did you not mark this private?"
let searchController = UISearchController(searchResultsController: nil)
I mean, it does not make sense for other classes to access the search controller of my VC. It's mine!
Question:
Why don't most, if not all tutorials provide sample code that contains private properties? Is it because iOS is more secure or something? Should I mark suitable stuff as private in production code?
I hope this is not too opinion based. In Java, you will never make a field public, right? That's just a fact - you should not make fields public. So please don't close as opinion based, it's not.
Why not everything private? There are several really common scenarios that I've seen that always favor having the variable either internal or public.
Delegate methods:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(
myCellID,
forIndexPath: indexPath);
return cell;
}
This method will be called not internally by you, but rather by the iOS system that manages and displays the tableView. The delegation pattern is widely used within iOS development.
Data exchange between two ViewControllers, where you simply want to set the other ViewController's field:
class MyVC1: UIViewController {
var flagShouldUpateColors = false {
didSet{
// some stuff
}
}
}
Then at some point you want to notifiy this ViewController that the flag should be set to true. You do that my simply acccessing it's field.
Also selectors. When I register an instance of a ViewController for some notification, I pass the name of a method that I have within the very same ViewController. It is to be called when the notification triggers. Basically what the code says is "please call this method for me when this occurs". If you say call this private method when this occurs, it wouldn't make sense would it ? How is the caller supposed to call it(aside from reflection and other unoptimized ways). Here is example:
override func viewDidLoad() {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(self.doStuffWhenEnterForeground),
name: UIApplicationWillEnterForegroundNotification,
object: app)
doStuffWhenEnterForeground();
}
func doStuffWhenEnterForeground() {
}
Main difference between Java and Swift is in properties.
Java has no concept of properties. It has fields and if you want to allow public access to those fields you can either access them directly or through getter/setter methods.
If you create public field that needs to be protected later on you will have to use methods and thus your public API will be changed - fields are accessed without parens and methods with them.
Swift is different in that regard. You can protect your field access with getter/setter at any point without changing API. So if you have field that is part of public API you can just leave it as is (without making it private) and without having getter/setter methods attached to it.
Encapsulation in Java and Swift are of the same importance. What differs is how it is achieved (implemented). Since there is no pressure for premature encapsulation in Swift and it is only matter of adding visibility specifier when appropriate there is some lack of discipline in adding those in tutorial code where main purpose is not enforcing encapsulation, but teaching some other concepts and how-to's.
Why don't most, if not all tutorials provide sample code that contains private properties? Is it because iOS is more secure or something? Should I mark suitable stuff as private in production code?
Probably because it's simpler, save few keystrokes and doesn't add unnecessary overhead to understanding the main theme of tutorial.
Should I mark suitable stuff as private in production code?
Yes, you should do it for the same reasons you would do it in Java. Notice 2 things, however:
There is no such thing as protected.
Access modifiers in Swift work differently compared to many other languages. private restricts access to variable or function to file where it was declared, regardless of who will access them. Thus, if you have 2 classes declared in the same file, they both can see private fields of each other. On the other hand, you can't see private fields even from extension of that class if this extension in other file. It looks strange at first and you just need to get used to it.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I need some best pratices advice when checking conditions before running some methods.
Let's consider the following implementation :
#interface Foo : NSObject {
NSObject *_anObject;
}
#end
#implementation Foo
- (id)aMethod
{
if (!_anObject) return nil;
// do something
return obj;
}
- (id)aMethod2
{
if (!_anObject) return nil;
// do something
return obj;
}
Even if this implementation works well, I find pretty ugly to have these redundant checking codes if (!_anObject) return nil;.
So do you have some best pratices to avoid this ? (other than creating a macro to replace the line of code, which is pretty the same ugliness)
Thx in advance for your help.
Hmm, a few thoughts. I think it will depend a lot on what your // do something does.
If this is just a few methods, I think what you are doing is perfectly readable. And I agree a macro would only add confusing when reading the code.
Another thing to remember is in Objective-C you can call methods on a nil object safely, so maybe the check isn't necessary? Or you could try a null object-ish pattern. Usually used to prevent null pointer references which isn't a problem here, but maybe you could have a blank object that returns the correct thing if _anObject that makes sense in aMethod1 and aMethod2.
Another thought, if you are really checking for nil before all of your functions, perhaps you need to move up a level instead? It sounds like to me you have two classes. What about subclassing Foo with NilObjectFoo that just returns nil for all methods (or whatever)? Then when creating Foo, check if you have a _myObject and if you don't, create a NilObjectFoo instead. Then the rest of the code using that object doesn't care, and you are not cluttering up you Foo object with a bunch of nil checks.
Maybe a more concrete example would be helpful?
If I read you correctly (and I might not have), I would think that check of your belongs somewhere else. e. g.:
- (void)fooMethod{
if (_anObject){
// do whatever you need to do to the object, then:
NSObject *foo = [self aMethod];
}
}
- (id)aMethod{
// prepare the object you want
return obj;
}
This seems sturdier as you might need to have the result of aMethod used elsewhere even when _anObject is nil giving each fewer responsibilities. If you want a method to create several objects from different methods all depending on the state of _anObject you only need one outer if rather than the pattern you describe above:
- (void)fooMethod{
if (_anObject){
NSObject *foo = [self aMethod];
NSObject *bar = [self anotherMethod];
}
}