What is different between extension and inherent - swift

I want know about extension.
Case 1.
import Foundation
import Parse
class Room: PFObject, PFSubclassing {
#NSManaged var name: String?
static func parseClassName() -> String {
return "Room"
}
}
case 2.
import Foundation
import Parse
class Room: PFObject {
#NSManaged var name: String?
}
extension Room: PFSubclassing {
class func parseClassName() -> String {
return "Room"
}
}
What is different? Both are working perfectly I just know which one is better and why?

An extension lets you add functionality to a class (to extend it) without having to subclass.
So imagine you want to add a quickAlertFunction so you can easily display a basic alert with a title, message and ok button:
func displayQuickAlert(title: String: message: String) {
// create a alert VC with title and mesage
// add the ok button/action
// present the alertVC
}
If you done this by subclassing, you would need to update all your ViewControllers to extend from your subclass, but if you done this as an extension of UIViewController you wouldn't need to update anything.
It's generally better to use an extension when you want to add general functionality to a class, if you want to add specific changes, maybe like extending a textfield and adding some autocomplete or something.. you wouldn't want these changes to be global on all Textfields, just instances of your subclass.
Also, One last thing to note.. you cannot add properties in an extension, but you can in a subclass

Related

How do I check the class of an instance that conforms to a protocol in swift?

I'm trying to check the class of an instance which conforms to a protocol.
I have a protocol.
protocol ToolbarProtocol {
func show()
func hide()
}
I have a class which conforms to that protocol.
class GameToolbar: ToolbarProtocol {
...
}
I have a manager class I createed to manage my toolbars.
class ToolbarManager {
var existingToolbars: [Game.rotation: Array<ToolbarProtocol>]
}
In this manager, I have a function that wants to find the first instance of a specific type of toolbar.
func getDebugToolbar() -> ToolbarProtocol? {
return existingToolbars[.east]?.first(where: { (toolbar: ToolbarProtocol) -> Bool in
toolbar.isKind(of: GameToolbar.self) //This line causes an error because .isKind is not a member of ToolbarProtocol
})
}
I can't call isKind(of) on toolbar, which previously worked when my toolbars were a different kind of class provided by an external library (which I'm trying to remove from my codebase because I want different functionality).
I tried making my protocol extend AnyObject, but I think that's implicit anyway, and it had no effect.
How can I check an array of instances which conform to a given protocl, to check for specific class types?
I think you would need to attempt to cast it, like
if let vc = toolbar as? GameToolbar {}
In your case, you might need something like this:
func getDebugToolbar() -> ToolbarProtocol? {
return existingToolbars[.east]?.first(where: { (toolbar: ToolbarProtocol) -> Bool in
let _ = toolbar as? GameToolbar
})
}

How to convert String to Struct (in Swift)

I have a struct like,
struct LoginConstants {
struct Selectors {
let testa = "test1234"
}
}
and a class like,
class Login: XCTestCase {
override class func setUp () {
// below constant will have a value like "LoginConstants"
let localConstants = "\(String(describing: self))Constants"
}
}
... so here I have a struct-name as a string format in localConstants.
My Question is how I can access the LoginConstants properties from the localConstants string?
NOTE:
I know I can access the LoginConstants() directly.
But I am planning to create a parent class where I can access this ***Constants struct dynamically.
Thanks for the help!
Objective-C has the ability to do this, but Swift does not. If you give a class an Objective-C name via the #objc attribute, you can use the Objective-C runtime functions to access it by name. However, this is not possible with a struct.
It's probably not the best way to go anyway. A better solution is to rethink what you are trying to do, and access the struct type directly rather than by name.

Use class func on class parameter in Swift

I am trying to use a class func to set a title for a book, however it's not working. Please see my code below:
import Foundation
class Book: NSObject {
var bookTitle: String = ""
var bookPage: String = ""
override init(){
print("Book object has been created")
}
class func setPageTitle(title: String)
{
bookTitle = title //I get the error here
}
}
I want to make it mandatory to set a pageTitle when a Book object is created.
Can someone please help me ?
The best way to set any required property/attribute is when you initialize it. So try coding your class this way:
class Book: NSObject {
var bookTitle: String = ""
var bookPage: String = ""
init(title:String) {
bookTitle = title
print("Book object has been created")
}
}
Several notes:
Your error is because you declare class in your setPageTitle function. That makes no sense.
There are better (and other) ways to set the bookTitle, including after initialization. But you specifically wanted to make sure you have a title when initializing, so there you go.
There are definitely better ways to maintain the bookTitle attribute. (Most languages teach you to hold a price variable to start with.) I'm mostly trying to give you a way to initialize it with the class.
You probably don't need (or have) any superclass call to make, but you also may not need to make your Book class a NSObject either.

