How to hide an inherited method in Swift - ios

I have a Child class that contains methods that I define and methods inherited from its Parent class. I want some of the methods from Parent to be unavailable to the user or at least generate a compile error/warning when used. Example:
class Parent {
public func secretMethod() { // Don't want anyone to use
}
}
class Child: Parent {
public func overtMethod() { // Fine with people using
}
}
Child.init().overtMethod() // Fine
Child.init().secretMethod() // Not Fine. Should not be viewable/useable/accessible
I cannot change the parent class. How I long to be able to set secretMethod to private. Swift doesn't allow restricting the access level when overriding functions, so I can't set secretMethod to private in the Child class either.
So far I have been using #available to mark the method with a compile warning and message, but I am hoping that there is a better way? I considered overriding and throwing an error, but that can't be done if the original method isn't marked throws.
Thank you.
Edit: I also cannot override the secretMethod to make it unavailable. The Child class needs to access it.

Rethink your design.
I think you may be only considering the "user" (another developer? .. you are writing a library, I guess?) and not existing source. The basic idea of subclassing is that the subclass will be able to be used anywhere the parent is used.
class A: UIView {
func availableMethod() {
}
// func layoutSubviews() ----- let's say you want to hide this method
}
The problem arises here from you not knowing what any other internal classes may be doing with the layoutSubviews and if you somehow block it on an instance of A, then anything expecting to be able to use that instance as though it is an instance of UIView will now fail.

Don't use inheritance if you don't want to expose public methods of the parent class. You can hide the 'parent' class as private instance in your 'child' class and only forward the methods you want to expose.
If you are relying on inheritance of your child class to your parent, because of some APIs which expect the parent class, then you also cannot make any parent methods private. This would break the contract between the API using the parent class, if you pass a child class, which hides formerly public parent methods. That won't work.

Look, what you're looking for is protected access modifier which would allow you to have methods and variables visible within its descendants.
But, in Swift there isn't any. The main access modifiers are private or internal.
Somewhere between them is fileprivate. It allows you to have visible methods and variables within one file. Even if this can be solution for you, it may not be right design pattern.
If you're writing library and you don't want to allow other programmers to call methods from parent but you want to allow them to see subclasses' methods, you can override internal function from parent to public or open function in subclass

