I am currently learning swift, so I'm working in the swift playground with xcode.
I am working with classes but I get some extra output that it's just kind of distracting for me.
I don't know if I have modify xcode preference or there is something wrong with my code.
//: Playground - noun: a place where people can play
import UIKit
class Person {
var name = ""
}
class BlogPost {
var title:String?
var body = ""
var author:Person!
var numberOfComments = 0
}
let post = BlogPost()
if let actualTitle = post.title {
}
I just want to get rid off the __lldb_expr_114.
Use a protocol oriented approach:
import Foundation
import Swift
protocol PlaygroundFriendlyClass: CustomStringConvertible
{
}
extension PlaygroundFriendlyClass
{
var description: String
{
return String(describing: type(of: self)).components(separatedBy: ".").last!
}
}
class Foo: PlaygroundFriendlyClass
{
init()
{
}
}
class Bar: PlaygroundFriendlyClass
{
init()
{
}
}
Foo() // "Foo"
Bar() // "Bar"
Add the description property:
var description : String {
return "BlogPost \(author) - \(title)"
}
Related
If I have a series of protocols like so:
protocol Customer {
var name:String { get set }
var age: Int { get set }
var startDate:Date { get set }
var meals:Array<String> { get set }
var market:Int { get set }
}
protocol Vegan:Customer {
}
protocol Vegetarian:Customer {
}
protocol Paleo:Customer {
}
and extension like so:
extension Customer where Self:Vegan, Self:Vegetarian {
func getMeals() -> Array<String> {
return ["VeganMeal1", "VeganMeal2", "VeganMeal3", "VeganMeal4"]
}
}
extension Customer where Self:Vegetarian {
func getMeals() -> Array<String> {
return ["VegetarianMeal1", "VegetarianMeal2", "VegetarianMeal3", "VegetarianMeal4"]
}
}
extension Customer where Self:Paleo {
func getMeals() -> Array<String> {
return ["PaleoMeal1", "PaleoMeal2", "PaleoMeal3", "PaleoMeal4"]
}
}
and this struct
struct aCustomer:Customer, Vegan {
var name:String
var age: Int
var startDate:Date
var meals:Array<String>
var market:Int
}
when I create a new object based on that struct
var newCustomer = aCustomer(name:"William", age:40, startDate:Date(), meals:[], market:1)
how come I can't access the getMeals function in the extensions? I get an error stating getMeals is an ambiguous reference.
extension Customer where Self:Vegan, Self:Vegetarian {
extends Customer in the case where the adopter or Customer also both adopts Vegan and Vegetarian. Your aCustomer (a struct type starting with a small letter?? the horror, the horror) does not do that, so the extension doesn't apply to it.
If the goal is to inject the same code either when the adopter adopts Vegan or when the adopter adopts Vegetarian, use two extensions, or, if you don't like the repetition, have them both adopt some "higher" protocol that is extended with the desired code to be injected.
I am going through the Head-First Design Pattern book when I came across the "Command Pattern" chapter. I have recreated the example in Playground:
protocol RemoteActions {
func turnOn()
}
protocol Product {
var description: String { get set }
}
struct Light: Product {
var description: String
// some other properties
}
struct Heater: Product {
var description: String
// some other properties
}
class LightOn: RemoteActions {
var light: Light
init(light: Light) {
self.light = light
}
func turnOn() {
print("\(light.description) on")
}
}
class HeaterOn: RemoteActions {
var heater: Heater
init(heater: Heater) {
self.heater = heater
}
func turnOn() {
print("\(heater.description) on")
}
}
class Remote {
func doAction(action: RemoteActions) {
action.turnOn()
}
}
let r = Remote()
let l = Light(description: "light1")
let h = Heater(description: "heater1")
let lo = LightOn(light: l)
let ho = HeaterOn(heater: h)
r.doAction(action: lo)
r.doAction(action: ho)
I mean what are the benefits of this pattern?? Yes, I can see that the remote will only know about its actions, but what if I wanted to create a new Product to be turned on and off? I will undoubtfully have to create a new "Command Class" right? Which makes this part in the book really silly:
Wouldn't it be better if we conformed the action into said Product? Like this:
protocol RemoteActions {
func turnOn()
}
protocol Product: RemoteActions {
var description: String { get set }
func turnOn()
}
struct Light: Product {
var description: String
// some other properties
func turnOn() {
print("\(description) on")
}
}
struct Heater: Product {
var description: String
// some other properties
func turnOn() {
print("\(description) on")
}
}
class Remote {
func doAction(product: Product) {
product.turnOn()
}
}
let r = Remote()
let l = Light(description: "light1")
let h = Heater(description: "heater1")
r.doAction(product: l)
r.doAction(product: h)
gof says: 'The Command pattern lets toolkit objects make requests of unspecified application objects by turning the request itself into an object. This object can be stored and passed around like other objects. The key to this pattern is an abstract Command class, which declares an interface for executing operations. In the simplest form this interface includes an abstract Execute operation. Concrete Command subclasses specify a receiver-action pair by storing the receiver as an instance variable and by implementing Execute to invoke the request. The receiver has the knowledge required to carry out the request.'
I've recently came across a case where it would be very convenient to convert an instance of a class to a subclass, while the instance has been created within the parent class. But I've never seen such thing. So is there a way to do something like:
class Foo {
var name: String
}
class Bar: Foo {
var friendName: String
}
let foo = Foo(name: "Alice")
foo.toBar(friendName: "Bob")
// foo now of type Bar, as if I'd done
// foo = Bar(name: "Alice", friendName: "Bob")
If that's not possible, is there some reasons this would be impossible from a design perspective?
===edit=== description of a use case where it could make sense
Let say there's two views representing what correspond to the same database record for a book, on is a just a preview of the book and another is a more complex view. Models could be:
protocol BookMetaDelegate {
func onReadStatusUpdate()
}
/// describe a book
class BookMeta {
var delegate: BookMetaDelegate?
private var _hasBeenRead: Bool
var hasBeenRead: Bool {
get {
return _hasBeenRead
}
set {
guard newValue != _hasBeenRead else { return }
_hasBeenRead = newValue
delegate?.onReadStatusUpdate()
}
}
var title: String
}
/// contains all the content of a book
class Book: BookMeta {
var content: BookContent
var lastPageRead: Int
/// some logic that only makes sense in a Book instance
func getLastPageRead() {
return content.getPage(lastPageRead)
}
}
and views could look like:
class BookPreview: UIView, BookMetaDelegate {
var book: BookMeta
init(book: BookMeta) {
book.delegate = self
}
func onReadStatusUpdate() {
print("read status has changed! UI should update")
}
}
class BookView: UIView {
var book: Book
init(book: Book) {
book.hasBeenRead = true
}
}
Then things could happen like
fetch(bookMetaWithId: 123).then { bookMeta in // bookMeta is of type BookMeta
let preview = BookPreview(book: bookMeta)
...
fetch(contentOf: bookMeta).then { content, lastPageRead in
bookMeta.asBook(content: content, lastPageRead: lastPageRead)
let bookView = BookView(book: bookMeta) // doing so will change the hasBeenRead flag and message the instance's delegate, ie the preview
...
}
}
Thinking more about it, it sounds like that if such thing was possible, it'd break things like:
class Foo {
var name: String
}
class Bar: Foo {
var friendName: String
}
class Bla: Foo {
var surname: String
}
func something(foo: Foo) {
foo.toBla(surname: "Will")
}
let bar = Bar(name: "Alice", friendName: "Bob")
something(foo: bar) // what does that do ??? is bar a Bla now ?
so that'd be a good reason for making such casting impossible.
I just approached Swift and I'm encountering some problems...
I have a class which helps me to fetch some results
class ExpencesOperations {
struct ExpencesByDate {
var day: String!
var expence: [PFObject]
}
var expencesByDateArray = [ExpencesByDate]()
func getExpencesByDate(expences: [PFObject]) -> [ExpencesByDate] {
..... my function
return expencesByDateArray
}
}
When I call it in my TableViewController I don't know how to redeclare the struct ExpencesDate!
class HomeTableViewController: UITableViewController {
var myCurrency = MyCurrency()
var expencesOperations = ExpencesOperations()
var expencesByDateArray = [ExpencesOperations.ExpencesByDate]() /* Not Working */
func fetchExpences() {
expencesByDateArray = self.expencesOperations.getExpencesByDate(someInput) /* here i get the error */
}
Put the struct outside of your class scope and it should be visible to other files as well.
struct ExpencesByDate {
var day: String!
var expence: [PFObject]
}
class ExpencesOperations {
var expencesByDateArray = [ExpencesByDate]()
func getExpencesByDate(expences: [PFObject]) -> [ExpencesByDate] {
..... my function
return expencesByDateArray
}
}
You need to provide arguments for proper initialization of the ExpencesByDate struct (I think you meant ExpenSes, right?)
For example:
var expencesByDateArray = [ExpencesOperations.ExpencesByDate(day: "Friday", expence: [PFObject]())]
And regarding:
...getExpencesByDate(someInput) /* here i get the error */
The function you created expects an array:
func getExpencesByDate(expences: [PFObject]) -> [ExpencesByDate]
It's not clear from your question what someInput is. Is that an array?
As you posted in the question, it will always fail.
Plus, what are the compiler error messages?
In Objective-C, one can add a description method to their class to aid in debugging:
#implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:#"<%#: %p, foo = %#>", [self class], foo _foo];
}
#end
Then in the debugger, you can do:
po fooClass
<MyClass: 0x12938004, foo = "bar">
What is the equivalent in Swift? Swift's REPL output can be helpful:
1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}
But I'd like to override this behavior for printing to the console:
4> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
Is there a way to clean up this println output? I've seen the Printable protocol:
/// This protocol should be adopted by types that wish to customize their
/// textual representation. This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
var description: String { get }
}
I figured this would automatically be "seen" by println but it does not appear to be the case:
1> class MyClass: Printable {
2. let foo = 42
3. var description: String { get { return "MyClass, foo = \(foo)" } }
4. }
5>
6> let x = MyClass()
x: MyClass = {
foo = 42
}
7> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
And instead I have to explicitly call description:
8> println("x = \(x.description)")
x = MyClass, foo = 42
Is there a better way?
To implement this on a Swift type you must implement the CustomStringConvertible protocol and then also implement a string property called description.
For example:
class MyClass: CustomStringConvertible {
let foo = 42
var description: String {
return "<\(type(of: self)): foo = \(foo)>"
}
}
print(MyClass()) // prints: <MyClass: foo = 42>
Note: type(of: self) gets the type of the current instances instead of explicitly writing ‘MyClass’.
Example of using CustomStringConvertible and CustomDebugStringConvertible protocols in Swift:
PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
var pageIndex : Int = 0
override var description : String {
return "**** PageContentViewController\npageIndex equals \(pageIndex) ****\n"
}
override var debugDescription : String {
return "---- PageContentViewController\npageIndex equals \(pageIndex) ----\n"
}
...
}
ViewController.swift
import UIKit
class ViewController: UIViewController
{
/*
Called after the controller's view is loaded into memory.
*/
override func viewDidLoad() {
super.viewDidLoad()
let myPageContentViewController = self.storyboard!.instantiateViewControllerWithIdentifier("A") as! PageContentViewController
print(myPageContentViewController)
print(myPageContentViewController.description)
print(myPageContentViewController.debugDescription)
}
...
}
Which print out:
**** PageContentViewController
pageIndex equals 0 ****
**** PageContentViewController
pageIndex equals 0 ****
---- PageContentViewController
pageIndex equals 0 ----
Note: if you have a custom class which does not inherit from any class included in UIKit or Foundation libraries, then make it inherit of NSObject class or make it conform to CustomStringConvertible and CustomDebugStringConvertible protocols.
Just use CustomStringConvertible and var description: String { return "Some string" }
works in Xcode 7.0 beta
class MyClass: CustomStringConvertible {
var string: String?
var description: String {
//return "MyClass \(string)"
return "\(self.dynamicType)"
}
}
var myClass = MyClass() // this line outputs MyClass nil
// and of course
print("\(myClass)")
// Use this newer versions of Xcode
var description: String {
//return "MyClass \(string)"
return "\(type(of: self))"
}
The answers relating to CustomStringConvertible are the way to go. Personally, to keep the class (or struct) definition as clean as possible, I would also separate out the description code into a separate extension:
class foo {
// Just the basic foo class stuff.
var bar = "Humbug!"
}
extension foo: CustomStringConvertible {
var description: String {
return bar
}
}
let xmas = foo()
print(xmas) // Prints "Humbug!"
class SomeBaseClass: CustomStringConvertible {
//private var string: String = "SomeBaseClass"
var description: String {
return "\(self.dynamicType)"
}
// Use this in newer versions of Xcode
var description: String {
return "\(type(of: self))"
}
}
class SomeSubClass: SomeBaseClass {
// If needed one can override description here
}
var mySomeBaseClass = SomeBaseClass()
// Outputs SomeBaseClass
var mySomeSubClass = SomeSubClass()
// Outputs SomeSubClass
var myOtherBaseClass = SomeSubClass()
// Outputs SomeSubClass
As described here, you can also use Swift's reflection capabilities to make your classes generate their own description by using this extension:
extension CustomStringConvertible {
var description : String {
var description: String = "\(type(of: self)){ "
let selfMirror = Mirror(reflecting: self)
for child in selfMirror.children {
if let propertyName = child.label {
description += "\(propertyName): \(child.value), "
}
}
description = String(description.dropLast(2))
description += " }"
return description
}
}
struct WorldPeace: CustomStringConvertible {
let yearStart: Int
let yearStop: Int
var description: String {
return "\(yearStart)-\(yearStop)"
}
}
let wp = WorldPeace(yearStart: 2020, yearStop: 2040)
print("world peace: \(wp)")
// outputs:
// world peace: 2020-2040