Key-value coding paths are useful in UIKit. They often allow you to configure elements that aren't specified in the public API of a view, or in the Interface Builder inspector for that view.
For instance, you can configure the text color of UIDatePicker using textColor key path, but there doesn't seem to be a property or method exposing that configuration -- the only way to do it is through key-value coding.
Given that -- how can one as an iOS developer find key-value coding paths for elements? I found this particular example in a StackOverflow response, but how did they find it? I'd love to be able to inspect these classes and find their key-value coding paths myself, or at least have a good crowdsourced reference to all the KVC key paths that might be useful when I'm trying to customize a view.
You can use class-dump to view all properties on an Objective-C class, including private properties (properties with the _ underscore prefix)
But also yes as #rmaddy said, most of the time you won't want to modify private properties-- but it should be pretty safe if you are just reading and not writing. For example, NSUndoManager has a private property, _undoStack, which is super useful to read so you can see what is currently in your undo stack
Related
I've been playing around with a button in my storyboard, and had a hard time getting a border around it, until I found a page where it showed how to add a User Defined Runtime Attribute. I was able to make the button look as I wanted, but I wanted to know if there was a way for me to view the list of available attributes for a particular Object.
Clicking the "+" to add a new attribute doesn't provide any kind of auto-complete to show the available ones, and looking through my project code doesn't seem to reveal anything either, not surprisingly. Is there somewhere I can find all of the available attributes for all/any Objects in Xcode? Searches here on SO and in general have not shown any useful results so far.
You can achieve the same thing from code, so just check the properties of UIButton (which is available in the documentation and with autocomplete) and you're good.
You also have to make sure you are checking the properties on an UIButton instance and not the class properties.
User defined runtime attribute is a list of key paths that NIB loading subsystem uses through unarchived process. After initialisation message -setValue:forKeyPath: will be send to your unarchiving object for each key path from this list. So available attributes are not more than set union of all methods with selector sort of -setAttribute: and ivars with "_attribute" or "attribute" name.
All that public attributes you may find at public headers or documentation.
There's also possible to set private attributes, but it's not good practice. For instance, you may find all ivars by breakpoint execution inside any method and look inside "self".
I'm a bit confused with Apple documentation relating to the explanation of whether to use prefix for methods or not?
Apple Doc Explanation 1:
Use prefixes when naming classes, protocols, functions, constants, and typedef structures. Do not use prefixes when naming methods; methods exist in a name space created by the class that defines them. Also, don’t use prefixes for naming the fields of a structure
Apple Doc Explanation 2:
If you are subclassing a large Cocoa framework class (such as NSView or UIView) and you want to be absolutely sure that your private methods have names different from those in the superclass, you can add your own prefix to your private methods. The prefix should be as unique as possible, perhaps one based on your company or project and of the form "XX_". So if your project is called Byte Flogger, the prefix might be BF_addObject:
For Classes which contains project related storylines/stuffs, there prefixes are not required.
But if we are using Apple Classes by extending few methods as given in example, like UIView to MBView then we should add prefix to methods to private methods in private category ( in .m file).
This is because ObjC does not support namespaces. Instead you should you capital letter prefixes(as you properly read in documentation). You could read this SO discussion why to use them.
Note that Apple uses two-letter prefixes(UI(View), NS(String), etc.) and advises programmers to use 3 letter prefixes.
I think you should use a prefix when you can, it can become a good practice and you can identify, by the name which part of your big software you're playing with.
Let's say your program name is Byte Flogger, then all your classes should start with :
BF prefix. BFBaseList for exemple, and if you want to prevent rejections when submitting your app to the AppStore, it's also a good practice to name your methods bfMyMethodName so that you still respect CamLCase naming conventions.
So for an image, you could name a property bfContentMode without being suspected by Apple to use one private API feature.
Now, let's say you handle some modules, a core module, a network module, etc...
If your class name is BFCObject, you could know that you're working with a Core object of your program.
So it is not necessary, but not doing it could force you to refactor your code in the last moment of submission. In a time driven project, I wouldn't even take that risk.
This is more of a coding style question but i believe it is valid. Coming from an obj c background i always create a .h and a .m when creating a class. However with swift that changes and all that goes into a single file. I know that for some people this is cool but i miss having these two things separate.
Quoting a comment from Zaph
"What I miss is a list of public methods as opposed to searching an
entire source file for methods not marked private. There is a
programming concept of "writing to the interface". And the public
methods should be carefully picked, not just because the developer
forgot to make some private."
is there a way to have a header - implementation class in separate files using swift? Maybe some trick?
Thanks
May be you can use Generated Interface to view all the public methods and properties. You can find that option at the bottom of related files popup in the upper-left of the source editor window. To switch back, click Original Source in the same pop up.
Shortcut: control + cmd + down arrow
This is how generated interface file looks.
As far as i'm aware, this cannot be done. That being said, if set out your .swift files correctly then they are still very readable. I tend to follow this as a guideline for styling in swift and i find that it breaks things up into readable sections, especially by using // MARK: as well.
In short, no.. But what do you miss..? Once you get used to it, you will probably prefer it like this! The old separation has no clear advantage over this new one!
More and more languages use this approach, as it reduce coupling and errors.
So when you change the signature of a function, to need to check another file to update it, it's only duplication without any added value.
The problem you describe (how to see only "public" functions) is usually done buy tools( IDE) or documentation generators.
You can create 2 swift files:
YourClassNameHeader.swift
class YourClassName {// put here all your properties
}
YourClassNameMethods.swift or YourClassNamePrivate.swift
extension YourClassName { // put here all private methods and
properties }
But in general its not good practise
Why is it allowed to declare properties in categories when neither they nor their accessor methods are synthesized? Is there any performance overhead involved?
Is categorisation purely a compiler technique?
I'm trying to understand how categories work. This just explains what to do and what not to do. Are there any sources which go into more detail?
EDIT : I know that I can use associated references. Thats not what I'm asking for. I want to know why are the properties not synthesised? Is there a performance issue or a security issue if the compiler synthesises them? If there is I want to know what and how?
Why is it allowed to declare properties in categories [...] ?
Properties have many aspects (during compile- and runtime).
They always declare one or two accessor methods on the class.
They can change the selector when the compiler transforms dot notation to messages.
In combination with the #synthesize directive (or by default) they can make the compiler synthesize accessor methods and optionally ivars.
They add introspection information to the class which is available during runtime.
Most of these aspects are still useful when declaring properties in categories (or protocols) and synthesizing is not available.
Is categorisation purely a compiler technique?
No. Categories, as properties, have both compile time as well as runtime aspects.
Categories, for example, can be loaded from dynamic libraries at a later time. So there might already be instances of a class that suddenly gets new methods added. That's one of the reasons categories cannot add ivars, because old objects would be missing these ivars and how should the runtime tell if an object has been created before or after the category has been added.
Before you go into categories, please reconsider the concept of properties in Obj-C: A property is something you can write and read to in an abstract sense, using accessors. Usually, there is an instance variable assigned to it, but there is no need to do so.
A property may also be useful e.g., to set a number of different instance variables in a consistent way, or to read from severals variables or do some calulation.
The crucial fact here: there is no need to have an instance variable assigned to a property.
A category serves as an extensiton of an object's behavior, i.e., to extend its set of methods, without changing the data. If you see a property in it abstract sense, then it add accessors, thus it matches the idea of a category.
But if you synthesize it, an instance variable would be generated what contradicts the idea of a category.
Thus, a property in a category makes only sense if you use it in the uncommon, abstract way, and #synthesize is to ease the common way.
You may want to read NSHipster about how to implement properties storage in categories.
Quoting from the article: "Why is this useful? It allows developers to add custom properties to existing classes in categories, which is an otherwise notable shortcoming for Objective-C."
#synthesize informs the compiler to go ahead and provide a default implementation for the setter and the getter.
Said default setters/getters rely on the existence of some kind of storage inside the object.
Categories do not offer any extra storage, so default setters/getters would have no place to store into, or read from.
An alternative is to use:
#dynamic
and then provide your own implementation and own storage for the said properties.
One way is to use associated objects.
Another would be to store into/read from some completely unrelated place, such as some accessible dictionary of NSUserDefaults or ...
In some cases, for read only properties, you can also reconstruct/compute their values at runtime without any need to store them.
This question is specifically focused around static libraries / frameworks; in other words, code that other people will eventually touch.
I'm fairly well versed in properties, since I started iOS development when iOS 6 was released. I have used hidden properties declared in interface extensions to do all of my "private" property work, including using readonly on public facing properties I don't want others to modify and readwrite within interface extensions.
The important thing is that I do not want other people who are using these static libraries / frameworks to be accessing these properties if I don't allow it, nor writing these properties if I let them read it.
I've known for a while that they could theoretically create their own interface extension and make my readonly properties readwrite themselves, or guess the names of hidden properties.
If I want to prevent this, should I be using ivars with the #private tag with directly declared ivars? Are there potential downfalls to doing it this way? Does it actually get me an additional measure of security, or is it a red herring?
Under ARC the only mode supported by properties and not instance variables is copy - so if you need copy use a property.
If you declare your private instance variables in the #implementation section:
#implementation MyClass
{
// private instance vars
}
then it takes serious effort to access them from outside the class. As you say accessing a "private" property just takes guessing its name - or using the library calls which tell you.
Is it worth it for security? YMMV. But its a good coding practice regardless.
Addendum
As the comment trail shows there has been much discussion over my use of serious effort.
First let's be clear: Objective-C is in the C family of languages, they all allow the programmer to just about anything they choose while staying within the language[*] - these are not the languages of choice if you want strong typing, access restrictions, etc., etc. within your code.
Second, "effort" is not an absolute measure! So maybe I should have chosen the word "obvious" to qualify it rather than "serious". To access a private property just requires the use of a standard method call where the object has type id - there is little clue in the code that the method being called is hidden. To access a private variable requires either an API call (a runtime function or KVC call) or some pointer manipulation - the resultant code looks nothing like a standard variable assignment. So its more obvious.
That said, apart from uses requiring copy, under ARC there is no good reason to use a private property when a private instance variable will do. For a private variable fred compare:
self.fred = 42; // property access, may involve a call (if not optimised out)
_fred = 42; // common way to bypass the accessors and get at the underlying var
fred = 42; // direct access
Take your pick, there is no right answer, but there isn't a wrong one either - this is the realm of opinion (and that is of course an opinion ;-)). I would often pick the last one, private variable - clean & simple. However #RobNapier in his answer prefers the use of properties.
[*] Note: once you consider linking to external code, say written in assembler, all bets are of in any language. At that point you have to look at the "hardware" (real or virtual) and/or "OS" to provide protection.
You should use private ("hidden") properties here. There is no "security" risk. The "attacker" in this scenario is the caller. The caller has complete access to all memory in the process. She can access anything in your framework she wants and there is absolutely nothing you can do to stop that (nor should you). This is true in any language. You can bypass "private:" designations in C++ as well if you know what you're doing. It's all just memory at the end of the day.
It is not your job to protect yourself or your framework from the caller. You both have the same goal: correct program behavior. Your goal is to protect callers from themselves. Make it difficult for them to use your framework incorrectly and easy to use it correctly.
So, you should use the tool that leads to the most correct code. And that tool is properties, and avoiding directly ivar access except in init and dealloc.