I would like to enhance on the answer of #nikwest. You should try to use composition instead of inheritance. So Parent and Child don't need to share any code at all but some methods are available on both. You could also create a common ancestor so a certain var will always exist.
class Parent: Overt {
}
class Child: Overt, Secret {
}
protocol Overt {
func overtMethod()
}
protocol Secret {
func secretMethod()
}
extension Overt {
public func overtMethod() { // stuff }
}
extension Secret {
public func secretMethod() { // stuff }
}
A variation on this when you have a common var to share or something (like UIViewControllers using the composition pattern) could use a CommonParent that has the var and then Child1 and Child2 would add the protocols they need to come to the required functionality. If you don't use the default implementation in the extension you can still override.

Related

Swift: To struct, or not to struct

I'm finally making the switch from Objective-C to Swift. I'm creating a view layout system for my client to make their apps more flexible in layout, without using auto layout as they want to design their screens remotely and auto-layout would be too complex for them. I tried to do this using structs and protocols but I found it to be quite clumsy, so I'm suspecting I'm not thinking about it the right way.
With classes, the structure would be as follows:
class ViewModel {
var frame: CGRect = .zero
}
class ViewGroupModel: ViewModel {
var weight: Int = 1
var children:[ViewModel] = [ViewModel]()
}
class HorizontalViewGroupModel: ViewGroupModel {
}
class VerticalViewGroupModel: ViewGroupModel {
}
I tried to approach it with protocols by defining a ViewModel protocol, and a ViewGroupModel protocol, but I found it created a lot of duplication (properties). Is there a better approach? Would it be considered a good practice to use classes in this case?
EDIT: In case it would be better to not uses classes, I am looking for an answer that gives me a concrete solution in terms of structs and protocols.
If the concern was merely how to implement the protocol's properties, I wouldn't necessarily let that sway my choice between struct vs class. If you had a variety of properties that your struct types must implement, you have two basic options:
If you're talking about a few properties, just implement those few properties in your struct types that conform to that protocol. We do this all the time. E.g. when defining custom types that conform to MKAnnotation, we simply implement the three required properties.
Sure, if we're talking about a much larger set of properties, this gets tedious, but the compiler holds our hand through this process, ensuring that we don't miss anything. So the challenge is fairly modest.
While I'm not a fan of this approach, https://stackoverflow.com/a/38885813/1271826 shows that you could implement the shared properties as a component, where you have struct to wrap all of these properties, and then implement default computed properties for your protocol in an extension:
enum SubviewArrangement {
case none
case horizontal
case vertical
case flow
}
struct ViewComponent {
var frame = CGRect.zero
var weight = 1
var subviews = [ViewModel]()
var subviewArrangement = SubviewArrangement.none
}
protocol HasViewComponent {
var viewComponent: ViewComponent { get set }
}
protocol ViewModel: HasViewComponent { }
extension ViewModel {
var frame: CGRect {
get { return viewComponent.frame }
set { viewComponent.frame = newValue }
}
var weight: Int {
get { return viewComponent.weight }
set { viewComponent.weight = newValue }
}
var subviews: [ViewModel] {
get { return viewComponent.subviews }
set { viewComponent.subviews = newValue }
}
var subviewArrangement: SubviewArrangement {
get { return viewComponent.subviewArrangement }
set { viewComponent.subviewArrangement = newValue }
}
}
Where, you can then create an instance that conforms to ViewModel, like so:
struct LabelModel: ViewModel {
var viewComponent = ViewComponent()
}
var label = LabelModel()
label.weight = 2
print(label.weight)
I have to confess, this isn't the most elegant approach. (I hesitate to even present it.) But it avoids having to implement all of those properties individually in your types that conform to ViewModel.
So, let's set the property question aside. The real question is whether you should be using value type (struct) or reference type (class). I think it's illuminating to consider Apple's discussion of value vs reference semantics near the end (#42:15) the Protocol-Oriented Programming in Swift video. They touch upon those cases where you actually may still want to use classes. For example, they suggest you might want to use reference types when, "Copying or comparing instances doesn't make sense". They suggest this rule might apply when dealing with "Window" instances. The same applies here.
On top of that, it doesn't seem to me that there is much benefit to use value types to represent a view hierarchy, which is a collection of reference type objects. It only makes it more confusing. I would just stick with class types, as it will accurately mirror the view hierarchy it represents.
Don't get me wrong: We're so used to using reference types that I think it's always good to challenge our preconceived notions and take a long hard look at whether a value type could better address the situation. In this case, though, I simply wouldn't worry about it and just stick with a class hierarchy that mirrors the hierarchy of those objects you're modeling.
That having been said, the class hierarchy proposed in your question doesn't quite feel right, either. It feels strange that you can actually instantiate a ViewModel to which you can't later add subviews (whereas all UIView objects have subview property). Also, your horizontal and vertical group types don't feel correct either. For example, should it be a single type with some "axis" property, like UIStackView or some other "arrangement" property, to broaden the notion to capture UICollectionView layouts, too?. As you'll see in my ViewComponent example, above, I've flattened this a bit, with these two caveats in mind, but do whatever you see fit.
In general, use a class only if you need the special features of classes, which are:
A class can have a superclass and/or a subclass; a struct can't.
A class is a reference type, while a struct is a value type.
Objective-C can introspect a class (esp. if it derives from NSObject), whereas it cannot even see a struct declared in Swift.
Its always good to code to interface/protocol than to classes/structs. This your model wisely.
You can make use of generics as well beautifully for this purpose. I hope it would save a lot of variables and duplications for you.
For layout purpose in my opinion structs coupled with protocols and generics would make a great design. I don't see for you any need to use classes in your case.
Its always good to know in and out of a feature to better use it. The main difference between structs and classes in Swift are
Class objects are stored/passed as references where as struct instances are stored/passed as values
Reference counting allows more than one reference to a class instance.
For Class we have identity operators === and !== which are used to check whether two variables or constants refer to the same instance of Class. The question for identity operators does not arise for Struct because two different Struct variables or constants can not point to same instance. You can try applying identity operator to Struct types. You will get compile time error.
Inheritance enables one class to inherit the characteristics of another.
Type casting enables you to check and interpret the type of a class instance at runtime.
Deinitializers enable an instance of a class to free up any resources it has assigned.
For detailed disscussion you can through my post Struct Vs Classes in Swift.

Swift, how to declare methods requiring instance members while following MVC

I'm trying to use the MVC in an app loading a url into a webView. I'm struggling with how to/whether to define the back, forward, reload, etc... functions in the model or the viewController. I'm pretty sure they belong in the model, but then how do I call them in the IBAction for the corresponding button?
In trying to call the class function in the IBAction, first I have to create an instance of WebViewLoadRequest in each IBAction which seems extraneous. I can't (and probably shouldn't) create a global instance of WebViewLoadRequest because self isn't available in the property initializer to reference the UIWebView Outlet
class WebViewLoadRequest {
var outlet: UIWebView
var url : String
private var address: URL
init(outlet: UIWebView, url: String) {
self.outlet = outlet
self.url = url
self.address = URL(string: url)!
}
func load() {
self.outlet.loadRequest(URLRequest(url:address))
}
func back() {
if outlet.canGoBack {
outlet.goBack()
}
}
func forward() {
if outlet.canGoForward {
outlet.goForward()
}
}
func refresh() {
outlet.reload()
}
}
To simplify:
How can I write the following function in the model layer and implement it in the ViewController?
//outlet refers to a UIWebView
func back() {
if outlet.canGoBack {
outlet.goBack()
}
}
Or should this strictly be a function of the view controller? I realize essentially just the view is being changed, but there's a lot going on behind the scenes in the goBack operation that I'm not sure belongs in the ViewController
You are confusing two things here IMO, there is object oriented programming which you described in your question. There is also another concept which is commonly used and also very common in Swift, this concept is MVC. Model, View, Controller. This is basically a seperation of powers. In practice this comes down to:
Model - custom class with all the logic, in your case the WebViewLoadRequest
View - defined in a 'storyboard'
Controller - Will be a subclass of UIViewController, this subclass also has a reference to your model, all the IBActions and IBOutlets to connect to and update your UI.
You can learn more about MVC here:
https://www.raywenderlich.com/132662/mvc-in-ios-a-modern-approach
Also I would strongly recommend watching the C193p course from Standford by Paul Hegarty, this teaches you all there is to know. For example the 4th week is about MVC
https://itunes.apple.com/us/course/developing-ios-10-apps-with-swift/id1198467120
EDIT:
Basically your construction is a construction of delegation. The normal way to solve this issue is by creating a delegate property on your model-class, the delegate implements a certain protocol with for example a 'canIGoBack'-function. The model can request extra data from the delegate by calling that delegate function. Apple has something about delegation in their swift manual (check the 'Delegation' part:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
I believe Paul Hegarty also discussed it.
However, in this case it is also fine to do the canGoBack in the viewcontroller and conditionally call your model. MVC is only a guideline, there are many reasons to sometimes do logic in a viewcontroller, the biggest reason is probably if it makes shit easier. Implementing delegation only for a canGoBack is most of the times just silly.

Using a function or a type method?

I want to create a Helper.swift file to add some functions/methods that are useful in different parts of my app.
I was wondering what is the best practice (if there is one): create a class and only create type methods or just create functions?
I would generally lean towards using a type methods on an appropriately named type, in order to give your helper methods context and avoid polluting the global namespace.
In Swift, structs are an ideal candidate for this sort of construct:
struct Helper {
static func helpfulMethod() { ... }
}
I also use embedded structs with static constants quite liberally in my top level types in order to group related constants within my code.
In writing custom Swift types, you should generally consider using structs first, and only resort to classes when inheritance, reference semantics (as opposed to the implicit copying with value semantics) or ownership semantics (unowned/weak) are required. In this case, your utility functions will be stateless, and there is no inheritance to speak of, so a struct should really be preferred over a class.
I would argue that in general, the Swift language is moving away from global functions in favour of the implicit namespacing provided by types (and protocols/generics). But it's still largely a matter of style/personal preference, and for something as simple as a utility function it's of little consequence.
It is not necessary to create a class or a struct. You can simply put the functions directly in Helper.swift file. And you dont even need to import this file by writing import statements.
To test it out create a file called helper.swift and just add the following lines of code to the file. No class or struct is required.
import Foundation
func addTwo(x: Int) {
return x+2
}
To use this function in any other file just call the function with the required arguments.
let a = addTwo(9)
I prefer this method because when you call the function then you dont have to call it on an instance of a class/struct. Secondly, it leads to cleaner code as you don't have to make each function a class function or a static function.
I will prefer type method because by this way you can easily differentiate your methods.
Suppose you have 50 to 60 methods in which some methods are for designing purpose, some methods are for calculation purpose and some methods are for getting and posting data on server.
Now in this scenario, if you create all these methods as globally it will become hard to recognise and remember.
Now if you differentiate this methods in some class/struct like below:
Methods which are use for Designing purpose make a DesignHelper class/struct and put all these methods into it as class/static method
Methods which are use for calculation purpose make a MathHelper class/struct and put all these method into it as class/static method
Methods which are use for process data with server make a ConnectionHelper class/struct and put all these method into it as class/static method
By using this way you can easily find out any of the method and it will also help in auto completion.
Thank you.
Class functions through a single class work but generally those functions that are being used throughout your app will reuccur on the same objects. A cleaner way is to define your functions in extensions of the object that will use the function. You could put all your extensions in Helper.swift
e.g.
extension UIColor
{
class func randomColor() -> UIColor
{
var randomRed:CGFloat = CGFloat(drand48())
var randomGreen:CGFloat = CGFloat(drand48())
var randomBlue:CGFloat = CGFloat(drand48())
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
}
}
with usage like this page.backgroundColor = UIColor.randomColor()
So you can still define your functions as class functions or object functions depending on the usage, but within the extension of the object.
This keeps your code clear so you dont route your calls through the helper throughout your code base. Its clearly defined for the object that will be needing the function. If you find code that does not make sense in an extended function then the function probably needs refactoring into more focused functionaly.
I don't know if it is the best practice but here is how I do it.
First I declare a protocol:
protocol UtilityType { }
Then I extend it (For example a utility function for UIViewController)
extension UtilityType where Self: UIViewController {
func setDefaultTitleAttributes() {
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
}
}
And I use it like this
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setDefaultTitleAttributes()
}
}
extension MyViewController: UtilityType {}
Solution #1:
class Helper {
class func classMethod() {
// TODO: play something
}
}
And call it:
Helper.classMethod()
In Apple doc:
Structures are always copied when they are passed around in your code, and do not use reference counting.
Solution #2:
struct Helper {
static func classMethod() {
// TODO: do something
}
}
And use it:
Helper.classMethod()
I think solution#2 better than solution#1 because it's not increase reference counting.
UPDATED: I tested with playground. See the result below:
Hope this helps!

