i'm starting with Swift by developing a simple application with a tableView, a request to a server and a few things more. I realized that every method inside UITableViewDelegate protocol is named in the same way (i guess it might be the same with other protocols) and the differences are made by changing the parameters passed to those methods (which are called "tableView" by the way).
I was wondering why Apple would do something like this, as it's a bit messy when i try to implement method from this protocol, as i can't start typing "didSele..." just to autocomplete with "didSelectRowAtIndexPath"; instead i have to type "tableView" to get a list of all available methods and manually search for the one whose second parameter is "didSelectRowAtIndexPath".
Everything's working fine, but just trying to know WHY could this be done this way.
Thank you so much in advice :)
PS: There's a screenshot about what i'm saying:
Swift is designed to be compatible with Objective-C. After all, almost all existing OS X and iOS APIs are in Objective-C and C (with a bit of C++ code here and there). Swift needs to be able to use those APIs and thus support most Objective-C features one way or the other. One of the most important features of Objective-C is how method calls are made.
For example, in C, a function with 3 arguments is called like this:
foo(1, "bar", 3);
You don't know what the arguments are supposed to be. So in Objective-C, the arguments are interleaved with the method name. For example, a method's name might be fooWithNumber:someString:anotherNumber: and it would be called like:
[anObject fooWithNumber:1 someString:#"bar" anotherNumber:3];
Swift now tries to be compatible with this Objective-C feature. It thus supports a form of named arguments. The call in Swift would look like:
anObject.foo(number:1, someString:#"bar", anotherNumber:3)
Often Swift method definitions are written so that you don't need to explicitly name the first argument, like:
anObject.foo(1, someString:#"bar", anotherNumber:3)
If you look up the UITableViewDelegate protocol documentation and select Objective-C you can see that all of these methods start with tableView: to designate the sender, but from then on they are very different. The list you've cited is the result of the conversion from Objective-C to Swift naming convention.
It is just naming conventions. It is the same in Objective-C. You can have a look to this page. Without these conventions it would be a complete mess.
The method name is not only the first word but also the public names of the parameters.
E.g. it the method name is not tableView() but tableView(_:didSelectRowAtIndexPath:).
Related
Many CocoaPod and native iOS libraries use protocols that they name either CustomClassDelegate or CustomClassDataSource as a means to do some setup or customization. I was wondering when I should use this programming model, because it seems like I could accomplish much of this with properties.
Example
If I define a custom class called SmurfViewController that has a SmurfLabel, is it better practice to store the smurfLabel as a private property and have a public computed property called smurf that looks like this:
private var smurfLabel = UILabel()
public var smurf: String {
get {
return smurfLabel.text
}
set(text) {
smurfLabel.text = text
}
}
or should I define a SmurfDataSource that has a public function that looks like this:
func textForSmurfLabel() -> String {
return "smurfText"
}
When should I use what here?
You should just use a property for that. Delegates and Datasources are for different controllers/Objects to speak to one another when the alternative is to instantiate the controller/object from the navigationStack/view hierarchy. A Delegate forms a specific communication between the two that allows for clear knowledge in what their relationship is while keeping them decoupled (assuming you try to keep it that way). I disagree with the article that says callbacks are "better". They are amazing and I advise using them often, but just understand that most options that swift provides you with have a place where they work best.
I might be slightly bias, but Swift is an amazing language with OOP being a backbone and everything it has was well put together in order to provide the correct tools for each situation you find yourself in.
I often find myself using both of those tools and one other more customizable option in my more advanced setups where I have an overseeing viewController that manages many child controllers. It has direct access to all of them that are active but if any of its children communicate with it, it is through delegates. Its main job is just to handle their place on the screen though, so I keep everything manageable.
Delegates and data sources are more appropriate for offloading behaviors to other entities, not simple values. In other words, if your type just needs a value for something, you are correct that it makes more sense to expose that as a property that can be set from the client code.
But what should happen (for example) when a user taps a specific table view cell is a behavior that shouldn't be hard coded into UITableView. Instead, for flexibility, any implementation of that behavior can be created in a delegate and called by the UITableView when appropriate.
In general, think of delegation as a way to make subclassing unnecessary, because the methods you would normally override in a subclass are instead moved into a protocol that can be implemented by ANY type, not just a subclass of the base type. And instead of calling internally implemented methods to get certain behaviors, your type is simply calling those behaviors on an external collaborating class (the delegate).
So perhaps the best guideline for when to use a data source or delegate is the question: "Would I need to subclass this class in order to change this value or behavior in the future". If the answer is no, because you can just set a property from client code, then don't use delegation. If the answer is yes, then offload that behavior to a delegate or data source instead of forcing future programmers to subclass your class to make it work for their use case.
Delegate is an interface for the undefined activities.
so when you make a SDK or framework, you must provide an interface so that users can write a proper code for the interfaces' expecting activity.
i.e, Table View needs a datasource to show it's contents, but the apple's library developers doesn't know the content whatever contents their library users will use. so they provided an interface like datasource, delegate.
and in the library, they just call this methods. that's the way the library should be made.
But in your code, the label is defined very explicitly as well as it's in the current view, and you don't need to make an interface for an undefined activity.
if you want know more about this kind of coding style, you need to do some researches on Software Design Pattern.
https://en.wikipedia.org/wiki/Observer_pattern
https://en.wikipedia.org/wiki/Delegation_pattern
https://en.wikipedia.org/wiki/Software_design_pattern
I love apple's sdk very much, because they used all the needed design patterns very properly.
I would like to Verify that an expected method is called with the correct parameters in Swift in unit-testing. This was very easily done in Objective-C using the OCMock framework. You could do a combination of partialMocking and running OCMExpect/Verify to assert code paths with the right parameters were being called. Any idea how to do something like this in Swift?
Swift doesn't support reflection, so traditional mocking libraries aren't feasible. Instead, you need to create your own mock. There are at least two approaches to do this.
Create a testing subclass of the class under test. This is partial mocking. Avoid this if possible.
Use an interface instead of a class. Create a testing implementation of the interface.
Hand-crafted mocks aren't hard. You want to
Count the number of calls to a method
Capture its arguments
Simulate its return value
It is a lot of boilerplate. There are libraries out there that can auto-generate this code.
When using Swift, up to now, I am always dealing with classes and their methods.
Is it also possible to have plain functions outside of any class, and group them together in a file MyFunctions.swift?
I would be surprised if the answer was not YES.
But since what I tried failed, I would like to know how I can refer to this file and its functions when I need it.
import MyFunctions.swift did not work.
I'm a bit confused with Apple documentation relating to the explanation of whether to use prefix for methods or not?
Apple Doc Explanation 1:
Use prefixes when naming classes, protocols, functions, constants, and typedef structures. Do not use prefixes when naming methods; methods exist in a name space created by the class that defines them. Also, don’t use prefixes for naming the fields of a structure
Apple Doc Explanation 2:
If you are subclassing a large Cocoa framework class (such as NSView or UIView) and you want to be absolutely sure that your private methods have names different from those in the superclass, you can add your own prefix to your private methods. The prefix should be as unique as possible, perhaps one based on your company or project and of the form "XX_". So if your project is called Byte Flogger, the prefix might be BF_addObject:
For Classes which contains project related storylines/stuffs, there prefixes are not required.
But if we are using Apple Classes by extending few methods as given in example, like UIView to MBView then we should add prefix to methods to private methods in private category ( in .m file).
This is because ObjC does not support namespaces. Instead you should you capital letter prefixes(as you properly read in documentation). You could read this SO discussion why to use them.
Note that Apple uses two-letter prefixes(UI(View), NS(String), etc.) and advises programmers to use 3 letter prefixes.
I think you should use a prefix when you can, it can become a good practice and you can identify, by the name which part of your big software you're playing with.
Let's say your program name is Byte Flogger, then all your classes should start with :
BF prefix. BFBaseList for exemple, and if you want to prevent rejections when submitting your app to the AppStore, it's also a good practice to name your methods bfMyMethodName so that you still respect CamLCase naming conventions.
So for an image, you could name a property bfContentMode without being suspected by Apple to use one private API feature.
Now, let's say you handle some modules, a core module, a network module, etc...
If your class name is BFCObject, you could know that you're working with a Core object of your program.
So it is not necessary, but not doing it could force you to refactor your code in the last moment of submission. In a time driven project, I wouldn't even take that risk.
an Objective-C method has params, and each param except the first one has two names:call name and var name, for example:
-SomeMessage:(type)varName callName2:(type)varName2
so, what's the use of callName ? why we need two names for an param?
Let's have a better method example:
- dataForKey:(NSString *)key withEncoding:(NSString *)encoding;
The first name, how you call it, is actually part of the method name, the whole method name is:
- dataForKey:withEncoding:
(including the colons).
Obj-C prefers method names that can be read like sentences. This is useful in context of the caller. In languages like Java or C++ the method would be called like this
data = object.getData("key", "ASCII")
which is difficult to understand for the readers because they doesn't know what the parameters stand for. In Obj-C
data = [object dataForKey:#"key" withEncoding:#"ASCII"];
is easy to understand without looking at the method declaration.
Its to make your code more readable, each "call name" is a description of a parameter
so instead of C style having myMethod(5, 4, 9, 2)
you would have [self myMethodWithParam:5 andACoolNumber:4 thisShouldBeNine:9 divisor:2];
which just helps you understand what the functions parameters need to be, its optional, but you should always do it to help with code maintainability
This is how it works what you wrote is correct "Somemessage" and "callName2" are part of the method name while varName and varName2 are variables .
callname2 is optional , generally it is used if we want to give any definition for the variable we writes after that
Hope this helped you.