Class versus Instance method Obejctive-C calls - NSLocale methods - method-call

I am a very green nubie, anyways, I am working through a tutorial that walks me through using the NSLocale class to get the local currency, like this:
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
So, I understand that I am creating an instance of the NSLocale class called 'here', then I send the 'here' object a message asking for the objectForKey, and the result is returned into the NSString, called 'currency'. Last, I print the currency value with the NSLog.
Ok, so here's my question, I then reviewed what other methods are on the NSLocale class and I found one called 'preferredLanguages', it returns an array of the preferred languages. So I though I would call that method and then print it to the log, just for grins and to help me learn. Going off of the example above, I figured I would call it like this. Starting with the fact that I already have an instance of the NSLocale class called 'here' from the code above, I thought that I would just need the following ( I am repeating the three lines above just so it is easy to read here. )
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
NSArray *prefLangs = [here preferredLanguages];
NSLog(#"Preferred Languages are: %#", prefLangs);
But that didn't work, I got an error message that said, "No visible #interface for 'NSLocale' declares the selector 'preferredLanguages'
I figured out that I must do it this way instead:
NSLocale *here = [NSLocale currentLocale];
NSString *currency = [here objectForKey:NSLocaleCountryCode];
NSLog(#"Money is %#", currency);
NSArray *prefLangs = [NSLocale preferredLanguages];
NSLog(#"Preferred Languages are: %#", prefLangs);
I just don't understand why I had to call the method like this: [NSLocale preferredLanguages], instead of [here preferredLanguages]. The instance of 'here' is already created above. Can someone please explain.

You'll get accustomed to the joy and pain of Objective C pretty quick, but the short answer involves looking at the method declaration, which looks like:
+ preferredLanguages:
The "+" in the declaration indicates it's a class method.
Here's a relevant paragraph from Apple's "Learning Objective C" document
A class in Objective-C can declare two types of methods: instance
methods and class methods. An instance method is a method whose
execution is scoped to a particular instance of the class. In other
words, before you call an instance method, you must first create an
instance of the class. Class methods, by comparison, do not require
you to create an instance, but more on that later.
If the declaration starts with a "-", that makes it an instance method and you need to have an instance instantiated (created) in order to call methods on that object.
Hopefully this makes sense so far.

Related

Kotlin Bundle.putString not explicitly adding "String" but instead is "String?"

val args = Bundle()
args.putString("type", details.type)
navigator.navigate(context!!, findNavController(), Destination.TYPE, args)
I am quite confused as to why in the receiving fragment when I go to access the arguments I have passed through it is responding with...
val type: String = arguments.getString("type")
The arguments.getString is all underlined red and says "Required String Found String?" But how when I called method "putString"?!?
It is resulting in text not being rendered in the new fragment and I assume this is a nullability issue.
It's a matter of knowledge that is available in the receiving Fragment.
The Fragment is not aware of how its arguments were created (or modified) so it has to assume the "type" key you're looking for might not be in the arguments Bundle. That's why it returns a nullable (String?) result (the null value would mean absent in arguments).
Your fragment might be created in many places in your app and its arguments might have been modified in many places. We have no way of tracking that.
There are different solutions for this problem, depending on your approach in other parts of the code and how "confident" you are in creating of your Fragment.
I would usually choose a solution in which I assume setting the type is mandatory. Therefore if the type is absent - I fail fast. That would mean the Fragment was misused.
val type: String = arguments!!.getString("type")!!
The code above will crash if either:
a) arguments weren't set, or
b) String with type wasn't put in the arguments Bundle.
You are right, that is a : null ability issue.
First you should be sure if you are expecting a value, so try adding "?" or "!!", i would recommend "?", or go with the block of if {} else
To read the string safely you can use:
val type: String = arguments?.getString("type").orEmpty()
The orEmpty call at the end ensures that a valid String is returned even if either arguments or getString() returns null.
The method signature for getString() returns a nullable String. This is because at compile time, the compiler can't know if the value exists in the bundle or not. You will have the same issue when retrieving anything from any Map.
If you know for certain that the value in the bundle or map should exist at the time you call getString(), you can use the !! operator. That's what it's there for. When you know something should always be there, it is appropriate to want an exception to be thrown (in this case KNPE) if it's not there so you can easily find any programming error during testing.
isEmpty() or ?.let aren't helpful in this particular case because they would just be masking a programming error and making it harder to discover or debug.

Why I cannot get exactly the same GString as was put to map in Groovy?

With the following snippet I cannot retrieve gString from a map:
def contents = "contents"
def gString = "$contents"
def map = [(gString): true]
assert map.size() == 1 // Passes
assert gString.hashCode() == map.keySet().first().hashCode() // Passes, same hash code
assert gString.is(map.keySet().first()) // Passes, exactly the same object
assert map[gString] // Fails
How is that possible?
What's interesting here is that map.get(map.keySet()[0]) works fine while map.get[map.keySet()[0]] does not.
Assertion message clearly shows that there's something wrong:
assert map[gString] // Fails
| ||
| |contents
| null
[contents:true]
It's not the same question as Why groovy does not see some values in dictionary?
First answer there suggests:
You're adding GString instances as keys in your map, then searching for them using String instances.
In this question I clearly add GString and try to retrieve GString.
Also neither Why are there different behaviors for the ways of addressing GString keys in maps? nor Groovy different results on using equals() and == on a GStringImpl have an answer for me. I do not mutate anything and I do not mix String with GString. Groovy documentation is not helpful as well.
tl;dr: You seem to have discovered a bug in Groovy's runtime argument overloading evaluation.
Answer:
map[gString] is evaluated as map.getAt(gString) at runtime straightforwardly via Groovy's operator overloading mechanism. So far, so good, but now is where everything starts to go awry. The Java LinkedHashMap class does not have a getAt method anywhere in it's type hierarchy, so Groovy must use dynamically associated mixin methods instead (Actually that statement is sort of reversed. Groovy uses mixin methods before using the declared methods in the class hierarchy.)
So, to make a long story short, Groovy resolves map.getAt(gString) to use the category method DefaultGroovyMethods.getAt(). Easy-peasy, right? Except that this method has a large number of different argument overloads, several of which might apply, especially when you take Groovy's default argument coercion into account.
Unfortunately, instead of choosing DefaultGroovyMethods.getAt(Map<K,V>,K), which would seem to be a perfect match, Groovy chooses DefaultGroovyMethods.getAt(Object,String), which coerces the GString key argument into a String. Since the actual key is in fact a GString, the method ultimately fails to find the value.
To me the real killer is that if the argument overload resolution is performed directly from code (instead of after the operator resolution and the category method selection), then Groovy makes the right overload choice! That is to say, if you replace this expression:
map[gString]
with this expression:
DefaultGroovyMethods.getAt(map,gString)
then the argument overloading is resolved correctly, and the correct value is found and returned.

JavaFX binding and null values

I was wondering how to bind values where the source of the bind could be null.
I have a property:
private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null);
I also have a text field:
#FXML
private Text txtCurrentOperation;
I would like to bind the textProperty of the field to the value of the operation object.
My first thought was to use FluentAPI with its when/then/otherwise construct, but it is eagerly evaluated so the solution:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(operation.get().getName()));
will throw a NPE, because the parameter of otherwise is evaluated no matter what the result of the when.
My next idea was to use lambda somehow:
txtCurrentOperation.textProperty().bind(() ->
new SimpleStringProperty(
operation.isNotNull().get() ? "Null" : operation.get().getName()
));
But the bind has no lambda enabled solution. (Later I realized that it couldn't have, becasue the real work goes backward: the change of the binded object (operation) will trigger the update of the binder (the field text property).)
Some articles I found suggested to use an "extremal" value for the property instead of null. But Operation is a complex and heavy weight component so it is not trivial to construct an artifical instance to represent null. Even more, this seems to me boilercode, something the binding mechanism is designed to help eliminating.
My next try was to logically swap the binding direction and add listener to the operation property and let it update the field programatically. It works and rather simple as long as the need of update only depends the operation object instances:
operation.addListener((e) -> {
txtCurrentOperation.setText(operation.isNull().get() ?
"Null" : operation.get().getName());
});
operation.set(oper);
It is relatively simple, but doesn't work: it throws "A bound value cannot be set." exception and I don't see why is the text property of the control regarded as bound.
I ran out of ideas. After much searching, I still cannot solve the simple problem to update a text field differently based on whether the source is null or not.
This seems so simple and everyday problem, that I am sure I missed the solution.
If a 3rd party library is an option, check out EasyBind. Try something like this:
EasyBind.select(operation)
.selectObject(Operation::nameProperty)
.orElse("null");
There's also a JavaFX JIRA issue for the type of functionality provided by EasyBind. If you don't want to use a 3rd party library, try Bindings.select:
Bindings.when(operation.isNotNull())
.then("null")
.otherwise(Bindings.select(operation, "name"));
Be aware the null checking in Bindings.select isn't super efficient. There's a JIRA issue for it.
Just in case if somebody using not Java itself but Kotlin.
It is a good idea to use wonderful tornadofx library.
There you can just use operation.select{it.name}. Although, this feature seems not to be documented yet, so it took some time to discover it.

QVector array in QT cannot access private member error

I have experience in programming but Im still learning, I decided to create a QVector array to store some QGraphicsRectItem in it like this:
QVector<QGraphicsRectItem> *FreeLayer1;
FreeLayer1 = new QVector<QGraphicsRectItem>;
FreeLayer1->resize(10);
Here is the error:
c:\QtSDK\Desktop\Qt\4.8.1\msvc2010\include\QtCore/qvector.h(532) : error C2248: 'QGraphicsRectItem::QGraphicsRectItem' : cannot access private member declared in class 'QGraphicsRectItem'
c:\qtsdk\desktop\qt\4.8.1\msvc2010\include\qtgui\qgraphicsitem.h(728) : see declration of 'QGraphicsRectItem::QGraphicsRectItem'
c:\qtsdk\desktop\qt\4.8.1\msvc2010\include\qtgui\qgraphicsitem.h(683) : see declaration of 'QGraphicsRectItem'
c:\QtSDK\Desktop\Qt\4.8.1\msvc2010\include\QtCore/qvector.h(473) : while compiling class template member function 'void QVector<T>::realloc(int,int)'
I know this may sound really stupid or really easy to do but I didn't find errors exactly like mine and I don't have a lot of experience with declarations. My question is how can I write this code in order to use my variable FreeLayer1. I insist on using QVector<>, I just don't know how to declare it.
Thank you for your help! :)
Your declaration is fine, the problem seems to be that QGraphicsRectItem's default constructor is private, so you can't use methods of QVector which need the default constructor, like QVector::resize. Looking at the docs for QGraphicsRectItem, there seems to be no public copy constructor or copy assignment operator either, so QGraphicsRectItem is not eligible as the element type of QVector. You'll have to store pointers to QGraphicsRectItem:
QVector<QGraphicsRectItem*> FreeLayer1;
FreeLayers1.resize(10);
FreeLayers1[0] = new QGraphicsRectItem(/* ... */);