Two classes, callback and unit testing

I have one class with static methods : this class wraps calls to the Twitter API
In a second class, I have some business logic.
Due to the asynchronousness behaviour of some methods in the wrapper class, I have difficulties to design the communication. Here is what I've done :
APIManager.swift
public class APIManager {
class func getPermission(callback : () -> Void) {
let accountStore = ACAccountStore()
let accountType =
ACAccountStore().accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
let callbackRequestAccess = { (granted: Bool, error: NSError!) -> Void in
...
if(granted) {
callback()
}
}
accountStore.requestAccessToAccountsWithType(setAccountType,
options: nil, completion: callbackRequestAccess)
}
}
Welcome.swift
public class Welcome {
public func checkPermission() {
APIManager.getPermission(getTweet)
}
public func getTweet() {
...
}
}
I am not sure that this design in right or not.
I don't want to have a strong link between those classes, that's why I am using a callback.
Is this a classic design ?
Moreover, I don't feel like this behaviour will be easy to test ?
You will greatly improve testability by not using class methods here. Create a TwitterConnection protocol. Create a SystemTwitterConnection that conforms to it and manages things through ACAccountStore. Create a TestTwitterConnection that returns pre-set responses that you can configure for testing. You could even create a KeychainTwitterConnection to manage Twitter logins by hand without using ACAccountStore, or some other implementation if Apple comes out with yet another way to store these accounts.
Pass the appropriate connection to Welcome when it is created.
If the TwitterConnection protocol gets large, you should strongly consider splitting it up into smaller protocols, such as TwitterAuthenticator and TweetFetcher that handle fewer things (even if a single type actually implements all of those protocols). This can make testing much easier by allowing your test types to implement just a few functions rather than dozens.
The use of closures is probably fine, but you should stick more closely to Cocoa naming conventions. What you're calling a callback is traditionally called completion. I'd also follow Cocoa's lead on how to name methods. Rather than getPermission(), it would be requestAccessWithCompletionHandler(). This would help the caller understand that it has very similar behavior to requestAccessToAccountsWithType(options:completion:). Don't built a new vocabulary for the caller.
https://en.wikipedia.org/wiki/Observer_pattern
It will help you to decouple event publisher (Observable) and consumer (Observer).
Also you can have a special Observable implementation
which doesn't connect to anywhere but notify the observers with static content.
So you directly call notifyObservers method, for testing the behavior of Observers.

