#property(nonatomic, retain) NSString *password;
-(id)init {
...
password=[NSString stringWithFormat:#"%#", [[NSProcessInfo processInfo] globallyUniqueString]];
OR
password=[[NSProcessInfo processInfo] globallyUniqueString];
}
My problem is that during course of execution at some random point the password object gets automatically released. Effect is same when i use either of the assignments. As soon as i put in a retain, the problem no longer exists. I'm sure there is no release of password object anywhere in the flow - as i mentioned it is in a singleton class. I also checked that the class instance is same even when the password object is released.
Any hints please!
You assign the iVar, not the property...
So as you don't use the setter method, your object is not retained.
Use the property instead:
self.password = ...
You could use...
password=[[NSString stringWithFormat:#"%#", [[NSProcessInfo processInfo] globallyUniqueString]] retain];
Also checkout Apple's doc on memory management. I would also set breakpoints in your code and see then your object gets released.
Related
I have the following problem with my EMF based Eclipse application:
Undo works fine. Validation works fine. But when there is a validation error for the data in a GUI field, this blocks the use of the undo action. For example, it is not possible to undo to get back to a valid state for that field.
In this picture it is not possible to use undo:
Tools that are used in the application:
Eclipse data binding
UpdateValueStrategys on the bindings for validation
Undo is implemented using standard UndoAction that calls CommandStack.undo
A MessageManagerSupport class that connects the validation framework to the Eclipse Forms based GUI.
The data bindings look like this:
dataBindingContext.bindValue(WidgetProperties.text(...),
EMFEditProperties.value(...), validatingUpdateStrategy, null);
The problem is this:
The undo system works on the commands that change the model.
The validation system stops updates from reaching to model when there are validation errors.
To make undos work when there are validation errors I think I could do one of these different things:
Make undo system work on the GUI layer. (This would be a huge change, it's probably not possible to use EMF for this at all.)
Make the invalid data in the GUI trigger commands that change the model data, in the same way as valid data does. (This would be okay as long as the data can not be saved to disk. But I can't find a way to do this.)
Make the validation work directly on the model, maybe triggered by a content listener on the Resource. (This is a big change of validation strategy. It doesn't seem possible to track the source GUI control in this stage.)
These solutions either seem impossible or have severe disadvantages.
What is the best way to make undo work even when there are validation errors?
NOTE: I accept Mad Matts answer because their suggestions lead me to my solution. But I'm not really satisfied with that and I wish there was a better one.
If someone at some time finds a better solution I'd be happy to consider to accept it instead of the current one!
It makes sense that the Validator protects your Target value from invalid values.
Therefor the target commandstack remains untouched in case of an invalid value.
Why would you like to force invalid values being set? Isn't ctrl + z in the GUI enough to reset the last valid state?
If you still want to set these values to your actual Target model, you can play around with the UpdateValueStrategy.
The update phases are:
Validate after get - validateAfterGet(Object)
Conversion - convert(Object)
Validate after conversion - validateAfterConvert(Object)
Validate before set - validateBeforeSet(Object)
Value set - doSet(IObservableValue, Object)
I'm not sure where the validation error (Status.ERROR) occurs exactly, but you could check where and then force a SetCommand manually.
You can set custom IValidator for each step to your UpdateValueStrategy to do that.
NOTE: This is the solution I ended up using in my application. I'm not really satisfied with it. I think it is a little bit of a hack.
I accept Mad Matts answer because their suggestions lead me to this solution.
If someone at some time finds a better solution I'd be happy to consider to accept it instead of the current one!
I ended up creating an UpdateValueStratety sub-class which runs a validator after a value has been set on the model object. This seems to be working fine.
I create this answer to post the code I ended up using. Here it is:
/**
* An {#link UpdateValueStrategy} that can perform validation AFTER a value is set
* in the model. This is used because undo dosen't work if no model changed in made.
*/
public class LateValidationUpdateValueStrategy extends UpdateValueStrategy {
private IValidator afterSetValidator;
public void setAfterSetValidator(IValidator afterSetValidator) {
this.afterSetValidator = afterSetValidator;
}
#Override
protected IStatus doSet(IObservableValue observableValue, Object value) {
IStatus setStatus = super.doSet(observableValue, value);
if (setStatus.getSeverity() >= IStatus.ERROR || afterSetValidator == null) {
return setStatus;
}
// I used a validator here that calls the EMF generated model validator.
// In that way I can specify validation of the model.
IStatus validStatus = afterSetValidator.validate(value);
// Merge the two statuses
if (setStatus.isOK() && validStatus.isOK()) {
return validStatus;
} else if (!setStatus.isOK() && validStatus.isOK()) {
return setStatus;
} else if (setStatus.isOK() && !validStatus.isOK()) {
return validStatus;
} else {
return new MultiStatus(Activator.PLUGIN_ID, -1,
new IStatus[] { setStatus, validStatus },
setStatus.getMessage() + "; " + validStatus.getMessage(), null);
}
}
}
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.
I just installed the new version of Xcode/ios6. viewDidUnload is now depreciated.
In the apple doc,
viewDidUnload [...] Deprecated in iOS 6.0. Views are no longer purged under low-memory conditions and so this method is never called.
But numbers of apps are using this callback to release their properties, like :
- (void)viewDidUnload {
[super viewDidUnload];
self.recipientButton = nil;
self.connectButton = nil;
self.infoLabel = nil;
}
This was the best practice to release your IBOutlets.
So, first question:
What is going to happen these existing apps in iOS 6? Will they leak ?
and second one:
What is the new recommended way to release an IBOutlet property ? In dealloc method ?
For the first Question:
Your ViewController will receive didReceiveMemoryWarning method callback and you can nil out the view & other components in this method
For Reference Do Check WWDC 2012 video Session on EVOLUTION OF VIEW CONTROLLER, in case you haven't (I Believe they are available only for registered developers, but not sure).
Answer to your second one.
[object release]; in dealloc. No need to assign nil to object before releasing.
I recommend you to use weak property for the IBOutlets like
#property (weak) IBOutlet UILabel * labelText;
That way you don't need to do anything in dealloc. In iOS 6, simply ViewDidUnload won't call, iOS5 or earlier it is just call when memory warning have occur.
and second one: What is the new recommended way to release an IBOutlet
property ? In dealloc method ?
What is the "old" recommended way? You must always release retained instance variables in dealloc; it has always been this way and continues to be this way.
It was just that in viewDidUnload (which is only called for low memory) you could also set your properties to nil.
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.
My dilemma is as follows:
I have a custom subclass of UIImage (I've added some serialization methods i.e. initWithCoder, encodeWithCoder), and I would like to apply my custom subclass as a variable to a UIImageView, or at least a subclass of UIImageView.
As you are aware, UIImageView has a variable called "image", that is of type UIImage. I'd like to override this variable with my subclass.
My goal is to have a UIimageView that will respond to archivedDataWithRootObject without crashing with the encodeWithCoder message is sent to the variable image. If there is a smarter way to get there, I'm open to suggestions.
Thank you!
[edit] I think one possible route is through some type of casting...However:
UIImage *image = [[UIImage alloc] init];
MLImage *mlImage = [[MLImage alloc] init];
mlIamge = (MLImage*)image;
When I mouse-over mlImage after the second line executes, I can see that it is of type MLImage. However, even with the cast, after the third line executes mlImage becomes a UIImage. What do I need to do to change the type of image to MLImage?
[/edit]
Be careful with your terminology. It's not possible to override a property—the UIImageView will still have its own image property, it won't be replaced. You're trying to override the accessors (-image and -setImage:).
And you're right, casting is a better route. But your example has a problem: that cast is illegal. When you do [[UIImage alloc] init], you're creating an object of type UIImage. Nothing is going to change that, including your cast. Casting is a way of telling the compiler (in your case) "I know you think that this UIImage* is, well, a UIImage, but it's really a MLImage." In this case, that's a lie, since it really is a UIImage—you allocated it right there.
What you can do, though, is stick an actual MLImage into the image property of a UIImageView. For example:
MLImage *myImage = [[MLImage alloc] init];
myView.image = myImage;
And then somewhere else:
MLImage *myImage = (MLImage *)(myView.image);
And you'll get back your custom image object. But it has to have been an MLImage in the first place.