Property "window" not found on object? - iphone

This came up in another question (kindly answered by meronix) but I curious to learn a little more about what is going on here, is this a LLVM/Clang issue, or are the two statements different in someway.
I know I can fix this by adding (See below), so more curious than anything ...

The two statements are different. A property can only be used if the type of the lvalue declares the property. This is because the getter and setter for the property might be non-obvious (often the case with boolean properties, where the getter is explicitly set to isSomething.) The compiler cannot infer that without strong type info.
The [lvalue message] syntax, however, has no such ambiguity, so the compiler allows it. Since the type of the lvalue is id, any known message can be sent to it without a compiler warning. The compiler will only warn if two signatures correspond to the same selector (for instance, one class has - (UIWindow *)window and another has - (int)window.)
The UIApplicationDelegate protocol defines a window property, so when you explicitly type your object as id <UIApplicationDelegate>, the compiler knows about the property and can use it.

Related

Is it possible to use an alias for `self` in swift?

Swift appears to share with python one characteristic of requiring the class instance reference to access the members - even inside the class itself. The default in both languages is self. In particular
self.someClassMethod()
This is identical between python and swift. I also dislike this requirement finding it to be intrusive: it attracts my attention to self and away from which method is actually being invoked. In python I reduce (though do not remove) the annoyance by using s instead:
def someInstanceMethod(s, param1, param2)
instead of the standard
def someInstanceMethod(self, param1, param2)
Then inside the method I can access other instance methods :
s.someOtherInstanceMethod()
I'm not going to fight any battles on this: PEP folks will jump up and down about it -but it is more readable to me and others in my team. Is there any such way to do a shortcut in swift? I noticed typealias and tried to use it:
fileprivate let tp = U.tprint // Any non-critical logging statements will happen with this
But then it is necessary to do this:
self.tp("Loaded synthesizer settings")
Without the reference to self the following error occurs:
(162, 25) reference to property 'tp' in closure requires explicit 'self.' to make capture semantics explicit
I would prefer just
tp("Loaded synthesizer settings")
but that is not apparently possible. Can we get closer to that - along the lines of s.<method> instead of self.<method> ?
It's a little unclear what the question is, or what you think is the purpose of passing self around, so here's a quick summary of the key facts:
There are instance members and type members (type members are marked static or class).
If a method is an instance method, it does not need to say self to access instance members.
If a method is a type method, it does not need to say self to access type members.
If a method is an instance method, it can say Self to access type members.
If a method is a type method, there is no instance so instance members cannot be accessed.

Learning about type methods/type properties

I'm reading through the Swift documentation about type methods and type properties, and I cannot for the life of me figure out why it says this particular thing (in bold):
Within the body of a type method, the implicit self property refers to
the type itself, rather than an instance of that type. For
structures and enumerations, this means that you can use self to
disambiguate between type properties and type method parameters, just
as you do for instance properties and instance method parameters.
More generally, any unqualified method and property names that you use
within the body of a type method will refer to other type-level
methods and properties. A type method can call another type method
with the other method’s name, without needing to prefix it with the
type name. Similarly, type methods on structures and enumerations
can access type properties by using the type property’s name without a
type name prefix.
So, why is this pointing out structures and enumerations being able to do these things when, as far as I know, you can do these things with any kind of type methods/parameters (i.e. classes as well)? It makes me think I'm missing something.
The page in the documentation I'm looking at is here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
Apparently I wasn't the only one with this question. I'm not sure how I didn't see this post before: https://softwareengineering.stackexchange.com/questions/276962/static-properties-and-implicit-self-property-in-structures-and-enumerations-vs

Cast object to Class who's type was passed as a parameter

