Sample code that produces memory leak (controller is not collected by GC):
public class SampleViewModel
{
public string TextValue { get; set; }
}
public class SampleViewController : UIViewController
{
private Binding _binding;
private SampleViewModel ViewModel { get; } = new SampleViewModel();
private UITextField Field { get; } = new UITextField();
public override void ViewDidLoad()
{
base.ViewDidLoad();
View.AddSubview(Field);
_binding = this.SetBinding(() => ViewModel.TextValue, () => Field.Text, BindingMode.TwoWay);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Console.WriteLine("I am disposed");
}
}
If you run it on simulator "I am disposed" message is never logged.
If I change BindingMode to OneWay, it is displayed immediately when there is no reference to the sample controller instance (i.e. pop from navigation controller, on simulator objects are collected immediately).
I think that "ObserveTargetEvent" (that is called internally for TwoWay binding) produces that leak.
Am I wrong somewhere? or using binding system wrong way?
Related
Good day
I have code that worked on the old Pick pack and ship screen, the code would do a couple of changes on a QR code and then send it in to Acumatica.
With the new changes in Acumatica this is not possible any more.
What is the correct way to hook into the new (version 22) process barcode code?
Originally I could do this:
using WMSBase = PX.Objects.IN.WarehouseManagementSystemGraph<PX.Objects.IN.INScanReceive, PX.Objects.IN.INScanReceiveHost, PX.Objects.IN.INRegister, PX.Objects.IN.INScanReceive.Header>;
using PX.Objects;
using PX.Objects.IN;
namespace ExtScannerCode
{
public class INScanReceiveHostExtCustomPackage : PXGraphExtension<INScanReceive, INScanReceiveHost>
{
public static bool IsActive() => true;
#region Overrides ProcessItemBarcode
//ProcessItemBarcode
public delegate void ProcessItemBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessItemBarcode(string barcode, ProcessItemBarcodeDelegate baseMethod)
{
baseMethod?.Invoke(barcode);
}
#endregion
#region Overrides ProcessLotSerialBarcode
//ProcessLotSerialBarcode
public delegate void ProcessLotSerialBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessLotSerialBarcode(string barcode, ProcessLotSerialBarcodeDelegate baseMethod)
{
baseMethod?.Invoke(barcode);
}
#endregion
#region Overrides ProcessExpireDate
//ProcessLotSerialBarcode
public delegate void ProcessExpireDateDelegate(string barcode);
[PXOverride]
public virtual void ProcessExpireDate(string barcode, ProcessLotSerialBarcodeDelegate baseMethod)
{
baseMethod?.Invoke(barcode);
}
#endregion
}
[PXProtectedAccess]
public abstract class INScanReceiveHostExtProtectedAccess : PXGraphExtension<INScanReceiveHostExtCustomPackage, INScanReceive, INScanReceiveHost>
{
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessItemBarcode(string barcode);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ApplyState(string state);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessLotSerialBarcode(string barcode);
}
}
With the new layout I am a bit lost, how would I hook into the new WarehouseManagementSystem? to process my barcodes
Referencing the private articles in the Acumatica Community site, you need to use an extension that has already been declared for each graph. For Pick Pack and Ship, the class definition would be
public class PickPackShipExt : PickPackShip.ScanExtension
{
}
From there, you would override the DecorateScanState function. There is an existing functionin the solution library, to show as an example. The code file is PX.Objects.SO\WMS\Modes\PickModes.cs.
You would inject into the state you are checking. Search for the graph you are overriding, so you can list states. For example, pick pack ship has these states:
protected override IEnumerable<ScanState<PickPackShip>> CreateStates()
{
yield return new ShipmentState();
yield return new LocationState();
yield return new InventoryItemState() { AlternateType = INPrimaryAlternateType.CPN, IsForIssue = true, SuppressModuleItemStatusCheck = true };
yield return new LotSerialState();
yield return new ExpireDateState() { IsForIssue = true };
yield return new ConfirmState();
yield return new CommandOrShipmentOnlyState();
}
So lets say we want to interject the lot serial number barcode reader. In this example, we want to add an X in front of what is scanned.
public class PickPackShipExt : PickPackShip.ScanExtension
{
[PXOverride]
public virtual ScanState<PickPackShip> DecorateScanState(ScanState<PickPackShip> original, Func<ScanState<PickPackShip>, ScanState<PickPackShip>> base_DecorateScanState)
{
var state = base_DecorateScanState(original);
//are you in pick mode?
if (state.ModeCode == PickMode.Value)
{
//are you scanning lot serial information?
if(state is LotSerialState lotSerialState)
{
//add some sort of validation/transoformation
lotSerialState.Intercept.GetByBarcode.ByOverride((basis, barcode, del) =>
{
//call the delegate, which just trims the barcode
string newBarcode = del(barcode);
//do something else with the barcode to transform. This example, add an X to the beginning and return
newBarcode = "X" + newBarcode;
return newBarcode;
});
}
}
return state;
}
}
You can search the solution for the state, and check the functions that are called. For example, the lot serial state code is:
public class LotSerialState : EntityState<string>
{
public const string Value = "LTSR";
public class value : BqlString.Constant<value> { public value() : base(LotSerialState.Value) { } }
public override string Code => Value;
protected override string StatePrompt => Msg.Prompt;
protected override bool IsStateActive() => Basis.ItemHasLotSerial;
protected override string GetByBarcode(string barcode) => barcode.Trim();
protected override Validation Validate(string lotSerial) => Basis.IsValid<WMSScanHeader.lotSerialNbr>(lotSerial, out string error) ? Validation.Ok : Validation.Fail(error);
protected override void Apply(string lotSerial) => Basis.LotSerialNbr = lotSerial;
protected override void ReportSuccess(string lotSerial) => Basis.Reporter.Info(Msg.Ready, lotSerial);
protected override void ClearState() => Basis.LotSerialNbr = null;
[PXLocalizable]
public abstract class Msg
{
public const string Prompt = "Scan the lot/serial number.";
public const string Ready = "The {0} lot/serial number is selected.";
public const string NotSet = "The lot/serial number is not selected.";
}
}
I hope this helps everyone get their customizations working.
I have created new CustomView.xib file and associated to code-behind class. But when i try to initialise the view, the app getting crashed as below mentioned error.
MonoTouch: Could not install sigaction override, unexpected sigaction implementation.
NSBundle.MainBundle.LoadNib("CustomView", this, null); // App crashes here.
CS class file:
public partial class CustomView : UIView
{
public CustomView(IntPtr handle) : base(handle)
{
}
public override void AwakeFromNib()
{
base.AwakeFromNib();
}
}
Designer class:
[Register("CustomView")]
partial class CustomView
{
[Outlet]
UIKit.UIView contentView { get; set; }
void ReleaseDesignerOutlets ()
{
if (contentView != null) {
contentView.Dispose ();
contentView = null;
}
}
}
Note:
Build Action is set to interfaceDefinition.
File owner of the xib is set the class name "CustomView"
AwakeFromNib override method also implemented.
Thanks in advance.
Edited:
We came across with similar kind of issue after a long time but with different exceptions says "Object Null Reference" on "contentView" in the AwakeFromNib method. App crashes when you try to access the ContentView inside the AwakeFromNib method. This happened only on iOS 9.3.x. The following fix might help someone if they face the same kind of issue.
[Export("initWithFrame:")]
public SampleHeaderView(CGRect frame) : base(frame)
{
Initialize();
}
[Export("initWithCoder:")]
public SampleHeaderView(NSCoder coder) : base(coder)
{
Initialize();
}
public override void AwakeFromNib()
{
base.AwakeFromNib();
}
private void Initialize()
{
if (this.ContentView != null)
{
this.ContentView.BackgroundColor = UIColor.Red();
}
}
I am working on a game in C#.
I have a list of events, that can happen. E.g
List<Event> _events = new List<Event>();
_events.Add(new Event("A goblin approaches", 2));
_events.Add(new Event("A gang of thieves approaches", 3));
_events.Add(new Event("Some money has been stolen", 3));
_events.Add(new Event("Three goblins approach", 4));
_events.Add(new Event("A guard dies of unknown causes",4));
The string in the Event constructor is the event name and the number is the difficulty.
I was wondering if I could also add code into the constructor that can be run later on if the event is called. I'd like different code in each event.
Something like
_events.Add(new Event("Some money has been stolen", 3, "Supply.Gold = Supply.Gold -50"));
_events[2].runcode
I hope this makes sense, thanks
With this approach you can create events with simple implementation. And also difficult events with a lot of code (by extending Event class).
public class EventContext
{
public int Gold { get; set; }
}
public interface IEvent
{
void Do(EventContext context);
}
public abstract class Event : IEvent
{
protected Event(string title, int difficulty)
{
Title = title;
Difficulty = difficulty;
}
public string Title { get; private set; }
public int Difficulty { get; private set; }
public abstract void Do(EventContext context);
}
public class SimpleEvent : Event
{
private readonly Action<EventContext> _callback;
public SimpleEvent(string title, int difficulty, Action<EventContext> callback)
: base(title, difficulty)
{
_callback = callback;
}
public override void Do(EventContext context)
{
_callback(context);
}
}
internal class Program
{
private static void Main(string[] args)
{
var gameContext = new EventContext {Gold = 100};
var events = new List<IEvent>();
events.Add(new SimpleEvent("Some money has been stolen", 3, context => context.Gold -= 10));
events.First().Do(gameContext);
}
}
But I believe it can be better to separate event type and event handler.
I have a javafx design in the file javafx.fxml where the root element has the following attribute
fx:controller="de.roth.jsona.javafx.ViewManagerFX"
This controller class has a singleton machanism and is binded with some ui-elements.
public class ViewManagerFX {
private static ViewManagerFX instance = new ViewManagerFX();
#FXML
private Slider volumeSlider;
#FXML
private Label volumeLabel;
public IntegerProperty volumeValue = new SimpleIntegerProperty();
#FXML
private TabPane musicTabs;
public List<StringProperty> tabNames = new ArrayList<StringProperty>();
public static ViewManagerFX getInstance() {
return (instance);
}
public void initialize() {
// Volume
volumeSlider.valueProperty().bindBidirectional(volumeValue);
volumeLabel.textProperty().bindBidirectional(volumeValue, new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition pos) {
toAppendTo.append(obj);
toAppendTo.append("%");
return toAppendTo;
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null; // no need to be implemented
}
});
volumeValue.set(Config.getInstance().VOLUME);
}
public void addMusicFolderTab(final String t, final ArrayList<MusicListItem> items) {
Platform.runLater(new Runnable() {
#Override
public void run() {
Tab m = new Tab("Test Tab");
musicTabs.getTabs().add(0, m);
}
});
}
}
The method addMusicFolderTab is called from a thread that is used to scan files and directories.
In the initialize method I can access the ui-elements but in the method addMusicFolderTab, that is called from the filescanner-thread, the variable musicTabs is null. Here is the exception:
java.lang.NullPointerException
at de.roth.jsona.javafx.ViewManagerFX$3.run(ViewManagerFX.java:110)
I have no clue, why I can't access the TabPane from outside the initialize method.
Aside from the many questionable patterns used here, the problem is that your ViewManagerFX singleton (besides not being a singleton) never has its instance set.
When using FXML, the Controller is created and loaded dynamically by Reflection from the FXMLoader.
What happens is that by calling ViewManagerFX.getInstance(), you access the a different controller than the one created by the FXMLoader. The instance you access is the one created here:
private static ViewManagerFX instance = new ViewManagerFX();
The quickest way to solve the issue is to set the instance in the initialize() since it's called by the FXMLoader on the instance created by the FXMLoader.
public void initialize() {
instance = this;
// Volume
...
}
I must be overlooking something around getting the fluent-validation to fire within basic Service-Stack application I created.
I have been following the example found here. For the life of me I can't seem to get my validators fire????
Crumbs, there must be something stupid that I'm missing....???
I'm issuing a user request against the User-Service (http://my.service/users), the request goes straight through without invoking the appropriate validator registered.
Request is :
{"Name":"","Company":"Co","Age":10,"Count":110,"Address":"123 brown str."}
Response :
"user saved..."
Here is the code :
1.DTO
[Route("/users")]
public class User
{
public string Name { get; set; }
public string Company { get; set; }
public int Age { get; set; }
public int Count { get; set; }
public string Address { get; set; }
}
2.Validator
public class UserValidator : AbstractValidator<User>
{
public UserValidator()
{
RuleFor(r => r.Name).NotEmpty();
RuleFor(r => r.Age).GreaterThan(0);
}
}
3.AppHostBase
public class ValidationAppHost : AppHostBase
{
public ValidationAppHost()
: base("Validation Test", typeof(UserService).Assembly)
{
}
public override void Configure(Funq.Container container)
{
Plugins.Add(new ValidationFeature());
//This method scans the assembly for validators
container.RegisterValidators(typeof(UserValidator).Assembly);
}
}
4.Service
public class UserService : Service
{
public object Any(User user)
{
return "user saved...";
}
}
5.Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
new ValidationAppHost().Init();
}
Ok....found the issue....I (in error) installed (via nuget) and referenced within my project the FluentValidation.dll with Service-Stack's FluentValidation implementation (see namespace ServiceStack.FluentValidation).
Once I removed this the sole incorrect FluentValidation reference and ensured that my validator extended from the service-stack implementation of the AbstractValidator the validators fired correctly...