Xcode 10.2 Swift 5: dynamic' property '' must also be '#objc' - realm

After updating my Xcode to 10.2 which includes Swift 5, I tried building my project and got this error.
dynamic property 'openingHours' must also be '#objc'
on this line of code
dynamic let openingHours = List<ShopHourRealm>()
And before updating to Xcode 10.2, I was able to build and compile my project without any error.
Any thoughts why this is happening?

You don't need to specify dynamic for Realm List types. Just
let openingHours = List<ShopHourRealm>()
will suffice.
Based on the examples here https://realm.io/docs/swift/latest/#models
import RealmSwift
// Dog model
class Dog: Object {
#objc dynamic var name = ""
#objc dynamic var owner: Person? // Properties can be optional
}
// Person model
class Person: Object {
#objc dynamic var name = ""
#objc dynamic var birthdate = Date(timeIntervalSince1970: 1)
let dogs = List<Dog>()
}

Related

ZoneVersionTooLowException when working with MockNetwork

cordaVersion = 4.3
tokens_release_version = '1.1-RC06-PRESIGN'
OS = Windows 10
Using a MockNetwork I was testing TokenPointer’s that point to EvolvableTokenType’s (reference states) using the TokenSDK when I got the following error message:
net.corda.core.node.ZoneVersionTooLowException: Reference states requires all nodes on the Corda compatibility zone to be running at least platform version 4. The current zone is only enforcing a minimum platform version of 1. Please contact your zone operator.
I got the same ZoneVersionTooLowException error when using reference states in my contract and testing the flows using MockNetwork.
I fixed it by changing the minimumPlatformVersion to 4 in the testNetworkParameters class and using that to construct my MockNetwork. Here is the snippet in Kotlin.
import net.corda.testing.common.internal.testNetworkParameters
class AssetCreationFlowTests {
private lateinit var network: MockNetwork
private lateinit var a: StartedMockNode
private lateinit var b: StartedMockNode
#Before
fun setup() {
val myNetworkParameters = testNetworkParameters(minimumPlatformVersion = 4)
network = MockNetwork(MockNetworkParameters(
cordappsForAllNodes = listOf(
TestCordapp.findCordapp(AssetContract::class.packageName)
),
networkParameters = myNetworkParameters
)
)
I looked on stackoverflow and found this but I was determined to get a MockNetwork working because it is so handy for testing.
I had to create my MockNetwork manually versus using the defaults. I extracted all the MockNetwork properties from a default build of a MockNetwork:
MockNetwork mockNet = new MockNetwork(new MockNetworkParameters(getTestCordapps()));
Step 1) Build a NetworkParameters object setting the minimumPlatformVersion to 4:
List<NotaryInfo> notaryinfo = Arrays.asList();
NetworkParameters networkParameters = new NetworkParameters(
4,
notaryinfo,
10485760,
524288000,
java.time.Instant.now(),
1,
Collections.emptyMap()
);
Step 2) Create a MockNetworkParameters object using the new NetworkParameters;
MockNetworkParameters mockNetworkParameters = new MockNetworkParameters(
false,
false,
new InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random.Random(),
Arrays.asList(new MockNetworkNotarySpec(new CordaX500Name("Notary Service", "Zurich", "CH"), true)),
networkParameters,
getTestCordapps()
);
NB: getTestCordapps() just returns a List<TestCordapp> that I need for the test I am performing i.e.
private List<TestCordapp> getTestCordapps() {
return ImmutableList.of(
TestCordapp.findCordapp("com.template.contracts"),
TestCordapp.findCordapp("com.template.flows"),
TestCordapp.findCordapp("com.r3.corda.lib.tokens.contracts"),
etc.
etc.
)}
Step 3) Build your MockNetwork with your MockNetworkParameters object:
MockNetwork mockNetwork = new MockNetwork(mockNetworkParameters);
I’ve been using it for a few weeks and it seems to work. If there is a better way please let me know.

iOS 13 Xcode UI test Automation type mismatch

