I have model like this:
class Session: Object {
dynamic var token: NSData?
}
class SessionsPool: Object {
let sessions = List<Session>()
}
I can request all sessions (normally there is one or zero) with required token
let myToken: NSData = ...
let sessions = self.realm.objects(Session).filter("token == %#", myToken)
It works well.
And I would like to request all pools that has at least one session with required token. And I would like to "observe" this request for updates.
let myToken: NSData = ...
var pools = self.realm.objects(SessionsPool).filter("ANY sessions.token == %#", myToken)
pools.addNotificationBlock { (change) in
// Some code
}
But I can't do it due to error:
*** Terminating app due to uncaught exception 'Unsupported operator',
reason: 'NSData properties cannot be queried over an object link.'
So I can use predicates like token == *someNSData* or like ANY sessions.stringToken == *someNSString*, but not like ANY sessions.token == *someNSData*.
What's wrong with NSData?
That particular query type hasn't been implemented yet: https://github.com/realm/realm-cocoa/issues/4222
However, your query can be refactored to something that Realm does support:
Replace this: ANY sessions.token == %#
With this: SUBQUERY(sessions, $session, $session.token == %#).#count > 0
Related
I have the following:
let processURLS = processingViewController()
Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(processURLS.getURLsToSend),
userInfo: nil,
repeats: true)
When this event is triggered, I received the following error and I'm not sure why this doesn't work
2016-11-09 14:47:00.504932 AcumenJLR[3414:905978] * Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason:
'-[AcumenJLR.homeViewController getURLsToSend]: unrecognized selector
sent to instance 0x100d25c60'
* First throw call stack: (0x1816721c0 0x1800ac55c 0x181679278 0x181676278 0x18157059c 0x18215c8f8 0x1816208f4 0x181620608
0x18161fec4 0x18161dac0 0x18154c048 0x182fd2198 0x1875372fc
0x187532034 0x100114620 0x1805305b8) libc++abi.dylib: terminating with
uncaught exception of type NSException
Here is the getURLsToSend method
func getURLsToSend () {
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<URLsToSend> = URLsToSend.fetchRequest()
let context = getContext()
do {
//Get results
let searchResults = try getContext().fetch(fetchRequest)
print ("num of results = \(searchResults.count)")
//You need to convert to NSManagedObject to use 'for' loops
for urls in searchResults as [NSManagedObject] {
//get the Key Value pairs (although there may be a better way to do that...
//print("\(urls.value(forKey: "url"))")
let currentURL = urls.value(forKey: "url")!
//print(urls.value(forKey: "url")!)
completeLoadAction(urlString: currentURL as! String) { code in
if (code == 200){
context.delete(urls)
}
}
}
} catch {
print("Error with request: \(error)")
}
According to the target / action pattern the method specified in selector must be declared in the class specified in target in this case the current class self.
Either change the target or implement the method in self.
May be you have some paramter in method but you are not sending any value from there
I have a NSUrlRequest in which i call a method User.updateMyObject(id: NSNumber, name: String). Object User has the static properties:
static let appDelegate = UIApplication.shared.delegate as! AppDelegate
static let MOC = appDelegate.managedObjectContext
And several methods for updating/creating/deleting objects.
Now, I have read that you shouldn't use you MOC on different threads. And as far as I know a NSUrlRequest runs asynchronously. How would I then go about calling MyObject.updateMyObject(id: NSNumber, name: String)?
I sometimes get the error:
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
My request looks like this:
let session = URLSession.shared
// The singleton shared session is for basic requests.
// Data tasks send and receive data using NSData objects.
// Data tasks are intended for short, often interactive requests to a server.
let task = session.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
//JSon parsing
MyObject.updateMyObject(id: NSNumber, name: String)
}
task.resume()
MyObject.updateMyObject(id: NSNumber, name: String) looks like this:
static func updateMyObject(id: NSNumber, name: String) {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "MyObject")
let resultPredicate = NSPredicate(format: "id = \(id)")
request.predicate = resultPredicate
do {
let result = try User.MOC.fetch(request).first as! MyObject
result.name = name
User.appDelegate.saveContext()
}
catch {
print("User.updateMyObject: error.")
}
}
This is why the perform and performAndWait methods exist on NSManagedObjectContext-- so that you can safely use the context on different threads. You should use one of them here.
In general, any time you touch anything Core Data related, you need to wrap that code in a call to one of these two methods. The methods take a closure as an argument; put your Core Data code in that closure. The only exception to this rule, ever, is if you used mainQueueConcurrencyType and you know that your code is running on the main queue.
I am trying to use Microsoft Graph iOS SDK and followed the official code sample.
The following code snippet is to get basic profile of all users in the organization:
private func getContactInfo(){
self.graphClient.users().request().getWithCompletion{
(collection: MSCollection?, request:MSGraphUsersCollectionRequest?, error: NSError?) in
if let users = collection {
for user: MSGraphUser in users.value as! [MSGraphUser] {
print(user)
print(String(user.surname.dynamicType))
print(user.mobilePhone)
}
}
}
}
Output Result:
{
businessPhones = (
);
displayName = "Boss";
givenName = "Jack";
id = "30fb78ff-522f-45e7-a9cd-75ba8ee2eca6";
jobTitle = "<null>";
mail = "boss#abc.net";
mobilePhone = "<null>";
officeLocation = "<null>";
preferredLanguage = "<null>";
surname = "\U8a79";
userPrincipalName = "boss#abc.net";
}
ImplicitlyUnwrappedOptional<String>
And runtime exception happened
2016-06-05 17:02:55.302 ABC[76976:915052] -[NSNull _fastCStringContents:]: unrecognized selector sent to instance 0xb59398
2016-06-05 17:02:55.305 ABC[76976:915052] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull _fastCStringContents:]: unrecognized selector sent to instance 0xb59398'
*** First throw call stack:
(
0 CoreFoundation 0x0092c494 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x02640e02 objc_exception_throw + 50
...
When I try to print the null value like mobilePhone, runtime exception occurred. How to detect null value to avoid crashing? Thank you.
Add: MSGraphUser.m snippet used in this case,
#interface MSGraphUser()
{
...
NSString* _mobilePhone;
...
- (NSString*) mobilePhone
{
return self.dictionary[#"mobilePhone"];
}
...
There must be a better swift support, but for now, you could extend the class like what Casey has said.
If you did this, you can check
if user.optMobilePhone is NSNull
The actual extension would look something like this:
extension MSGraphUser {
var optMobilePhone: AnyObject? {
return dictionaryFromItem()["mobilePhone"]
}
}
You can use one way to filter null objects
- (NSString* __nullable) mobilePhone
{
if ([self.dictionary isKindOfClass:[NSString class]])
{
return self.dictionary[#"mobilePhone"];
}
return nil;
}
or
- (NSString* __nullable) mobilePhone
{
if (![self.dictionary isKindOfClass:[NSNull class]]) {
return self.dictionary[#"mobilePhone"];
}
return nil;
}
Many JSON APIs will return null in the JSON document for values that they want to mark explicitely as not present. This is different from keys that will not be reported at all.
The first thing you do is check with the creator of the API or with the documentation how that kind of value should be interpreted. For example, if you ask for the key "user", you might find that the value isn't present at all, that the value is null, or that the value is an empty string. Find out how each value should be interpreted, or if they should be treated the same.
Then since you will need this all the time, you add a function to NSDictionary that will return what you want, and logs things that you didn't expect. You check that a value isn't there at all by checking with if let ... . You check whether a value is null by checking value == NSNull (). And then you make that function return either an optional string or a string.
It looks like mobilePhone can actually return a NSString or NSNull so it should be declared as - (id) mobilePhone. Since it's not, we can extend MSGraphUser
extension MSGraphUser {
var optMobilePhone : String? { return self.dictionary["mobilePhone"] as? String }
}
And then use that computed property to safely access the value:
for obj in users.value {
if let user = obj as? MSGraphUser {
print(user)
print(String(user.surname.dynamicType))
print(user.optMobilePhone ?? "no phone")
}
}
I am trying to catch an error when I execute a FetchRequest with a wrong/inexistent Key/Keypath but the app still crashes.
This is how I created the NSPredicate:
let pred = NSPredicate(format: "(\("WRONGKEY") = %#)", equalTo)
let request = NSFetchRequest()
request.predicate = pred
request.entity = MyEntityDescription
(WRONGKEY is a parameter that could be wrong/nonexistent in the Core Data schema)
And this is the line that cause the error:
var objects = managedContext?.executeFetchRequest(request, error: &error) as? [Model]
This is the error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath keyX not found in entity < NSSQLEntity EN id=2 >'
* First throw call stack: .....
So I have tried to use:
if let objects = managedContext?.executeFetchRequest(request, error: &error) as? [Model] {
println("okkkkkkkk")
} else {
println("error")
}
but doesn't work.
I have tried:
if(error != nil) {
but doesn't work either.
Is there a way to catch the error and avoid that the app crashes?
In Swift, try-catch isn't available. You can switch back to Objective-C, or use a library like this one to add the functionality.
That said, your problem can be solved by keeping track of which keys are valid, instead of implementing a try-and-see approach.
I'm using a sudz-c generated SOAP framework, my service calls seem to work fine, but when I try doing anything with the data, iOS (emulator) crashes.
This is the service call...
[service hentOpgaveliste:self action:#selector(handleToDoList:) userid:userNameTxt.text pdaid:[pdaIdTxt.text intValue]];
For the handleToDoList: I am using the standard method provided in the examples, which successfully NSLogs my result.
....
CXMLNode *xmlResult = (CXMLNode*)value;
NSLog(#"HentToDo: %#", [xmlResult description]);
....
From here, I get the log you see below.
{
hentOpgavelisteResult = {
diffgram = "<null>";
schema = {
element = {
complexType = {
choice = {
element = {
complexType = {
sequence = {
element = "<null>";
};
};
};
};
};
};
};
};
When I attempt to NSLog the child count as seen below, or any of the other CXMLNode instance method for that matter, I get the following exception.
....
NSLog(#"Children %#", [xmlResult childCount]);
....
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary childCount]: unrecognized selector sent to instance
Not sure where to go from here. I've seen blogs such as this talking about issues with touchXML and namespaces, but it appears to me that I have a namespace.
Any ideas would be appreciated, when it comes to SOAP I'm noob class.
This is a common mistake; when logging integers you should use %i instead of %#, like this:
NSLog(#"Children %i", [xmlResult childCount]);
%# is only for logging objects. If you try to log an integer as an object, you get a crash because it thinks it's a pointer to a random place in memory, and tries to call the description method on it.
Also, from the exception that you're getting, xmlResult is an NSDictionary (CFDictionary is the same thing), in which case the method you should be calling is count, not childCount:
NSLog(#"Children %i", [xmlResult count]);
For printing count..
You should use '%d'
ex:
NSLog(#"Children count = %d", [xmlResult childCount]);