iOS doesn't support cross-store copies yet EKEvent - ios11

I am getting this NSInternalInconsistencyException error while saving EKEvent on Xcode 9, iOS11.
do {
try eventStore.saveEvent(newEvent, span: .ThisEvent, commit: true)
} catch {
}
Error:
Fatal Exception: NSInternalInconsistencyException iOS doesn't support
cross-store copies yet.

Whenever you are assigning any value to other object means copying one value to other value, so it was sometime sending exception.
In my case:
if(orginalEvent.structuredLocation != nil){
newEvent.structuredLocation = orginalEvent.structuredLocation
}
So, i have replaced with below:
if(orginalEvent.structuredLocation != nil){
if orginalEvent.structuredLocation!.title.characters.count > 0{
let location = EKStructuredLocation(title: orginalEvent.structuredLocation!.title)
if(orginalEvent.structuredLocation?.geoLocation != nil){
location.geoLocation = CLLocation(latitude: (orginalEvent.structuredLocation?.geoLocation?.coordinate.latitude)!, longitude: (orginalEvent.structuredLocation?.geoLocation?.coordinate.longitude)!)
}
newEvent.structuredLocation = location
}
}
So, it is working now.

Don't create and use new EKEventStore(). Just use existing EKEventStore instance.

Related

Cannot assign value of type [Employees] to type 'PublishSubject<[Employees]>

I have successfully parsed json data using URLSession and now I want to add the parsed data to an array. Doing this using an ordinary array works fine, but I'm learning Rx and thus want to use a subject.
So, this works:
var parsedJson = [Employees]()
self.parsedJson = decodedJson.people
But this gives an error:
var parsedJson: PublishSubject<[Employees]> = PublishSubject<[Employees]>()
self.parsedJson = decodedJson.people
Cannot assign value of type '[Employees]' to type 'PublishSubject<[Employees]>'
Here is the URLSession code:
// var parsedJson = [Employees]()
var parsedJson: PublishSubject<[Employees]> = PublishSubject<[Employees]>()
func getJSON(completion: #escaping () -> Void) {
guard let url = URL(string:"https://api.myjson.com/bins/jmos6") else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
do {
let jsonDecoder = JSONDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
jsonDecoder.dateDecodingStrategy = .iso8601
let decodedJson = try jsonDecoder.decode(People.self, from: data)
self.parsedJson = decodedJson.people
completion()
} catch {
print(error)
}
}.resume()
}
Anyone know how to do this and why there is an error in the first place? Doesn't the <> simply indicate which type should be observed? Didn't get .accept() to work either.
EDIT
let parsedJson: BehaviorRelay<[Employees]> = BehaviorRelay(value: [])
self.parsedJson.accept(decodedJson.people)
This worked, but what is the equivalent to BehaviorSubject and PublishSubjuct?
The error message is pretty clear: you have a type-mismatch. You would get the same error message if you tried to assign a String to an Int variable, for example. A PublishSubject is not an array. Its a mechanism (think of it as a pipeline) for sending a stream of certain types of values (here an array of Employees).
You typically use Subjects by subscribing to them like so:
var parsedJson = PublishSubject<[Employee]>()
// the 'next' block will fire every time an array of employees is sent through the pipeline
parsedJson.next { [weak self] employees in
print(employees)
}
The above next block will fire every time you send an array through the PublishSubject like so:
let decodedJson = try jsonDecoder.decode(People.self, from: data)
self.parsedJson.onNext(decodedJson.people)
From your EDIT it seems that you moved on to trying to use a BehaviorRelay. I would recommend reading up on the differences between these two classes before decided which is appropriate for your use case. This article was really helpful to me when trying to learn the differences between the different types of Subjects and Relays: https://medium.com/#dimitriskalaitzidis/rxswift-subjects-a2c9ff32a185
Good luck!
Try
self.parsedJSON.onNext(decodedJson.people)

Why does File.listFiles() throws NullPointerException on some devices?

