Why does this simple Swift generics construct fail to compile? - ios

I'm working on my first Swift based project (xcode 6.3.2) and don't seem to get a simple generics construct to build.
The following seems to fail to compile on xcode 6.3.2 (compiler exit with code 1):
// with :AnyObject constraint => compiler crash
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T: AnyObject>{
private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
It looks like the Swift compiler does not like the :AnyObject type constraint of MyWrapper; the following code compiles and runs without any problem:
// no :AnyObject constraint
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T>{
private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
I need the :AnyObject type constraint because I'm actually trying to create a weak wrapper, which requires this constraint, like so:
// with weak wrapper and obligatory :AnyObject constraint (compiler crash)
class GenericsTest : MyDelegate{
static let instance = GenericsTest()
private init(){
var wrapper = MyWrapper<MyDelegate>(inner: self)
if let md = wrapper.inner {
println("delegate value : \(md.someString)")
}
}
// MyDelegate impl
var someString = "my delegate impl"
}
protocol MyDelegate : class {
var someString : String {get set}
}
class MyWrapper<T: AnyObject>{
weak private (set) var inner : T?
init(inner : T){
self.inner = inner
}
}
Anybody any idea how to work around this issue?

Related

iOS swift singleton clear data

class ShareData {
class var sharedInstance: ShareData {
struct Static {
static var instance: ShareData?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = ShareData()
}
return Static.instance!
}
var someString : String! //Some String
var selectedTheme : AnyObject! //Some Object
var someBoolValue : Bool!
}
This is my singleton design.However , I want to know how I can clear all its data as and when required?
Also can i have more than one singleton Class??
Since you've only got 3 properties on your singleton it would be far easier just to set up a method that nils each property in turn.
Once you start getting in to how to destroy and recreate your singleton, you get in to the realm of do you actually even want a singleton or should you just be using a regular object.
You are creating a Singleton with the syntax available in... 2014
Today there's a better syntax to define a Singleton class
final class SharedData {
static let sharedInstance = SharedData()
private init() { }
var someString: String?
var selectedTheme: AnyObject?
var someBoolValue: Bool?
func clear() {
someString = nil
selectedTheme = nil
someBoolValue = nil
}
}
As you can see I also added the clearData() method you were looking for.

Use of unresolved identifier '_ComboItemId'

Hello friends I am getting a strange error while creating a model class Though i have created the class it shows an error
any suggestion !!
Thank you
Here is the code
import Foundation
class ComboModel {
private var _ComboItemId: String!
private var _ComboMainCategory: String!
private var _ComboCategoryId: String!
}
var ComboItemId : String {
return _ComboItemId // Error Use of unresolved identifier '_ComboItemId'
}
init(ComboItemId : String) {
self._ComboItemId = ComboItemId // Error Initializers may only be declared within a type
}
This is a simple user mistake. You've got a class with private variables
class ComboModel {
private var _ComboItemId: String!
private var _ComboMainCategory: String!
private var _ComboCategoryId: String!
} // your class ends here!!!
Now you're trying to access ComboModel classes private variable _ComboItemId.
var ComboItemId : String {
return _ComboItemId // Error Use of unresolved identifier '_ComboItemId'
}
So, this is probably what you're looking for:
class ComboModel {
private var _ComboItemId: String!
private var _ComboMainCategory: String!
private var _ComboCategoryId: String!
var ComboItemId : String {
return _ComboItemId
}
init(ComboItemId : String) {
self._ComboItemId = ComboItemId
}
}

Weak property requirement in Swift protocol with associated type

I want to write a protocol with weak property requirement. Class that conforms it must be able to specify any type for this property. Also I don't want to specify an actual type, so it should be a type specified with some protocol. This code shows my idea for non-weak property:
protocol ObjectProtocol: class {
typealias PropertyType
var property: PropertyType {get set}
}
protocol FirstPropertyProtocol: class {}
protocol SecondPropertyProtocol: class {}
class FirstObjectImpl: ObjectProtocol {
var property: FirstPropertyProtocol?
}
class SecondObjectImpl: ObjectProtocol {
var property: SecondPropertyProtocol?
}
It works as expected.
I tried to do the same for weak property:
protocol ObjectProtocol: class {
typealias WeakPropertyType: AnyObject //must be a class type
weak var weakProperty: WeakPropertyType? {get set}
}
protocol WeakPropertyProtocol: class {}
class ObjectImpl: ObjectProtocol {
weak var weakProperty: WeakPropertyProtocol?
}
And I got a compiler error:
Type 'ObjectImpl' does not conform to protocol 'ObjectProtocol'
Is there any way I can make this work?
I made it work with #objc attribute for WeakPropertyProtocol:
protocol ObjectProtocol: class {
typealias WeakPropertyType: AnyObject //must be a class type
weak var weakProperty: WeakPropertyType? {get set}
}
#objc protocol WeakPropertyProtocol {}
class SomeObjectImpl: ObjectProtocol {
weak var weakProperty: WeakPropertyProtocol?
}
It's not a best solution because I concern about this note from apple doc
Note also that #objc protocols can be adopted only by classes that
inherit from Objective-C classes or other #objc classes.
I can live with this restriction but I will appreciate any better solution.
I don't believe a protocol can enforce weak-ness. For example:
protocol ObjectProtocol: class {
weak var weakProperty: AnyObject? {get set}
}
class ObjectImpl1: ObjectProtocol {
weak var weakProperty: AnyObject?
}
class ObjectImpl2: ObjectProtocol {
var weakProperty: AnyObject?
}
These both compile ok, even though the protocol has weak but ObjectImpl2 does not implement it.
EDIT: Is this what you're after?...
protocol ObjectProtocol: class {
typealias WeakPropertyType: Any //must be a class type
var weakProperty: WeakPropertyType? {get set}
}
protocol WeakPropertyProtocol: class {}
class ObjectImpl: ObjectProtocol {
typealias WeakPropertyType = WeakPropertyProtocol
weak var weakProperty: WeakPropertyProtocol?
}
This implementation requires use of Any rather than AnyObject, since WeakPropertyProtocol is a protocol rather than a class.
Or this?...
protocol WeakPropertyProtocol: class {}
protocol ObjectProtocol: class {
typealias WeakPropertyType: AnyObject //must be a class type
var weakProperty: WeakPropertyType? {get set}
}
class MyWeakClass: WeakPropertyProtocol {
}
class ObjectImpl: ObjectProtocol {
typealias WeakPropertyType = MyWeakClass
weak var weakProperty: MyWeakClass?
}
Either way, I think the key is in defining which class/protocol to use for WeakPropertyType.
As Swift 5.7, bundled with Xcode 14.0, the compiler emits the error: "'weak' cannot be applied to a property declaration in a protocol"
A possible protocol limitation workaround uses a computed variable and a supplementary 'weak' variable wrapped by the computed variable.
Workaround 1: This workaround doesn't force types that apply the protocol to set the property to weak
protocol SharedInformation {
var name: UIViewController? { get set }
}
class Country: SharedInformation {
private weak var _name: UIViewController?
var name: UIViewController? {
get {
_name
}
set {
_name = newValue
}
}
}
Workaround 2: This one forces a type that applies the protocol to have the property wrapped with weak storage.
protocol SharedInformation {
var name: Weak<UIViewController> { get set }
}
class Country: SharedInformation {
var name: Weak<UIViewController> = .init()
func usage() {
// set
name.wrappedValue = UIViewController()
// get
let value = name.wrappedValue
}
}
public struct Weak<Wrapped: AnyObject> {
public weak var wrappedValue: Wrapped?
public init(_ value: Wrapped? = nil) {
self.wrappedValue = value
}
}
Swift 4 version.
I needed my view models to conform to a protocol. They mustn't retain a coordinator object:
protocol ViewModelType {
associatedtype CoordinatorType: AnyObject
weak var coordinator: CoordinatorType? { get }
}

Swift 2 Correct way to get level of any object game, protocol? struct? extension?

This is my first game, and I'm new on swift and sprite kit.
I must have a level for each class that needs get level. Like car lev1 car lev 2 etc. I have read about protocol extension etc, witch is the best way to approach level management?
I have tried to use LevelTraker as extension of this protocol:
protocol LevelTracker {
typealias TypeUnit: TypeGame
var nameClass: String! {get set}
var currentLevel : Int {get set}
mutating func levelIncreases()
}
but with extension, i must write 3 var each class that needs level.
i try the same extension LevelTraker with struct LevelTraker:
func getClassName (theClass:AnyObject) -> String {
let name = _stdlib_getDemangledTypeName(theClass); return name}
protocol TypeGame {}
enum transportType : TypeGame {
case ground, sea, air
}
struct LevelTracker {
var sender: AnyObject
var TypeUnit: TypeGame
private func getSaveFileWhitName() -> String {
let saveWithName = getClassName(sender) + "." + String(TypeUnit)
return saveWithName
}
var currentLevel : Int {
get {
let stringName = getSaveFileWhitName()
let returnValue : Int = dataBase.read(stringName) as? Int ?? 1 //Check for first run of app, if = nil, set = 1
return returnValue
}
set (newValue) {
let stringName = getSaveFileWhitName()
let level : Int = self.currentLevel
let val = newValue
if (newValue > level) {dataBase.write(val, key: stringName)}
}
}
mutating func levelIncreases() {self.currentLevel++}
///SERVE SOLO PER SVILUPPO
mutating func RESETLEVEL() {dataBase.write(1, key: getSaveFileWhitName())}
}
To use: (thanks #Krzak)
class car {
init () {
let level = LevelTracker(sender: self, TypeUnit: transportType.ground).currentLevel
}
}
But I don't want modify all init object that use level, and the super super class in common, some class don't have propriety level.
The reason why you have compiler error is in your last line. You're missing the .ground
I'm not sure how you're thinking though that this will work, shouldn't it be var?
var level = LevelTracker(sender: self, TypeUnit: transportType.ground).currentLevel
What I am reading it sounds like you are doing this:
class Level : AnyObject
{
private func getSaveFileWhitName() -> String {
let saveWithName = getClassName(sender) + "." + String(TypeUnit)
return saveWithName
}
var currentLevel : Int {
get {
let stringName = getSaveFileWhitName()
let returnValue : Int = dataBase.read(stringName) as? Int ?? 1 //Check for first run of app, if = nil, set = 1
return returnValue
}
set (newValue) {
let stringName = getSaveFileWhitName()
let level : Int = self.currentLevel
let val = newValue
if (newValue > level) {dataBase.write(val, key: stringName)}
}
}
mutating func levelIncreases() {self.currentLevel++}
///SERVE SOLO PER SVILUPPO
mutating func RESETLEVEL() {dataBase.write(1, key: getSaveFileWhitName())}
}
class car : Level
{
init () {
let level = self.currentLevel
}
}
I found a solution, I'm happy to have some comment.
protocol TypeGame {}
enum transportType : TypeGame {
case car, bus, trak
}
protocol LevelTracker {
var nameClass: String! {get}
var currentLevel : Int {get set}
mutating func levelIncreases()
}
extension LevelTracker {
var currentLevel : Int {
get {/*set to DB*/ return 1}
set (newValue) {/*set to DB*/}
}
mutating func levelIncreases() {self.currentLevel++}}
A protocol only for transport object:
protocol Transport : LevelTracker {}
Ok, now my (simplified) class are:
class AllNode {//SKSpriteNode
init(){}
}
class TransportGame:AllNode, Transport {
var nameClass : String! = "Transport"
override init() {
super.init()
self.nameClass = nameClass + "." + getClassName(self)}
}
class Car : TransportGame {}
class miniCar : Car {}
class Bus: TransportGame {}
class Tree: AllNode {}
var carOne = Car()
let levelCar = carOne.currentLevel
var busOne = Bus()
let levelBue = busOne.currentLevel
var treeOne = Tree()
tree.currentLevel //ERROR YUPPI!!!! :)
Now the tree class can't access to level!
What do you think about this solution?

Swift protocol extension self reference issues with init

I'm looking for a way to add a default initializer to a protocol via protocol extensions.
My protocol is:
protocol TestProtocol {
var myVar : Double { get set }
init(value: Double)
init(existingStruct : TestProtocol)
}
I've implemented a struct using this protocol as:
struct TestStruct : TestProtocol {
var myVar : Double
init(value : Double) {
myVar = value
}
init (existingStruct : TestProtocol) {
myVar = existingStruct.myVar
}
}
However if I try via extension to make a default initializer for this protocol I run into self issues:
extension TestProtocol {
init(value : Double) {
myVar = value
}
init(existingStruct : TestProtocol) {
myVar = existingStruct.myVar
}
}
Where both assignment lines issue the error
Variable 'self' passed by reference before being initialized
Is there a way to make this work - or am i limited to using classes?
Your question is almost the same as in this post I answered yesterday.
Here is the trick to solve this :)
protocol TestProtocol {
var myVar : Double { get set }
init() // designated initializer which will ensure that your class or structer type will instantiate correctly
}
struct TestStruct : TestProtocol {
var myVar : Double
init() {
myVar = 0
}
}
extension TestProtocol {
init(value : Double) {
self.init()
myVar = value
}
init(existingStruct : TestProtocol) {
self.init()
myVar = existingStruct.myVar
}
}
Have a good day. :) Protocol extension is so nice.

Resources