Converting NSEnum from Userinfo in NSNotification fails in Objective c - c++

I want to convert userInfo data from a NSNotification to an enum to use in a switch statement. The notification is coming from a pre-compiled c++ framework with some headerfiles defining te enum.
-(void)updateOTAStatus:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
otaUpgradeStatus status = (otaUpgradeStatus)userInfo[#"status"];
//...
}
Enum definition:
typedef NS_ENUM(NSUInteger, otaUpgradeStatus) {
none = 0,
started = 1,
inProgress = 2,
completed = 3,
failed = 4,
failedLowBattery = 5,
cancelled = 6,
timedout = 7,
forced = 8
};
When debugging I get
Printing description of status:
(otaUpgradeStatus) status = 6178538944
And switch statement fails, when I do the same in Swift:
let status = notification.userInfo?["status"] as? otaUpgradeStatus
I get the right status back, and switch statement works as expected.
What goes wrong here?

An NSDictionary can only hold objects, i.e. instances of (a subclass of) NSObject. Swift has a mechanism to wrap/unwrap values in an
opaque _SwiftValue instance transparently.
But for interoperability with Objective-C you have to put the number
as NSNumber instances into the user info dictionary on the Swift side, e.g.
let notification = Notification(name: ..., object: ...,
userInfo: ["status": NSNumber(value: otaUpgradeStatus.failed.rawValue)])
and extract the integer value on the Objective-C side, e.g.
NSDictionary *userInfo = notification.userInfo;
NSNumber *num = userInfo[#"status"];
otaUpgradeStatus status = num.unsignedIntegerValue;

Related

How to start with IOTA application

i want to develop an IOTA application, but not a messaging application or coin based system. I want an simple example of how to store data in IOTA. For example i want to build an SCM or even an simple login/registration app. Can anyone guide me? Any sample application? i try to run https://github.com/domschiener/leaderboard-example But getting same error like https://github.com/domschiener/leaderboard-example/issues/6 How to run this.
Storing text data on the tangle is not that difficult. The following are snippets from my tangle-based app. I used IOTA's API Java wrapper library Jota.
1) Connect to IOTA node. You can find a list of nodes here https://nodes.iota.works. Also you can set up your own full node and use it instead of an external one.
final String protocol = "https";
final String url = "tuna.iotasalad.org";
final String port = "14265";
IotaAPI iotaServer = new IotaAPI.Builder().protocol(protocol).host(host).port(port).build();
2) Covert your text into trytes
String trytes = TrytesConverter.toTrytes("my text");
3) Prepare and send transaction to tangle
private static final String SEED = "IHDEENZYITYVYSPKAURUZAQKGVJERUZDJMYTANNZZGPZ9GKWTEOJJ9AAMXOGZNQLSNMFDSQOTZAEETA99";//just a random one
private static final int MIN_WEIGHT_MAGNITUDE = 14;
private static final int DEPTH = 9;
private static final int TAG = "mytag"; //optional
String tangleHash = prepareTransfer(createAddress(), trytes);
public String createAddress() throws ArgumentException {
GetNewAddressResponse res = iotaServer.getNewAddress(SEED, 2, 0, false, 1, false);
return res.getAddresses().get(0);
}
public String prepareTransfer(String address_seclevel_2, String trytes) throws ArgumentException {
List<Transfer> transfers = new ArrayList<Transfer>();
transfers.add(new Transfer(address_seclevel_2, 0, trytes, TAG));
SendTransferResponse str = iotaServer.sendTransfer(SEED, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null,
null, false, false);
if(str.getSuccessfully()!=null){
//Transfer successfully!
for(Transaction tx: str.getTransactions()) {
return tx.getHash();
}
}
return "Handle error here. Something went wrong!";
}

NSKeyedArchiver.archivedData crashing for NSDictionary of objects