Please pay attention to all the tests in the following code:
File folder = new File(sFolderPath);
if (folder == null) {
//do nothing
} else {
if (folder.exists()) {
File[] flist = folder.listFiles();
}
}
folder.listFiles() throws the following exception:
java.lang.NullPointerException: Attempt to get length of null array
It rarely happens. I am wondering how this can be possible after passing the tests of null and existence.

LABiometryType in iOS11 always return None

No matter what settings is configured in Device's passcode and touchId settings , LAContext always returns none . It is just throwing me a warning not the exception.
Its only working in XCode 9.1 Beta in iOS11.1 beta as suggested :(
I just figured out the problem! You have to call canEvaluatePolicy for biometryType to be properly set.
Example:
func isFaceIdSupported() -> Bool {
if #available(iOS 11.0, *){
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
return context.biometryType == LABiometryType.typeFaceID
}
}
return false
}
As per the Apple docs for biometryType:
"This property is only set when canEvaluatePolicy(_:error:) succeeds for a biometric policy. The default value is none."
If you use the code from #Ermish, isFaceIdSupported() will return false if there are no enrolled faces on the device.
As per my latest tests shows on iOS SDK 11.1, just call the laContext.canEvaluatePolicy function and do not care about the result, then check the content of laContext.biometryType.
If there are no enrolled faces, the canEvaluatePolicy will fail, but the device supports Face ID.
Got the same issue here, fixed it with the following code. But it only works with the Xcode 9.1 Beta (and iOS 11.1 beta in the simulator).
if (laContext.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: nil)) {
if #available(iOS 11.0, *) {
if (laContext.biometryType == LABiometryType.faceID) {
print("FaceId support")
} else if (laContext.biometryType == LABiometryType.touchID) {
print("TouchId support")
} else {
print("No Biometric support")
}
} else {
// Fallback on earlier versions
}
}
In Xamarin.iOS, you need evaluate the Policy Before:
NSError error;
bool success = context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out error);
if (context.BiometryType == LABiometryType.TouchId)
{
//Do Something
}

Swift crashes when listing to value changes on Firebase

Trying to get my question answered (Retrieve Boolean array from Firebase) I am trying to solve the question by myself. I think I am almost done but 1 thing is bugging me. I want to retrieve a boolean array and store it in a boolean array in my app.
This is what I got:
if snapshot.key == "whatAchievementsunlocked"
{
whatAchievementsUnlocked.removeAll()
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for x in snapshots
{
print(x.value!) //prints 0
var valueForIndexX = x.value as! Int //crash
print(valueForIndexX)
if valueForIndexX == 0
{
whatAchievementsUnlocked.append(false)
}
else
{
whatAchievementsUnlocked.append(true)
}
}
}
}
Why would it crash there? If I use as?, the output would be nil. I also tried to use var valueForIndexX = Int(x.value!) But that gives me an error: Cannot invoke initializer for type Int with an argument list of type (Any). The output of x.value! is clearly an Int, why would this result in an error? The debug just shows "(lldb)". What am I doing wrong?\

Dynamic AutoComplete

When I type a location starting with 'W', the related locations are listed below. But if I erase the already typed location and then type in a different one starting with 'L', then the list shows the previously listed options for the old location first(locations starting with 'W') then the options related to new location are listed.
Because of this the autocomplete list displays the locations starting with 'W' and then the locations starting with 'L',both.
I also tried placing options.removeAll(); as first statement in the filter method.
AutoCompleteTextField ac = new AutoCompleteTextField(options) {
protected boolean filter(String add) {
options.removeAll();
if(add.length() == 0) {
return false;
}
String[] l = searchLocations(add);
if(l == null || l.length == 0) {
return false;
}
for(String s : l) {
options.addItem(s);
}
return true;
}
};
//ac.setMinimumElementsShownInPopup(1);
ac.setMinimumLength(1);
Container c = stateMachine.findContainer(form);
AutoCompleteTextField oldac = (AutoCompleteTextField) stateMachine.findAddress(c);
c.replace(oldac, ac, null);
Is there a way to rectify this?
Thanks!!
Check out this live sample, this issue doesn't occur here so I'm guessing the problem with the preexisting results is related to the way you modified the the model.

Resources