I don't really know what is wrong with this that i cant get any output
class Shape {
var numberOfSides : Int = 3
var name : String
init(name : String){
self.name = name
}
func print() -> String {
return("numberOfSides : \(numberOfSides)")
}
}
var Square = Shape("moraba")
println(Square.print())
Unlike normal methods and functions init() methods require to pass the first parameter name
let square = Shape(name:"moraba")
println(square.print())
Related
I am trying to use another initalizer when some edge case happens during initialization, but I realized that once I delegate initialization to another initalizer, I can't treat that initializer like I would a normal one, instead I have to delegate initialization in all code branches.
(real use case is to initialize a struct containing email and name from a ASAuthorizationAppleIDCredential But because this object only returns the email and name the first time the user signs up with Apple, I have to check if it contains it, if no then an initalizer is called, that can create one by loading it from NSUbiquitousKeyValueStore. I ended up solving this by creating a function returning this struct instead of an init function)
The errors I get are
'self' used before 'self.init' call or assignment to 'self'
'self.init' isn't called on all paths before returning from initializer
These come up when I try to use a different initializer in a guard statement's else closure. Here is a simplified example:
struct Test {
var name : String
var age : Int
init(name : String) {
self.name = name
self.age = -1
}
init(name : String, age : Int?) {
guard let age = age else {
self.init(name: name)
return
}
self.name = name
self.age = age
}
}
Another solution I found is to create an init that can be called after the guard statement, in this case:
init(name: String, age : Int) {
self.name = name
self.age = age
}
and then use this init instead of assigning values directly.
My question is: why is this the case, and where is this behaviour mentioned or explained? The only documentation I found about this was the swift docs here:
https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID215
Not sure about other languages but in Swift you have to first initialise existing initialiser before initialising extra property/properties.
import UIKit
struct Test {
var name : String
var age : Int
init(name : String) {
self.name = name
self.age = -1
}
init(name : String, age : Int?) {
self.init(name: name)
if let age = age {
self.name = name
self.age = age
}
}
}
let x = Test(name: "x", age: nil)
let y = Test(name: "y", age: 18)
let z = Test(name: "z")
I'm working on a project and I have created a class to handle the json response to convert it to modal class and change it back to json request with updated data if needed.
Here in the class I'm getting and saving values from and into dictionary. I need to create an enum for the dictionary keys so that there should be less chance for error for complex key formats.
I even tried using like
enum Fields {
case Name
case Email
}
but Fields.Email return Fields object
if I use a protocol of a variable like
protocol someProtocol {
var name: String { get }
}
extension someProtocol {
var name:String {
return String(describing: self)
}
}
and then extend the enum Fields:someProtocol
then I can use it like Fields.name.name or Fields.email.name
But My client will not approve this I want to create an enum so that I can access the string directly like for name I want key "Name" and I should get it liek "Fields.name" or ".name"
So here I have two objectives
first it that I need to create something that can be accessed through class function
second it should be common so that I can use it with multiple classes
third I can access it with less operators
—
class PersonService {
class Update {
var name = ""
var email = ""
var personId = 0
func createDataFrom(dic:[AnyHashable : Any]) -> Update {
let update = Update()
update.name = dictionary["Name"]
update.email = dictionary["Email"]
update.personId = dictionary["Id"]
return update
}
func createDataTo() -> [AnyHashable:Any] {
var ret = [AnyHashable : Any]()
ret["Name"] = name
ret["Email"] = email
ret["Id"] = personId
return ret
}
}
}
Something like that?
enum Fields: String {
case Name = "Name"
case Email = "Email"
}
Print(Fields.Name.rawValue)
result: "Name"
Or
struct Constants {
static let name = "Name"
static let email = "Email"
}
print(Constants.name)
result: "Name"
In order to reduce cut-and-paste code in this app, I'm trying to pass class names around in order to tell a method which way it should process some data. I have something like the following:
class MyClass : NSObject {
var name : String = ""
}
class OneClass : MyClass {
override init() {
super.init()
self.name = "One"
}
}
class TwoClass : MyClass {
override init() {
super.init()
self.name = "Two"
}
}
class Thing : NSObject {
func doStuff(withClass cls: AnyClass) -> String {
let x = cls.init()
return x.name
}
}
let z = Thing()
print(z.doStuff(withClass: OneClass))
print(z.doStuff(withClass: TwoClass))
Passing withClass cls: AnyClass the parser pushed me to change let x = cls() to let x = cls.init(). But I've got an Expected member name or constructor call after type name error for the last two lines. The recommended fixes both cause other problems.
The first suggestion, adding the () constructor after the class name, causes new errors on those lines: Cannot convert value of type 'OneClass' to expected argument type 'AnyClass' (aka 'AnyObject.Type')
Taking the second suggestion and changing them to OneClass.self and TwoClass.self gets rid of the parser errors, but when I execute the code it just runs forever.. never erroring out, and never completing.
I found a recommendation elsewhere that suggests I should change the Thing.doStuff() parameters to expect MyClass instead of AnyClass, but that causes another set of new problems.
First, the parser starts complaining about the cls.init() call, and the series of fixes it suggests eventually lead to something that makes no sense: let x = cls.type(of:;; init)(). The parser ends up in a suggestion loop where it keeps adding more semi-colons in the middle of the statement.
Second, I'm back to type mismatch errors on the calls to doStuff() in the last two lines: Cannot convert value of type 'OneClass.Type' to expected argument type 'MyClass'.
There's obviously something I'm not getting here about passing types as arguments, but none of the googling I've done has landed me on something that explains the problems I'm seeing.
How about the generic Swift way.
The code constrains the generic type T to MyClass since it must have a name property.
class MyClass : NSObject {
var name : String
override required init() {
self.name = ""
super.init()
}
}
class OneClass : MyClass {
required init() {
super.init()
self.name = "One"
}
}
class TwoClass : MyClass {
required init() {
super.init()
self.name = "Two"
}
}
class Thing : NSObject {
func doStuff<T : MyClass>(withClass cls: T.Type) -> String {
let x = cls.init()
return x.name
}
}
let z = Thing()
print(z.doStuff(withClass: OneClass.self))
print(z.doStuff(withClass: TwoClass.self))
Or use a protocol.
protocol Nameable {
var name : String { get }
init()
}
class MyClass : NSObject, Nameable { ...
...
class Thing : NSObject {
func doStuff<T : Nameable>(withClass cls: T.Type) -> String {
let x = cls.init()
return x.name
}
}
To get this working, you must call init on cls after typecasting it to NSObject.Type. Also, x.name only works if cls Class type contains that particular property. This is the reason x is then typecasted to MyClass.
class Thing : NSObject
{
func doStuff(withClass cls: AnyClass) -> String?
{
let x = (cls as? NSObject.Type)?.init()
if let x = x as? MyClass
{
return x.name
}
return nil
}
}
Call doStuff with ClassType.self
print(z.doStuff(withClass: OneClass.self))
print(z.doStuff(withClass: TwoClass.self))
Let me know if you still face any issues.
I have created a custom class called PhoneTranslator (based on Xamarin's "Hello, iOS" guide). It looks like this:
class PhoneTranslator {
func ToNumber(raw:String) -> String {
var newNumber = raw.isEmpty ? "" : raw.uppercaseString
//newNumber operations...
return newNumber
}
}
Then I have a ViewController standard class. I want to do this:
var translatedNumber : String?
if let inputText = PhoneNumberTextField.text //getting text from UITextField
{
translatedNumber = PhoneTranslator.ToNumber(inputText) //error
}
Then in line with ToNumber method I get an error Cannot convert value of type 'String' to expected argument type 'PhoneTranslator'.
What am I doing wrong? All input and output types seems to match.
Change your code to
class PhoneTranslator {
class func ToNumber(raw:String) -> String {
var newNumber = raw.isEmpty ? "" : raw.uppercaseString
return newNumber
}
}
Your function was not a class function. Therefore you need an instance first. Above code defines the ToNumber function as class func.
Alternatively create an instance of the PhoneTranslator first:
translatedNumber = PhoneTranslator().ToNumber(inputText)
Note the () after PhoneTranslator.
Alternatively no need to make a class function. You can have a shared Instance which will be a singleton object for the entire application. With this singleton object you can call the PhoneTranslator methods
class PhoneTranslator {
static let sharedInstance = PhoneTranslator()
func ToNumber(raw:String) -> String {
var newNumber = raw.isEmpty ? "" : raw.uppercaseString
//newNumber operations...
return newNumber
}
}
And you can call it this way
translatedNumber = PhoneTranslator.sharedInstance.ToNumber(inputText)
I have two class and i would like to get a variable with the value (the variable is in a function) to my second class :
public class StreamPlayer {
class var sharedInstance : StreamPlayer{
struct Static {
static let instance : StreamPlayer = StreamPlayer()
}
return Static.instance
}
public var intermediate = NSString()
func metaDataUpdated(metaData : NSString){
var result : String = ""
var listItems = metaData.componentsSeparatedByString(";") as [String]
if (listItems.count > 0){
var containerName = listItems[0]
result = "StreamTitle=\'([^\"]*)\'".matchesForRegexIn(containerName, atRangeIndex: 1)
self.intermediate = result
}
}
}
and the second class
class RadioViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
println(test + StreamPlayer.sharedInstance.intermediate)
}
}
The problem is that the var intermediate doesn't change and don't get the value of result (in my first class)
I've copied your StreamPlayer class code into a playground. I've just commented out the matchesForRegexIn method as it seems it's your String extension so my code looks like this:
public class StreamPlayer {
class var sharedInstance : StreamPlayer{
struct Static {
static let instance : StreamPlayer = StreamPlayer()
}
return Static.instance
}
public var intermediate = String()
func metaDataUpdated(metaData : NSString){
var result : String = ""
let listItems = metaData.componentsSeparatedByString(";") as [String]
if (listItems.count > 0){
// var containerName = listItems[0]
result = "StreamTitle=\'([^\"]*)\'" //.matchesForRegexIn(containerName, atRangeIndex: 1)
intermediate = result
}
}
}
// calling the method to make sure intermediate gets updated
StreamPlayer.sharedInstance.metaDataUpdated("asd")
// check if it got updated
print(StreamPlayer.sharedInstance.intermediate)
The last line prints StreamTitle=\'([^\"])\'* so all is good. Just make sure to call StreamPlayer.sharedInstance.metaDataUpdated before checking intermediate
PS. I'm really not sure what you're trying to achieve by sharing intermediate results from a function to the outside world but it feels off. Think about splitting metaDataUpdated method into two methods maybe?
PPS. metaDataUpdated is a really bad name for a function
PPPS. If I were you I'd declare intermediate as String?
self.intermediate is a NSString while result is a String
Try
self.intermediate = result as NSString