Difference between method swizzling and category in Objective c

I was just understanding the method swizzling done in obj c Method Swizzling and dangers of using method swizzling and couldn't help but draw a comparison between doing method swizzling and overwriting method implementation using categories.
They both help override the functionality of the predefined framework methods.
So is there any difference between the two or they can be used interchangeably?
The main difference is that Objective C prevents you from invoking the original implementation from a category override. This is because Objective-C's super invocations start from the super-class, while categories override methods on the same class level.
Method swizzling, on the other hand, lets you keep a reference to the original implementation as well, so that you could call it from inside your implementation. For example, in the article at your first link the author writes this:
- (void) logged_viewDidAppear:(BOOL)animated {
[self logged_viewDidAppear:animated];
NSLog(#"logged view did appear for %#", [self class]);
}
The second line makes a call to logged_viewDidAppear: method, which looks like an unconditional call to itself that should cause infinite recursion. However, this is not what happens: after swizzling, this call gets transformed into a call to the original viewDidAppear: because of the way method swizzling works.
In contrast, overriding a method from a category does not give you access to the logic of the method that you are overriding. It lets you replace the logic, but it does not let you extend it.
extension UIViewController{
public func myViewDidLoad(){
self.viewDidLoad()
//but you need to call this method everywhere replacing
}
//you cant do this
public func viewDidLoad(){
self.viewDidLoad()
//my code
}
}
Categories or extension let you do these:
Add computed properties and computed type properties
Define instance methods and type methods
Provide new initializers
Define subscripts
Define and use new nested types
Make an existing type conform to a protocol
(from Apple)
They don't let you extend original method of the same class that you are extending and if you try like the above code method signature conflict pops up.
You might want to check this website to get the concept diagrammatically. I really loved it.
http://matteogobbi.github.io/blog/2014/12/15/extending-methods-in-a-category-by-method-swizzling/
Make sure to check this awesome article for good implementation detail:
http://nshipster.com/method-swizzling/

Resources