What I want to do is:
- (UIView *)getView:(UIView *)recycledView withClass:(Class)myClass
{
myClass *currentItem = (myClass*)recycledView;
....
}
I'm calling this function as follows:
[self getView:myView withClass:[SpecialView class]];
Getting a compilation error, any ideas if it's possible to achieve this?
Casting is a compilation only operation. You can't cast at runtime. At runtime, you can use isKindOfClass: to determine class.
In general, the need for dynamic casting indicates a design problem in your code. Specifically, you aren't leveraging either inheritance or polymorphism correctly.
For this case, you might add:
+ (UIView*)recyleView:(UIView*)recycledView;
As a method to all of your SpecialView classes (or it might be abstracted).
Sorry, you can't do it. The best you can do is cast to the declared type of myClass. Casts do not modify the objects, they simply declare the known (after checking) type of the existing object.
And there is no advantage to casting to a dynamic type, since all the compiler and JVM checks that occur based on the cast are static.
A cast happens during compilation, so attempting to cast to a type that's determined at run time (as in an Objective-C method call) is impossible.

Intersystems Cache - Correct syntax for %ListOfObjects

The documentation says this is allowed:
ClassMethod GetContacts() As %ListOfObjects(ELEMENTTYPE="ContactDB.Contact")
[WebMethod]
I want to do this:
Property Permissions As %ListOfObjects(ELEMENTTYPE="MyPackage.MyClass");
I get an error:
ERROR #5480: Property parameter not declared:
MyPackage.Myclass:ELEMENTTYPE
So, do I really have to create a new class and set the ELEMENTTYPE parameter in it for each list I need?
Correct syntax for %ListOfObjects in properties is this one
Property Permissions As list of MyPackage.MyClass;
Yes, a property does sometimes work differently than a method when it comes to types. That is an issue here, in that you can set a class parameter of the return value of a method declaration in a straightforward way, but that doesn't always work for class parameters on the class of a property.
I don't think the way it does work is documented completely, but here are some of my observations:
You can put in class parameters on a property if the type of the property is a data-type (which are often treated differently than objects).
If you look at the %XML.Adaptor class it has the keyword assignment statement
PropertyClass = %XML.PropertyParameters
This appears to add its parameters to all the properties of the class that declares it as its PropertyClass. This appears to be an example of Intersystems wanting to implement something (an XML adaptor) and realizing the implementation of objects didn't provide it cleanly, so they hacked something new into the class compiler. I can't really find much documentation so it isn't clear if its considered a usable API or an implementation detail subject to breakage.
You might be able to hack something this way - I've never tried anything similar.
A possibly simpler work around might be to initialize the Permissions property in %OnNew and %OnOpen. You will probably want a zero element array at that point anyway, rather than a null.
If you look at the implementation of %ListOfObjects you can see that the class parameter which you are trying to set simply provides a default value for the ElementType property. So after you create an instance of %ListOfObjects you could just set it's ElementType property to the proper element type.
This is a bit annoying, because you have to remember to do it every time by hand, and you might forget. Or a maintainer down the road might not now to do it.
You might hope to maybe make it a little less annoying by creating a generator method that initializes all your properties that need it. This would be easy if Intersystems had some decent system of annotating properties with arbitrary values (so you could know what ElementType to use for each property). But they don't, so you would have to do something like roll your own annotations using an XData block or a class method. This probably isn't worth it unless you have more use cases for annotations than just this one, so I would just do it by hand until that happens, if it ever does.

Must I import my category header file every time I want to use that additions?

For some reason the compiler gives me a warning that my category methods may not be there (like "foobar may not respond to doFoo"). However, the category works.
Yes, you must import your category header file. Otherwise, the compiler will give a warning for any calls to methods defined in the category. This is exactly the same as when you call a method on a class, and the method is not defined.
Because of Objective-C's dynamic nature, at runtime it will still be able to find and execute the method you call, despite the compiler warning. That is why the warning is worded "foobar may not respond to doFoo". At compile time the compiler cannot find a declaration of the doFoo method, therefore it may not be able to call the doFoo method correctly, however at runtime the doFoo method may be called correctly.