My app uses a WKWebView that is setup in code (this is done because of this bug in iOS 10):
final class HelpViewController: UIViewController {
// …
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(webView)
let margins = view.layoutMarginsGuide
webView.topAnchor.constraint(equalTo: self.back.bottomAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: margins.rightAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: margins.leftAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
webView.navigationDelegate = self
//…
}
My UI test looks like this:
func test_helpButtonShowsHelpText() {
//…
let webView = shopEasyApp.webViews.element
let webViewExists = webView.waitForExistence(timeout: kDefaultUITestTimeout)
XCTAssert(webViewExists, "Web view does not exist")
let webViewIsHittable = webView.isHittable
//…
}
This test run without problems up to iOS 12.
With iOS 13, it stops at the test webView.isHittable with the following error:
Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x600000bdfbb0>.
The log says:
Assertion Failure: ShopEasyBasicUITests.swift:1100: Failed to get matching snapshot: Multiple matching elements found for <XCUIElementQuery: 0x600003efb4d0>.
Sparse tree of matches:
→Application, pid: 71038, label: 'Shop Easy!'
↳Window, {{0.0, 0.0}, {375.0, 812.0}}
↳Other, {{0.0, 0.0}, {375.0, 812.0}}
↳Other, {{0.0, 0.0}, {375.0, 812.0}}
↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
↳WebView, {{16.0, 74.0}, {343.0, 704.0}}
Possibly caused by runtime issues:
Automation type mismatch: computed WebView from legacy attributes vs ScrollView from modern attribute. Input attributes and values: {
"XC_kAXXCAttributeAutomationType" = 46;
"XC_kAXXCAttributeElementBaseType" = UIScrollView;
"XC_kAXXCAttributeElementType" = WKScrollView;
"XC_kAXXCAttributeTraits" = 8589934592;
}
Automation type mismatch: computed Other from legacy attributes vs WebView from modern attribute. Input attributes and values: {
"XC_kAXXCAttributeAutomationType" = 58;
"XC_kAXXCAttributeElementBaseType" = UIView;
"XC_kAXXCAttributeElementType" = WKWebView;
"XC_kAXXCAttributeTraits" = 146028888064;
}
Automation type mismatch: computed Other from legacy attributes vs WebView from modern attribute. Input attributes and values: {
"XC_kAXXCAttributeAutomationType" = 58;
"XC_kAXXCAttributeElementBaseType" = UIView;
"XC_kAXXCAttributeElementType" = WKContentView;
"XC_kAXXCAttributeTraits" = 146028888064;
}
The view hierarchy is the following:
My questions are:
What is wrong with my code, and how to do it correctly?
You have three WebKit views in play which XCTest can see:
WKScrollView
WKWebView
WKContentView
It looks like they have changed the way that elements are given their type on iOS 13, meaning that your view hierarchy now contains multiple elements which resolve to being classed as a WebView. It appears that WKWebView and WKContentView now both resolve to being elements of type WebView, whereas in iOS 12, only the WKScrollView (which, in iOS 13, no longer resolves to being classed as a WebView element) was classed as a WebView.
Now for the query:
shopEasyApp.webViews.element
The query uses element, which is only supposed to be used when you know the query will resolve to a single element. Since there are now 2 results for shopEasyApp.webViews, there is not a single element for element to return. You are able to check for existence because checking XCUIElement's exists property does not require the query to be resolved successfully. However, all other XCUIElement properties do require the query to be resolved, so when isHittable is used, the XCTest engine attempts to resolve the query, finds that the query does not resolve to a single element as expected, and throws this error.
Multiple matching elements found for <XCUIElementQuery: 0x600003efb4d0>
To resolve this, I suggest you modify the query to use the first matching index instead of using element:
shopEasyApp.webViews.elementBound(by: 0)
In the event that there is more than a single WebView element on screen, this query will choose the first element in the list.
I have faced similar issue - there were no webview's descendants.
After investigation it turned out that everything is OK on iOS 13.1 but not on iOS 13.3.
I think it's a simulator's bug.
For all facing the same problem - specify earlier version (13.1) until it's fixed.

Changelog method based on project tracker template

Based on the project tracker I have integrated a changelog into my app that relates my UserSettings model to a UserHistory model. The latter contains the fields FieldName, CreatedBy, CreatedDate, OldValue, NewValue.
The relation between both models works fine. Whenever a record is modified, I can see the changes in a changelog table. I now want add an "undo"-button to the table that allows the admin to undo a change he clicks on. I have therefore created a method that is handled by the widget that holds the changelog record:
function undoChangesToUserRecord(changelog) {
if (!isAdmin()) {
return;
}
var fieldName = changelog.datasource.item.FieldName;
var record = changelog.datasource.item.UserSettings;
record[fieldName] = changelog.datasource.item.OldValue;
}
In theory method goes the connection between UserHistory and UserSettings up to the field and rewrites its value. But when I click on the button, I get a "Failed due to circular reference" error. What am I doing wrong?
I was able to repro the issue with this bit of code:
google.script.run.ServerFunction(app.currentPage.descendants.SomeWidget);
It is kinda expected behavior, because all App Maker objects are pretty much complex and Apps Script RPC has some limitations.
App Maker way to implement it would look like this:
// Server side script
function undoChangesToUserRecord(key) {
if (!isAdmin()) {
return;
}
var history = app.models.UserHistory.getRecord(key);
if (history !== null) {
var fieldName = history.FieldName;
var settings = history.UserSettings;
settings[fieldName] = history.OldValue;
}
}
// Client side script
function onUndoClick(button) {
var history = widget.datasource.item;
google.script.run
.undoChangesToUserRecord(history._key);
}

Not able to get organization form node in alfresco

Using Alfresco Community 5.0.d and not able to get organization from node.
File: pickerresults.lib.js
Method: createPersonResult(node)
function createPersonResult(node)
{
var personObject =
{
typeShort: node.typeShort,
isContainer: false,
properties: {},
displayPath: node.displayPath,
nodeRef: "" + node.nodeRef
}
// define properties for person
personObject.properties.userName = node.properties.userName;
// defining new property for the personObject but
// but not getting any value
personObject.properties.companyname = (node.properties["cm:organization"] ? node.properties["cm:organization"] : "");
personObject.properties.companyname = (node.properties.organization ? node.properties.organization : "");
return personObject;
}
Override the pickerresults.lib.js file by copying it to location as below.
/Applications/alfresco-5.0.d/tomcat/shared/classes/alfresco/extension/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.js
how could I get organization name?
also how could I debug the node properties like logger.log is there but does not work here.
Thanks.
please try to get properties without extra "." in
node.properties.["cm:organization"]
like:
node.properties["cm:organization"]
please refer this doc link
http://docs.alfresco.com/4.0/references/API-JS-ScriptNode.html
properties
Provides access to all the properties of this node. The properties returned are accessed via an associative array. Properties of a node can be accessed in the following ways:
Example: node.properties["name"]
Example: node.properties.name
example i have tried:
var node =people.getPerson("admin");
logger.log(node.properties["cm:email"]);
logger.log(node.properties.email);

Realm + NSClassFromString

Hi everyone and thank you for be reading this.
I am new with Realm and I am stucked with a function that I can't figure out how to build. My intention is to have one function called func delete(className:String, id:Int){ that should be able to delete any object of any Realm class by its ID. The inner code of the function is:
func delete(objectNameV:String, id:Int){
let theClass = NSClassFromString(objectNameV)
// Get the default Realm
let realm = try! Realm()
let queryResult = realm.objects(theClass as! Object.Type).filter("id = \(id)")
try! realm.write {
realm.delete(queryResult)
}
}
But the fact is that let theClass = NSClassFromString(objectNameV) it's allways NIL.
Any help is appreciated, i just need a function that given a realm classname and the id from an object of that class can delete it!
Realm version: 2.0.1
Xcode version: 8
According to the Apple developer docs, classes in Swift are namespaced by their module names. So it's not sufficient to simply write the class name; you must also include their module name as well.
The example Apple used on their website is:
let myPersonClass: AnyClass? = NSClassFromString("MyGreatApp.Person")

Resources