This is more of a coding style question but i believe it is valid. Coming from an obj c background i always create a .h and a .m when creating a class. However with swift that changes and all that goes into a single file. I know that for some people this is cool but i miss having these two things separate.
Quoting a comment from Zaph
"What I miss is a list of public methods as opposed to searching an
entire source file for methods not marked private. There is a
programming concept of "writing to the interface". And the public
methods should be carefully picked, not just because the developer
forgot to make some private."
is there a way to have a header - implementation class in separate files using swift? Maybe some trick?
Thanks
May be you can use Generated Interface to view all the public methods and properties. You can find that option at the bottom of related files popup in the upper-left of the source editor window. To switch back, click Original Source in the same pop up.
Shortcut: control + cmd + down arrow
This is how generated interface file looks.
As far as i'm aware, this cannot be done. That being said, if set out your .swift files correctly then they are still very readable. I tend to follow this as a guideline for styling in swift and i find that it breaks things up into readable sections, especially by using // MARK: as well.
In short, no.. But what do you miss..? Once you get used to it, you will probably prefer it like this! The old separation has no clear advantage over this new one!
More and more languages use this approach, as it reduce coupling and errors.
So when you change the signature of a function, to need to check another file to update it, it's only duplication without any added value.
The problem you describe (how to see only "public" functions) is usually done buy tools( IDE) or documentation generators.
You can create 2 swift files:
YourClassNameHeader.swift
class YourClassName {// put here all your properties
}
YourClassNameMethods.swift or YourClassNamePrivate.swift
extension YourClassName { // put here all private methods and
properties }
But in general its not good practise
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.
It's possible to add extensions to existing Swift object types using extensions, as described in the language specification.
As a result, it's possible to create extensions such as:
extension String {
var utf8data:NSData {
return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
}
}
However, what's the best naming practice for Swift source files containing such extensions?
In the past, the convention was to use extendedtype+categoryname.m for the Objective-C
type as discussed in the Objective-C guide. But the Swift example doesn't have a category name, and calling it String.swift doesn't seem appropriate.
So the question is: given the above String extension, what should the swift source file be called?
Most examples I have seen mimic the Objective-C approach. The example extension above would be:
String+UTF8Data.swift
The advantages are that the naming convention makes it easy to understand that it is an extension, and which Class is being extended.
The problem with using Extensions.swift or even StringExtensions.swift is that it's not possible to infer the purpose of the file by its name without looking at its contents.
Using xxxable.swift approach as used by Java works okay for protocols or extensions that only define methods. But again, the example above defines an attribute so that UTF8Dataable.swift doesn't make much grammatical sense.
I prefer having a + to underline the fact it contains extensions :
String+Extensions.swift
And if the file gets too big, you can then split it for each purpose :
String+UTF8Data.swift
String+Encrypt.swift
There is no Swift convention. Keep it simple:
StringExtensions.swift
I create one file for each class I'm extending. If you use a single file for all extensions, it will quickly become a jungle.
I prefer StringExtensions.swift until I added too much things to split the file into something like String+utf8Data.swift and String+Encrypt.swift.
One more thing, to combine similar files into one will make your building more faster. Refer to Optimizing-Swift-Build-Times
Rather than adding my comments all over the place, I'm surfacing them all here in one answer.
Personally, I take a hybrid approach that gives both good usability and clarity, while also not cluttering up the API surface area for the object that I'm extending.
For instance, anything that makes sense to be available to any string would go in StringExtensions.swift such as trimRight() and removeBlankLines().
However, if I had an extension function such as formatAsAccountNumber() it would not go in that file because 'Account Number' is not something that would naturally apply to any/all strings and only makes sense in the context of accounts. In that case, I would create a file called Strings+AccountFormatting.swift or maybe even Strings+CustomFormatting.swift with a formatAsAccountNumber() function if there are several types/ways to actually format it.
Actually, in that last example, I actively dissuade my team from using extensions like that in the first place, and would instead encourage something like AccountNumberFormatter.format(String) instead as that doesn't touch the String API surface area at all, as it shouldn't. The exception would be if you defined that extension in the same file where it's used, but then it wouldn't have it's own filename anyway.
If you have a team-agreed set of common and miscellaneous enhancements, lumping them together as an Extensions.swift works as Keep-It-Simple first level solution. However, as your complexity grows, or the extensions become more involved, a hierarchy is needed to encapsulate the complexity. In such circumstances I recommend the following practice with an example.
I had a class which talks to my back-end, called Server. It started to grow bigger to cover two different target apps. Some people like a large file but just logically split up with extensions. My preference is to keep each file relatively short so I chose the following solution. Server originally conformed to CloudAdapterProtocol and implemented all its methods. What I did was to turn the protocol into a hierarchy, by making it refer to subordinate protocols:
protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
var server: CloudServer {
get set
}
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void)
}
In Server.swift I have
import Foundation
import UIKit
import Alamofire
import AlamofireImage
class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void) {
.
.
}
Server.swift then just implements the core server API for setting the server and getting the API version. The real work is split into two files:
Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift
These implement the respective protocols.
It means you need to have import declarations in the other files (for Alamofire in this example) but its a clean solution in terms of segregating interfaces in my view.
I think this approach works equally well with externally specified classes as well as your own.
Why is this even a debate? Should I put all my sub classes into a file called _Subclasses.swift. I think not. Swift has module based name spacing. To extend a well known Swift class needs a file that is specific to its purpose. I could have a large team that creates a file that is UIViewExtensions.swift that express no purpose and will confuse developers and could be easily duplicated in the project which would not build. The Objective-C naming convention works fine and until Swift has real name spacing, it is the best way to go.
I found the excellent resource of the open source iOS GPX Framework (http://gpxframework.com/) which allows me to create and read GPX files. However I would like to add a custom extension to store data specific to my app. I can see that the GPX framework implements a file GPXExtensions.h and .m, but I am not sure how to go about adding say a tag for storing the speed data at a particular coordinate in the GPX.
I am guessing I would have to add the data I would like to add as an extension to the GPXExtensions class as a property and then somehow modify the code in this method:
- (void)addChildTagToGpx:(NSMutableString *)gpx indentationLevel:(NSInteger)indentationLevel
{
[super addChildTagToGpx:gpx indentationLevel:indentationLevel];
}
But I am not sure what this method is supposed to do, any ideas?
That's basically the right idea. Jaime Machuca's fork contains a commit where he added heart rate, etc. It should give you a pretty good template from which to create your own modifications. Note that if you want something more sophisticated, you may need to create your own subclass of GPXElement so that you can take advantage of the tree structure.
How do you add "objects" to an existing app ?
For example, the EasyRefresh for Chrome tweak, enables a new button inside the iOS Chrome app, as do many other tweaks.
How may i add a simple UIButton to, for example, the Twitter app ?
Is there any GitHub projects that might help me to understand how it's done ?
Image Source: ModMyI
Thanks.
The trick involves some (very basic) reverse engineering and is made up of several steps; I'll try to explain them as clearly as possible.
Step Zero: if the app is downloaded from the AppStore, it's encrypted. You have to decrypt it using one of the scripts/applications normally used to crack apps; one command line script is poedCrack.sh (google it, you'll find it quickly on one of the paste sites), one GUI application is Crakculous (it's available in Cydia). Note that one of these are needed for easy (automatic) decryption -- the manual decryption method is way too involved to put in a StackOverflow answer, that's why I'm suggesting these tools.) However, I don't in any way encourage you to crack apps! (Basically I'm asking you not to use these tools for their original purpose :) If you want to have a look at the manual decryption process, head here.
Step One: you need to do what classes the application uses/creates. For this, you need the class-dump or class-dump-z utility. This command-line application reverses the app's binary executable file and generates interface declarations for all Objective-C classes the app uses and has inside. You can find class-dump-z, the more advanced and preferred variant here.
Step Two: after you have the class declarations, you'll have to guess which class does what and when (yep, a bit confusing). For example, in one of the files generated from above app, Google Chrome, by class-dump-z, you may find something similar:
#interface ChromeUrlToolbar: UIToolbar {
UISearchBar *urlBar;
}
- (id)initWithFrame:(CGRect)frame;
- (void)loadURL:(NSURL *)url;
#end
Well, that sounds good, doesn't it? You can see that its implementation has an initWithFrame: method (as all UIView subclasses) -- why not try to modify it?
Step Three: for this modification, you'll need MobileSubstrate. MobileSubstrate is a developer library created by Saurik, the creator of Cydia, in order to make code injection to apps easy. You can find some really good tutorials on the web, including this one.
So, you've got a class and you wanna 'hook' it -- so you write some code like this:
static IMP __original_init; // A
id __modified_init(id __self, SEL __cmd, CGRect frame) // B
{
__self = __original_init(__self, __cmd, frame); // C
// D
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[newButton setTitle:#"Chrome Pwned"];
newButton.frame = CGRectMake(0, 0, 100, 40);
[__self addSubview:newButton];
return __self;
}
// E
__attribute__((constructor))
void init()
{
Class clazz = objc_getClass("ChromeUrlToolbar"); // F
MSHookMessageEx(clazz, #selector(initWithFrame:), __modified_init, &__original_init); // G
}
Explanation: let's begin from the end. The init function (E) is declared __attribute__((constructor)). That means it's automatically called when the library we'll create out of this code will be loaded into Chrome. That's exactly what we want beause we want to alter our application's behavior prior to having started it.
On the line marked // F, we capture the class object itself we want to modify. Objective-C is a highly dynamic language; that means we can get and modify information about the classes and objects at runtime. On the line marked // G, we use the most important function of the MobileSubstrate API: MSHookMessageEx. To understand how it works (rather what it does), you must know the following: Objective-C itself is implemented as a plain C library -- the language itself, under the hoods, is just simple C. So every message send in Obejctive-C is actually a C function call. These C function have two special arguments: self and cmd -- the former is the pointer to the object being messaged, the latter is the selector (a special, unique pointer to the name of the message being sent). So what MSHookMessageEx does is it takes a class and a selector, finds the implementation of the function corresponding them, and exchanges that function with the function supplied in its 3rd argument itself (__modified_init in this case). In order not to lose data, it also returns the function in its 4th parameter (here it's __original_init).
So, now the initialization of the Chrome URL toolbar is redirected to our function, what to do next? Well, nothing special: first we just call the original initialization function (notice the first two special arguments, __self and __cmd!) which creates the toolbar as if normally (this line of code is denoted by // C). Then, we do the actual alteration: in section // D, we create an UIButton, set its title and place, and add as a subview to our freshly created toolbar. Then, knowing this is an initalization function, we return back the original instance along with our button's code injected into it.
Well, that's basically what you'll need to know about this; if you're interested in deeper details of how Objective-C works and how you can create cool iOS tweaks, I suggest you to read Apple's official documentation on the topic and you can browse through some of my opensource Cydia tweaks. as well.
I hope this will help you!
You need in order to do this to understand how the Objective-C runtime works. Especially the messaging system (ie. calling a method). In particular, the methods to call are determined at runtime, vs other languages where it is at compile time.
This allows for global changing of particular methods, aka method swizzling.
Using the Mobile Substrate library you will be allowed to replace any method implementation with your own, and even call the original implementation. You need for that, of course, to know the method's name and the argument it takes, as well as the class it belongs to.
So to modify the SpringBoard for instance, you'd have to know which class in contains and which method. You'll have to use the class-dump or class-dump-z utility which does that for you (class-dump-z is more recent and more used for iOS dev, class-dump is more versatile and compatible with older binaries as well as 64 bit).
So to class-dump the SpringBoard, you'd need to enter in Terminal.app
class-dump -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard
For class-dump-z, the -p option will generate #property instead of getters/setters, which is more clear, so you'd probably type in
class-dump-z -p -H /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard -o ~/Desktop/SpringBoard
That line will create a folder on your desktop with all the classes definitions of SpringBoard.
Of course you might need to change path to one suited to your system (about that, for recent versions of Xcode, the Developer folder is in Xcode, so you'd need something like
/Applications/Xcode/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard
You can also find on the internet people who did that for you for most of the existing frameworks, this is pretty handy if you make sure they are at the right version for you're system.
Now, for AppStore applications, you will first need to decrypt them as they are protected. You will probably need to find the names and links of that yourselves as this is probably against the ToS of Stack Overflow, though using gdb can achieve that purpose.
To ease the work, some tools such as Logos (you will probably also need to see Theos) has been created that reduce the boilerplate code needed. There also is a (quite old) xcode template & tutorial for mobilesubstrate that provides good help.
Logos makes it easy to hook method method from class classname :
%hook classname //declares the class from your application you're going to override
-(void)method {
dosomethingnew(); //put all your new code for the method here
return %orig; //this calls the original definition of the method
}
%end //end hooking classname
For a list of the frameworks in the system and what they are usefull to, see here
Last thing : a list of popular tweaks that are opensourced (links to GitHub when possible) :
Chrome Customizer
MobileNotifier
UISettings (iOS 5 version was here also but seems to be pulled ?)
Spire
IconRenamer
Maxoimizer
IconRotator
QuickReply
WinterBoard
Veency
Some little tweaks
Finally, have a look at the WeekTweak, they release opensource tweak each week so you can learn by looking at someone else's source to try & do your own stuff. And the #theos chan on IRC (irc.saurik.com) will also provide help if you ask it kindly.
I've been a bad programmer because I am doing a copy and paste. An example is that everytime i connect to a database and retrieve a recordset, I will copy the previous code and edit, copy the code that sets the datagridview and edit. I am aware of the phrase code reuse, but I have not actually used it. How can i utilize code reuse so that I don't have to copy and paste the database code and the datagridview code.,
The essence of code reuse is to take a common operation and parameterize it so it can accept a variety of inputs.
Take humble printf, for example. Imagine if you did not have printf, and only had write, or something similar:
//convert theInt to a string and write it out.
char c[24];
itoa(theInt, c, 10);
puts(c);
Now this sucks to have to write every time, and is actually kind of buggy. So some smart programmer decided he was tired of this and wrote a better function, that in one fell swoop print stuff to stdout.
printf("%d", theInt);
You don't need to get as fancy as printf with it's variadic arguments and format string. Even just a simple routine such as:
void print_int(int theInt)
{
char c[24];
itoa(theInt, c, 10);
puts(c);
}
would do the trick nickely. This way, if you want to change print_int to always print to stderr you could update it to be:
void print_int(int theInt)
{
fprintf(stderr, "%d", theInt);
}
and all your integers would now magically be printed to standard error.
You could even then bundle that function and others you write up into a library, which is just a collection of code you can load in to your program.
Following the practice of code reuse is why you even have a database to connect to: someone created some code to store records on disk, reworked it until it was usable by others, and decided to call it a database.
Libraries do not magically appear. They are created by programmers to make their lives easier and to allow them to work faster.
Put the code into a routine and call the routine whenever you want that code to be executed.
Check out Martin Fowler's book on refactoring, or some of the numerous refactoring related internet resources (also on stackoverflow), to find out how you could improve code that has smells of duplication.
At first, create a library with reusable functions. They can be linked with different applications. It saves a lot of time and encourages reuse.
Also be sure the library is unit tested and documented. So it is very easy to find the right class/function/variable/constant.
Good rule of thumb is if you use same piece three times, and it's obviously possible to generalize it, than make it a procedure/function/library.
However, as I am getting older, and also more experienced as a professional developer, I am more inclined to see code reuse as not always the best idea, for two reasons:
It's difficult to anticipate future needs, so it's very hard to define APIs so you would really use them next time. It can cost you twice as much time - once you make it more general just so that second time you are going to rewrite it anyway. It seems to me that especially Java projects of late are prone to this, they seem to be always rewritten in the framework du jour, just to be more "easier to integrate" or whatever in the future.
In a larger organization (I am a member of one), if you have to rely on some external team (either in-house or 3rd party), you can have a problem. Your future then depends on their funding and their resources. So it can be a big burden to use foreign code or library. In a similar fashion, if you share a piece of code to some other team, they can then expect that you will maintain it.
Note however, these are more like business reasons, so in open source, it's almost invariably a good thing to be reusable.
to get code reuse you need to become a master of...
Giving things names that capture their essence. This is really really important
Making sure that it only does one thing. This is really comes back to the first point, if you can't name it by its essence, then often its doing too much.
Locating the thing somewhere logical. Again this comes back to being able to name things well and capturing its essence...
Grouping it with things that build on a central concept. Same as above, but said differntly :-)
The first thing to note is that by using copy-and-paste, you are reusing code - albeit not in the most efficient way.
You have recognised a situation where you have come up with a solution previously.
There are two main scopes that you need to be aware of when thinking about code reuse. Firstly, code reuse within a project and, secondly, code reuse between projects.
The fact that you have a piece of code that you can copy and paste within a project should be a cue that the piece of code that you're looking at is useful elsewhere. That is the time to make it into a function, and make it available within the project.
Ideally you should replace all occurrances of that code with your new function, so that it (a) reduces redundant code and (b) ensures that any bugs in that chunk of code only need to be fixed in one function instead of many.
The second scope, code reuse across projects, requires some more organisation to get the maximum benefit. This issue has been addressed in a couple of other SO questions eg. here and here.
A good start is to organise code that is likely to be reused across projects into source files that are as self-contained as possible. Minimise the amount of supporting, project specific, code that is required as this will make it easier to reuse entire files in a new project. This means minimising the use of project specific data-types, minimising the use project specific global variables, etc.
This may mean creating utility files that contain functions that you know are going to be useful in your environment. eg. Common database functions if you often develop projects that depend on databases.
I think the best way to answer your problem is that create a separate assembly for your important functions.. in this way you can create extension methods or modify the helper assemble itself.. think of this function..
ExportToExcel(List date, string filename)
this method can be use for your future excel export functions so why don't store it in your own helper assembly.. i this way you just add reference to these assemblies.
Depending on the size of the project can change the answer.
For a smaller project I would recommend setting up a DatabaseHelper class that does all your DB access. It would just be a wrapper around opening/closing connections and execution of the DB code. Then at a higher level you can just write the DBCommands that will be executed.
A similar technique could be used for a larger project, but would need some additional work, interfaces need to be added, DI, as well as abstracting out what you need to know about the database.
You might also try looking into ORM, DAAB, or over to the Patterns and Practices Group
As far as how to prevent the ole C&P? - Well as you write your code, you need to periodically review it, if you have similar blocks of code, that only vary by a parameter or two, that is always a good candidate for refactoring into its own method.
Now for my pseudo code example:
Function GetCustomer(ID) as Customer
Dim CMD as New DBCmd("SQL or Stored Proc")
CMD.Paramaters.Add("CustID",DBType,Length).Value = ID
Dim DHelper as New DatabaseHelper
DR = DHelper.GetReader(CMD)
Dim RtnCust as New Customer(Dx)
Return RtnCust
End Function
Class DataHelper
Public Function GetDataTable(cmd) as DataTable
Write the DB access code stuff here.
GetConnectionString
OpenConnection
Do DB Operation
Close Connection
End Function
Public Function GetDataReader(cmd) as DataReader
Public Function GetDataSet(cmd) as DataSet
... And So on ...
End Class
For the example you give, the appropriate solution is to write a function that takes as parameters whatever it is that you edit whenever you paste the block, then call that function with the appropriate data as parameters.
Try and get into the habit of using other people's functions and libraries.
You'll usually find that your particular problem has a well-tested, elegant solution.
Even if the solutions you find aren't a perfect fit, you'll probably gain a lot of insight into the problem by seeing how other people have tackled it.
I'll do this at two levels. First within a class or namespace, put that code piece that is reused in that scope in a separate method and make sure it is being called.
Second is something similar to the case that you are describing. That is a good candidate to be put in a library or a helper/utility class that can be reused more broadly.
It is important to evaluate everything that you are doing with an perspective whether it can be made available to others for reuse. This should be a fundamental approach to programming that most of us dont realize.
Note that anything that is to be reused needs to be documented in more detail. Its naming convention be distinct, all the parameters, return results and any constraints/limitations/pre-requisites that are needed should be clearly documented (in code or help files).
It depends somewhat on what programming language you're using. In most languages you can
Write a function, parameterize it to allow variations
Write a function object, with members to hold the varying data
Develop a hierarchy of (function object?) classes that implement even more complicated variations
In C++ you could also develop templates to generate the various functions or classes at compile time
Easy: whenever you catch yourself copy-pasting code, take it out immediately (i.e., don't do it after you've already CP'd code several times) into a new function.