A way to inherit from multiple classes

I have two classes I want to use in my new class. The first one implements a swipe to delete and the second enables a long press gesture:
class DeleteItem: UITableViewCell {
}
class OpenDetail: UITableViewCell {
}
Since Swift doesn't allow a class to inherit from multiple classes the following example obviously won't work:
class ItemViewCell: DeleteItem, OpenDetail {
}
So in order to create ItemViewCell and having both options, I'll have to have one of the classes to inherit from each other:
class DeleteItem: UITableViewCell {
}
class OpenDetail: DeleteItem {
}
class ItemViewCell: OpenDetail {
}
The problem is, if I only want the long press gesture I'll have to create a new class without inheriting from DeleteItem. Is there a better way of doing this?
This is the perfect case for using Protocols and Protocol extension. A swift protocol is like an interface in Java for example. A protocol can define a set of functions which has to be implemented by the entities which want to conform to this protocol, moreover a protocol can define properties which has to be present in these entities too. For example:
protocol ItemDeleter {
var deletedCount: Int {get set}
func deleteItem(item: ItemType)
}
The problem is, that each entity would have to provide its own implementation of func deleteItem(item: ItemType) even if multiple entities share the same logic of deleting an item, this where a protocol extension comes in handy. For example:
extension ItemDeleter {
func deleteItem(item: ItemType) {
// logic needed to delete an item
// maybe incremented deletedCount too
deletedCount++
}
}
Then you could make your ItemViewCell conform to the ItemDeleter protocol, in this case all you need is to make sure that ItemViewCell has a property deletedCount: Int. It does not need to provide an implementation for func deleteItem(item: ItemType) as the protocol itself provides a default implementation for this function, however you can override it in your class, and the new implementation will be used. The same applies for DetailOpener protocol.

Access variable in different class - Swift

i got two swift files :
main.swift and view.swift
In main.swift i have a variable (Int) initially set to 0.
With an IBACtion I set that variable to be 10, and everything is ok.
However, if I try access that variable from view.swift, with a simple call like main().getValue(), i get always 0 and not 10 even if the variable has changed it's value in main.swift.
The method getValue() in main.swift looks like this:
func getValue() -> Int {
return variable
}
EDIT
Here is the code (Translated from Italian :D )
import Cocoa
class Main: NSObject {
var variable: Int = 0
func getValue() -> Int {
return variable
}
#IBAction func updateVar(sender: AnyObject!) {
variable = 10
}
}
class View: NSView {
override func drawRect(dirtyRect: NSRect) {
println(Main().getValue()) //Returns always 0
}
}
Thanks in advance
Alberto
I have solved this by creating a generic main class which is accessible to all views. Create an empty swift file, name it 'global.swift' and include it in your project:
global.swift:
class Main {
var name:String
init(name:String) {
self.name = name
}
}
var mainInstance = Main(name:"My Global Class")
You can now access this mainInstance from all your view controllers and the name will always be "My Global Class". Example from a viewController:
viewController:
override func viewDidLoad() {
super.viewDidLoad()
println("global class is " + mainInstance.name)
}
There is an important distinction to be made between "files" in Swift and "classes". Files do not have anything to do with classes. You can define 1000 classes in one file or 1 class in 1000 files (using extensions). Data is held in instances of classes, not in files themselves.
So now to the problem. By calling Main() you are creating a completely new instance of the Main class that has nothing to do with the instance that you have hooked up to your Xib file. That is why the value comes out as the default.
What you need to do, is find a way to get a reference to the same instance as the one in your Xib. Without knowing more of the architecture of your app, it is hard for me to make a suggestion as to do that.
One thought, is that you can add a reference to your Main instance in your Xib using an IBOutlet in your View. Then you can simply do self.main.getValue() and it will be called on the correct instance.