passing multiple parameters to resulthandlers in flex

Is there a way to extend the ResultEvent class in flex. i have the following code:
var token:AsyncToken = remoteObject.setQueryAndGetPromptValues('country', queryString);
token.addResponder(new mx.rpc.Responder(resultCountrySearch,faultCountrySearch));
var token:AsyncToken = remoteObject.setQueryAndGetPromptValues('company', queryString);
token.addResponder(new mx.rpc.Responder(resultCompanySearch,faultCompanySearch));
so once the RPC call is executed I get a ResultEvent which is handled by resultCountrySearch or resultCompanySearch, each of which updates the corresponding text field. I have 30 such prompts so I do not want to create 30 different handler functions. Is there a way that I could pass which text field to update to the resultHandler along with the result event.
One way is to add your variables to to the asyncToken as object properties and the use them in the resulthandler
token.myprop = myvar;
There IS a way because the Swiz library does it for you. All you have to do is call executeServiceCall(call, resultHandler, faultHandler, eventArgs), and the evertArgs array is passed through as an argument to whichever handler is called.
I don't know all the implementation details, but it's an open source library, so you can have a poke around at their DynamicResponder class (implements IResponder) to see the Swiz approach. It's probably best to read the relevant documentation first of course (don't worry, it's short!).
Alternatively you could just use the library, though that may not be practical for your requirements.

Resources