In converting an app from Objective C to Swift 3, many of the data structures are no longer classes, but structs. In a particular function, I need to use the NSKeyedArchiver.archivedData(withRootObject: function to encapsulate these structs before sending them over a network connection, so I've converted them to good old Objective-C objects. But the code below still crashes when I attempt to encode them.
enum CustomDataType:Int
{
case CustomDataType0 = 0
case CustomDataType1 = 1
case CustomDataType2 = 2
case CustomDataType3 = 3
case CustomDataType4 = 4
}
func send(dataType:CustomDataType, dictionary: Dictionary<String, Any>)
{
// convert everything into objects
let dataTypeObject:NSNumber = NSNumber(integerLiteral: dataType.rawValue)
let dataValueObject:NSDictionary = dictionary as NSDictionary
let dataTypeObjectKey:NSString = "regis-type"
let dataValueObjectKey:NSString = "regis-value"
let transmissionData:NSDictionary = [dataTypeObjectKey : dataTypeObject, dataValueObjectKey :dataValueObject]
let data = NSKeyedArchiver.archivedData(withRootObject: transmissionData)
The last line produces a crash, and I'm baffled. Any thoughts?
Crash log:
[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x170448df0
2017-02-22 17:10:10.338319 cd Swift[441:56841] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x170448df0'

Scala.js js.Dynamic usage leads to a recursively infinite data structure

I'm trying to use Google Visualizations from Scala.js. I generated the type definitions using TS importer and the relevant portion it generated is:
#js.native
trait ColumnChartOptions extends js.Object {
var aggregationTarget: String = js.native
var animation: TransitionAnimation = js.native
var annotations: ChartAnnotations = js.native
// ... more
}
#js.native
trait TransitionAnimation extends js.Object {
var duration: Double = js.native
var easing: String = js.native
var startup: Boolean = js.native
}
Now, I'm trying to figure out how to actually use this and came up with:
val options = js.Dynamic.literal.asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal.asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
options.animation.duration = 2000
options.title = "Test Chart"
options.width = 400
options.height = 300
This works if I don't set the animation settings, but fails with the chart showing "Maximum call stack size exceeded" if I do.
I debugged, and found the following:
So animation contains a reference to itself, but I don't feel like this should happen based on the code above.
Ideas how to fix it?
Any other suggestions on how to best use the generated types to provide a type-safe way of creating the JavaScript objects which Google Visualizations expects? I tried new ColumnChartOptions {} which looks cleaner than js.Dynamic but that failed with "A Scala.js-defined JS class cannot directly extend a native JS trait."
P.S. I'd like to note that
options.animation = js.Dynamic.literal(
easing = "inAndOut",
startup = true,
duration = 2000
).asInstanceOf[TransitionAnimation]
actually works, but isn't type-safe (a mis-spelling of duration to durration won't be caught).
Your code lacks () when calling literal(), so the fix would be:
val options = js.Dynamic.literal().asInstanceOf[ColumnChartOptions]
options.animation = js.Dynamic.literal().asInstanceOf[TransitionAnimation] // comment this and the next line and chart will appear
In Scala (and therefore in Scala.js), the presence or absence of () is sometimes meaningful. literal is the singleton object literal, whereas literal() calls the method apply() of said object.

Dynamics GP Web Services: SalesInvoice Creation with Lot Allocation

I'm trying to use the following code to create a new SalesInvoice based on an existing SalesOrder:
SalesInvoice invoice = new SalesInvoice();
invoice.DocumentTypeKey = new SalesDocumentTypeKey { Type = SalesDocumentType.Invoice };
invoice.CustomerKey = originalOrder.CustomerKey;
invoice.BatchKey = originalOrder.BatchKey;
invoice.Terms = new SalesTerms { DiscountTakenAmount = new MoneyAmount { Value = 0, Currency = "USD", DecimalDigits = 2 }, DiscountAvailableAmount = new MoneyAmount { Value = 0, Currency = "USD", DecimalDigits = 0 } };
invoice.OriginalSalesDocumentKey = originalOrder.Key;
List<SalesInvoiceLine> lineList = new List<SalesInvoiceLine>();
for (int i = 0; i < originalOrder.Lines.Length; i++)
{
SalesInvoiceLine line = new SalesInvoiceLine();
line.ItemKey = originalOrder.Lines[i].ItemKey;
line.Key = new SalesLineKey { LineSequenceNumber = originalOrder.Lines[i].Key.LineSequenceNumber; }
SalesLineLot lot = new SalesLineLot();
lot.LotNumber = originalOrder.Lines[i].Lots[0].LotNumber;
lot.Quantity = new Quantity { Value = 2200 };
lot.Key = new SalesLineLotKey { SequenceNumber = originalOrder.Lines[i].Lots[0].Key.SequenceNumber };
line.Lots = new SalesLineLot[] { lot };
line.Quantity = new Quantity { Value = 2200 };
lineList.Add(line);
}
invoice.Lines = lineList.ToArray();
DynamicsWS.CreateSalesInvoice(invoice, DynamicsContext, DynamicsWS.GetPolicyByOperation("CreateSalesInvoice", DynamicsContext));
When executed, I receive the following error:
SQL Server Exception: Operation expects a parameter which was not supplied.
And the more detailed exception from the Exception Console in Dynamics:
Procedure or function 'taSopLotAuto' expects parameter '#I_vLNITMSEQ',
which was not supplied.
After a considerable amount of digging through Google, I discovered a few things.
'taSopLotAuto' is an eConnect procedure within the Sales Order Processing component that attempts to automatically fill lots. I do not want the lots automatically filled, which is why I try to fill them manually in the code. I've also modified the CreateSalesInvoice policy from Automatic lot fulfillment to Manual lot fulfillment for the GP web services user, but that didn't change which eConnect procedure was called.
'#I_vLNITMSEQ' refers to the LineSequenceNumber. The LineSequenceNumber and SequenceNumber (of the Lot itself) must match. In my case they are both the default: 16384. Not only is this parameter set in the code above, but it also appears in the SOAP message that the server attempted to process - hardly "not supplied."
I can create an invoice sans line items without a hitch, but if I add line items it fails. I do not understand why I am receiving an error for a missing parameter that is clearly present.
Any ideas on how to successfully create a SalesInvoice through Dynamics GP 10.0 Web Services?
Maybe you mess to add the line key to the lot:
lot.Key = new SalesLineKey();
lot.Key.SalesDocumentKey = new SalesDocumentKey();
lot.Key.SalesDocumentKey.Id = seq.ToString();

SubSonic GetPaged method - different index needed in unit test

I'm using SubSonic 3, and am using the ActiveRecord approach. I have a simple query in my controller:
var posts = from p in Post.GetPaged(page ?? 0, 20)
orderby p.Published descending
select p;
The "page" variable is defined as an nullable int (int?).
Here's the problem, when I run the following test, it works fine and passes:
[Test]
public void IndexWithNullPageShouldLoadFirstPageOfRecentPosts()
{
//act
var testPosts = new List<Post>()
{
new Post() {PostID = 1, BlogID = 1, Published = null, Body = "1"},
new Post() {PostID = 2, BlogID = 1, Published = DateTime.Now, Body = "2"},
new Post() {PostID = 3, BlogID = 1, Published = DateTime.Now.AddDays(1), Body = "3"}
};
Post.Setup(testPosts);
//act
var result = controller.Index(null) as ViewResult;
//assert
Assert.IsNotNull(result);
var home = result.ViewData.Model as HomeViewModel;
Assert.IsInstanceOf(typeof(HomeViewModel), home, "Wrong ViewModel");
Assert.AreEqual(3, home.Posts.Count());
//make sure the sort worked correctly
Assert.AreEqual(3, home.Posts.ElementAt(0).PostID);
Assert.AreEqual(2, home.Posts.ElementAt(1).PostID);
Assert.AreEqual(1, home.Posts.ElementAt(2).PostID);
}
However, when I launch the website, it doesn't return any records (and yes, there are records in the live database). Both ways have the "page" variable set to null. I found that if I change the index in "GetPaged" method to 1 instead of 0 - then records are returned on the website... however, as soon as I do that - my tests don't pass anymore. All the documentation I've seen shows that the GetPaged index is zero-based... so I'm a bit confused here.
Any ideas?
Thanks,
Chad
This seems to be a bug/inconsistency in the way GetPaged works with ActiveRecord. As you've already worked out it's using a 1 based index instead of a 0 based index in the ActiveRecord repository. Can you please log this as an issue at github