for an SDK, I would like to create a text field class that behaves like a standard UITextField except that it is impossible for the developer using the SDK to know the value of the field (for security reasons). Is this possible?
My approach: When creating a UISecureTextField that inherits from UITextField, I can overload text and the notification delegates, but am I missing something? Is there still a way for the developer to access the field? Would you do something differently?
Instead of blacklisting certain methods, you could go the opposite route – use containment so your UISecureTextField has a UITextField private property, and then whitelist the methods and properties you want to expose by calling through to the text field.
More work to maintain, but it's another way to do it!
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".
Many CocoaPod and native iOS libraries use protocols that they name either CustomClassDelegate or CustomClassDataSource as a means to do some setup or customization. I was wondering when I should use this programming model, because it seems like I could accomplish much of this with properties.
Example
If I define a custom class called SmurfViewController that has a SmurfLabel, is it better practice to store the smurfLabel as a private property and have a public computed property called smurf that looks like this:
private var smurfLabel = UILabel()
public var smurf: String {
get {
return smurfLabel.text
}
set(text) {
smurfLabel.text = text
}
}
or should I define a SmurfDataSource that has a public function that looks like this:
func textForSmurfLabel() -> String {
return "smurfText"
}
When should I use what here?
You should just use a property for that. Delegates and Datasources are for different controllers/Objects to speak to one another when the alternative is to instantiate the controller/object from the navigationStack/view hierarchy. A Delegate forms a specific communication between the two that allows for clear knowledge in what their relationship is while keeping them decoupled (assuming you try to keep it that way). I disagree with the article that says callbacks are "better". They are amazing and I advise using them often, but just understand that most options that swift provides you with have a place where they work best.
I might be slightly bias, but Swift is an amazing language with OOP being a backbone and everything it has was well put together in order to provide the correct tools for each situation you find yourself in.
I often find myself using both of those tools and one other more customizable option in my more advanced setups where I have an overseeing viewController that manages many child controllers. It has direct access to all of them that are active but if any of its children communicate with it, it is through delegates. Its main job is just to handle their place on the screen though, so I keep everything manageable.
Delegates and data sources are more appropriate for offloading behaviors to other entities, not simple values. In other words, if your type just needs a value for something, you are correct that it makes more sense to expose that as a property that can be set from the client code.
But what should happen (for example) when a user taps a specific table view cell is a behavior that shouldn't be hard coded into UITableView. Instead, for flexibility, any implementation of that behavior can be created in a delegate and called by the UITableView when appropriate.
In general, think of delegation as a way to make subclassing unnecessary, because the methods you would normally override in a subclass are instead moved into a protocol that can be implemented by ANY type, not just a subclass of the base type. And instead of calling internally implemented methods to get certain behaviors, your type is simply calling those behaviors on an external collaborating class (the delegate).
So perhaps the best guideline for when to use a data source or delegate is the question: "Would I need to subclass this class in order to change this value or behavior in the future". If the answer is no, because you can just set a property from client code, then don't use delegation. If the answer is yes, then offload that behavior to a delegate or data source instead of forcing future programmers to subclass your class to make it work for their use case.
Delegate is an interface for the undefined activities.
so when you make a SDK or framework, you must provide an interface so that users can write a proper code for the interfaces' expecting activity.
i.e, Table View needs a datasource to show it's contents, but the apple's library developers doesn't know the content whatever contents their library users will use. so they provided an interface like datasource, delegate.
and in the library, they just call this methods. that's the way the library should be made.
But in your code, the label is defined very explicitly as well as it's in the current view, and you don't need to make an interface for an undefined activity.
if you want know more about this kind of coding style, you need to do some researches on Software Design Pattern.
https://en.wikipedia.org/wiki/Observer_pattern
https://en.wikipedia.org/wiki/Delegation_pattern
https://en.wikipedia.org/wiki/Software_design_pattern
I love apple's sdk very much, because they used all the needed design patterns very properly.
How can I access an attribute that's been hidden via:
__attribute__((visibility("hidden")))
I'm trying to access UINavigationItemButtonView, but it seems sometime recent (iOS 7.1?) they've added the above into the header file. Recursively printing the window no longer reveals UINavigationItemButtonView in the view stack either.
So, given a UINavigationBar, how can I access a UINavigationItemButtonView that has been hidden via the above flag?
Printing all the subviews in UINavigationBar doesn't reveal it.
The attribute keyword is simply a message to the compiler, and has nothing to do with the runtime. Using ((visibility("xxx")) only serves to tell the compiler if the given declaration should be "visible" or usable by clients in some other package. visibility("hidden") just means that, despite the public declaration, make this thing invisible to external packages, so that they will not be able to use it. Compiling will fail if you attempt to use this class or method.
If you don't see this class being used in a recursive description, it is likely that this class is no longer used; it certainly isn't because of the attribute statement.
Since it's a private class, you shouldn't. Anything you do to bypass that restriction may result in your application failing the review process. Not to mention that, in general, accessing private and/or hidden API's, classes, instance variables, properties or whatever else it is, is a really good way to make sure your application breaks in the (not too distant) future.
I've been going through our code base and setting the accessibilityIdentifier property on all of our buttons and text fields so that I can access them using UIAutomation. While doing this, I came across some code that was already in place.
[_goodButton setAccessibilityLabel:#"off"];
I can't find any documentation on what the differences are between these two methods. It looks like they do the same thing. Does anyone know? I find it peculiar that this label is set to "off" as well.
There's definitely some confusion about these two properties. I myself fell into that very same trap, but research and experimentation with VoiceOver and UI Automation testing showed there is a clear difference.
accessibilityLabel
This is the value that's read by VoiceOver to the end-user, or exposed through other accessibility tools. As such, this should be a localized string. It's best to keep this to a single word, if possible, describing what it is (i.e. 'Help', 'Play', 'New Note', etc.) It should also be capitalized, but not end in a period. This helps with VoiceOver's pronunciation.
Because this is end-user facing, as part of user-testing, a developer may change this to be more clear as needed. For instance, it may change from 'Play' to 'Read Comments'. Because of that, you wouldn't want this to be tied to automation testing as such a change would break any tests referring to the now-non-existent 'Play' label. That's where accessibilityIdentifier comes in.
accessibilityIdentifier
While accessibilityLabel is end-user facing, accessibilityIdentifier in contrast is developer-facing only and is primarily used to identify an accessible element to UI automation and testing tools. As such, it should not be localized.
A developer should use a value that makes sense in the context of UI testing only, not to the end user. For instance, a button which displays a help topic can have the identifier 'HelpButton' as that's clear to what it's identifying but isn't something the end user would ever need to be exposed to.
Make it a habit to use this value! Doing so ensures your UI automation tests will never break due to localization or from changes to accessibilityLabel.
accessibilityHint (including for completeness)
accessibilityHint is for cases where the accessibilityLabel may not be clear enough on its own. Since accessibilityLabel should, if possible, be kept to a single word, accessibilityHint can provide additional context. However, if accessibilityLabel is expressive enough on its own, you should leave accessibilityHint blank.
If it is determined that accessibilityHint is required, keep this to a simple, short sentence fragment, capitalized and ending in a period. It should describe what it does, not tell you what to do (i.e. 'Plays the current track.' instead of 'Play the current track.' as the latter sounds like an instruction telling you what to you, not letting you know what will happen.)
How this is used is VoiceOver will first read the label, pause briefly, then it reads the hint (e.g. 'Play... Plays the current track.' If the user disables hints, it will of course just say 'Play')
Hope that helps!
Instead of using accessibilityLabel (see below) you should use accessibilityIdentifier.
This github issue explains the difference:
Given that accessibilityLabel is an outwardly-facing string that is actually used by accessibility screen readers (and should be localized to the device user's language), Apple now provides an alternate property (iOS 5+) that is specifically intended for UI Automation purposes
You check this one
Accessibility Label and Identifier Attributes
The label attribute and identifier attribute figure prominently in your script’s ability to access UI elements. It is important to understand how they are used.
Setting a meaningful value for the label attribute is optional, but recommended. You can set and view the label string in the Label text field in the Accessibility section of the Identity inspector in Interface Builder. This label is expected to be descriptive, but short, partly because assistive technologies such as Apple’s VoiceOver use it as the name of the associated UI element. In UI Automation, this label is returned by the label method. It is also returned by the name method as a default if the identifier attribute is not set. For details, see UIAccessibilityElement Class Reference.
The identifier attribute allows you to use more descriptive names for elements. It is optional, but it must be set for the script to perform either of these two operations:
Accessing a container view by name while also being able to access its children.
Accessing a UILabel view by name to obtain its displayed text (via its value attribute).
In UI Automation, the name method returns the value of this identifier attribute, if one is set. If it is not set, the name method returns the value of the label attribute.
Currently, you can set a value for the identifier attribute only programmatically, via the accessibilityIdentifier property. For details, see UIAccessibilityIdentification Protocol Reference.
AccessibilityLabel is the value that’s read by VoiceOver to the end-user. As such, this should be a localized string. The text should also be capitalized. Because this helps with VoiceOver’s pronunciation. accessibilityLabel is used for testing and Visual Impaired users.
AccessibilityIdentifier identifies an element via accessibility, but unlike accessibilityLabel, accessibilityIdentifier's purpose is purely to be used as an identifier for UI Automation tests. We use a value for testing process.
I would like to do coloring in Eclipse without using the presentation reconciler. Therefore, first, I need to figure out how to associate a TextPresentation object with either my editor or document, but I am having difficulty finding out how to link it either of those. Normally, the CreatePresentation in the IPResentationReconciler interface would give the style range to the textpresentation, and from there Eclipse would know what to do with that presentation object. Is there some way to use a TextPresentation object without the use of PresentationReconciler? It would be nice if I could do coloring without the use of reconciler. Thank you.
I finally figured out how to achieve the coloring without the use of Reconcilers.
I discovered that first I needed a way to obtain a reference to my SourceViewer object, as I am extending TextEditor. I also discovered that I could implement the TextListener interface and add my own listener to the SourceViewer object. One must be careful, however, as calling the getSourceViewer() method can result in null if not called at the appropriate spot. Originally, I overwrote the init(...) function in my editor class and made the getSourceViewer() call, but it still resulted in null. After doing a bit of research, I discovered that I could properly obtain a reference to the SourceViewer object by overriding the createPartControl method. I first call super.createPartControl(...) and then make a call to getSourceViewer(). After I obtained that reference, I used that with my listener class I created and was able to do the coloring myself with the setTextColor method the SourceViewer object has. Hope this helps others in the same situation.