error when using parse functions outside of the app delegate - ios

Using Xcode 6 beta 6 to set up my app with parse.com. I followed the instructions listed here and got the framework imported into my app and added the bridged header etc. I then added my app keys into my app delegate
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
// Override point for customization after application launch.
Parse.setApplicationId("app key here", clientKey: "client key here")
var testObject = PFObject(className: "test")
testObject["foo"] = "bar"
testObject.saveInBackground()
return true
}
and that worked fine. I verified the test object was created in the data browser and thought I was set. then I started working on implementing logon into my app. in my first view controller I create a current user variable and my app crashes with the following error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'You have to call setApplicationId:clientKey: on Parse to configure Parse.'
Well I did set it, and it works in my app delegate, but for some reason, any parse code outside the app delegate causes this crash. I even pasted the test code again in my view controller and it doesnt even autocomplete anything after the first line of parse related code
class HomeViewController: UITableViewController {
var testObject = PFObject(className: "test")
//this line after the first has a "expected expression error" and no parse methods get autocompleted
testObject["foo"] = "bar"
testObject.saveInBackground()
has anyone else had this problem? is it a problem with xcode 6?

While working on another app I realized what I had done when I had this problem. I was trying to initialize a property to store the current user, but I was doing it outside of view did load so it must have been getting called before the app delegate call to configure parse even ran. After initializing it inside of viewDidLoad instead of when declaring the property it worked fine.

Related

Accidentally overriding getter with swift extension - Only during runtime when app enters foreground again

The last 2 days i brooded over a strange behavior i found in my iOS app. It was one of these moments when you start to have doubts about everything. I found the problem and fixed it. But i want to write this here to search for answers and gain knowledge about the system behind.
I am the developer of "Controller for HomeKit", an app to control HomeKit devices. In HomeKit you have HMActionSets to execute many changes at once. E.g. Turn on all lights.
Executing HMActionSet is a basic functionality and worked always. Here with a swipe of UITableViewCell.
let performAction = UIContextualAction(style: .normal, title: AppStrings.Actions.perform, handler: { (ac: UIContextualAction, view: UIView, success: #escaping (Bool) -> Void) in
self.home?.executeActionSet(selectedActionSet, completionHandler: { (error: Error?) in
if let err = error {
UIApplication.printToConsole(text: err)
success(false)
return
}
success(true)
})
})
BUT suddenly it stopped working flawlessly with a new development version. It took me a while to reproduce the situation, when it wasn't executing the action set.
Every time i start the app from scratch, everything works.
If i execute the HMActionSet right after navigating from the previous UIViewController, everything works. (Most common use case)
It stops working when being in the view, press the home button, reentering the app. After that all executions won't work, until going one view backwards and forward again.
Console logs this error:
Error Domain=HMErrorDomain Code=2 "Object not found." UserInfo={NSLocalizedDescription=Object not found.}
I walked backwards every commit until the problem was solved. After digging in the dark in a too big commit, i found the root cause.
But why am i not getting compile errors? Why does going to the home screen breaks it?
For a new feature i needed a new way to identify a HomeKit object on multiple devices, because the .uniqueIdentifier parameter is salted on every device.
import Foundation
import HomeKit
protocol Identifyable {
func getUniqueIdentifier() -> String?
}
extension HMActionSet: Identifyable {
func getUniqueIdentifier() -> String? {
return self.name.toBase64()
}
}
I created a swift protocol and made an extension to HMActionSet. Of course now that i found the error it looks stupid, to name the method like a getter. But this should not be the discussion now. It seems like this methods overrides the attribute of HMActionSet. When executing the actionSet internal functions accidentally use the wrong uniqueIdentifier, therefore the error is correct. (No object found).
/*!
* #brief A unique identifier for the action set.
*/
#available(iOS 9.0, *)
open var uniqueIdentifier: UUID { get }
If i name the method func uniqueIdentifier() -> String? Xcode immediately shows me a warning.
Method 'uniqueIdentifier()' with Objective-C selector 'uniqueIdentifier' conflicts with getter for 'uniqueIdentifier' with the same Objective-C selector
As i know HomeKit is written in Objective-C. I am using swift 4.
My questions to you:
Why are there no compiler errors (getUniqueIdentifier())?
If its a runtime problem mixing a swift extension into a objective-c framework, why does it only occur when reentering the app and not at the first start or later?
Looking forward to read your explanations about the problem that stole my sleep. :)

SharkORM Encrypted properties issue in iOS Swift 3

I'm working on iOS project with DB, I am using SharkORM and integrate it to my project using cocoa pods, my project is built using Swift 3.
Everything is working perfectly, but now I need to add encrypted values to the DB and in order to test it I added a very simple code,
I created a "User" class in which I defined a "test" property, this property is of type Double:
dynamic var test: Double = 0;
I also added the following code to the class to define "test" as encrypted property:
override class func encryptedPropertiesForClass() -> [Any]! {
return ["test"]
}
in order to read/write this property I did the following:
print(User.currentUser.test)
User.currentUser.test = 10
User.currentUser.commit()
print(User.currentUser.test)
Please note that current user is a singleton instance and it is being read from the DB. However, I'm getting the following exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SRKEncryptedObject doubleValue]: unrecognized selector sent to instance
Any idea why this is happening? thanks in advance.

ObjC class method is not called. GDB playing games?

I have a custom UITableViewController that I am trying to use to manage a UITableView. The flow of my code in the main UIViewController that contains the UITableView goes like below:
_messagesTableVC = [[AllMessagesTableViewController alloc] init];
_allMessageTableView.dataSource = _messagesTableVC;
_allMessageTableView.delegate = _messagesTableVC;
[_allMessageTableView reloadData];
The AllMessagesTableViewController custom UITableViewController class is initialized, it does any processing needed and I set the _allMessageTableView (the UITableView)'s delegates to my custom class.
When I run this code, the program acts as if the custom class is not there but no errors occur. It seems as that NO methods in the custom class are called, no init, no initWithCoder, nothing (I have set breakpoints and checked ;)).
As you can see in the screenshot below, I have set a breakpoint after a custom method refreshData in the custom class that I set to return YES. I assign the return value of refreshData to a local variable test.
In the debugger:
_messagesTableVC custom class does not appear to be nil.
test does not appear to exist.
Not shown here, but when I try to run [_messagesTableVC refreshData] in the debugger it says error: Execution was interrupted, reason: Attempted to dereference an invalid ObjC Object or send it an unrecognized selector.
The process has been returned to the state before expression evaluation.. So is _messagesTableVC actually nil??
What could be causing these problems or is GDB playing games? This is a Messages app extension in case that makes any difference. Thanks.
Update: Here is the code for the custom class init and refreshData
- (instancetype)init {
self = [super init];
if (!self)
return nil;
return self;
}
- (BOOL)refreshData {
return YES;
}
Update2: I created a blank working project and copy pasted the exact files into my original project (because it is an iMessage extension to a big iOS app). It turns out the Xcode is running the older build of the app even after I cleaned the project and changed the UITableView delegate to supply a different text.
I created a Messages Extension for the same project in the past and deleted the target while keeping the files in the project. When I re-added the Messages Extension to the project, Xcode kept running the older build of the app.
I fixed the issue with Xcode running an older version of the app by:
Clean All
Delete Messages Extension target from project
Backup existing Message Extension code to a directory outside the project. Then delete the Messages app group and directory from the project.
Delete the Messages Extension build scheme from project.
Delete project Derived Data directory.
Restart Xcode, create new Messages Extension target in project, and import saved code.

Parse 'Quick Start' with Swift - 'PFObject' does not have a member named 'subscript'

This is my first attempt with Parse on Swift, and I've followed the quick start guide on Parse's website as seen here: https://parse.com/apps/quickstart#parse_data/mobile/ios/swift/existing
Unfortunately I get this error, 'PFObject' does not have a member named 'subscript'. I have followed the example code and instructions exactly as they are written and have redone this several times but with the same result. I really fail to see where I've gone wrong with this particularly as it's straight off the site. I'm on Xcode 6.4 targeting iOS SDK 8.4 using version 1.8.3 of the Parse library.
This is the code on the ViewController in the viewDidLoad method (I have remembered to include import Parse)
let testObject = PFObject(className: "TestObject")
testObject["foo"] = "bar"
testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
println("Object has been saved.")
}
and this is the code I've added to AppDelegate. Again, I have imported Parse and Bolts as specified in the guide. This is the only code I have changed, the rest is as a standard blank single-view application would be. I have redacted the application ID and client key.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Parse.enableLocalDatastore()
Parse.setApplicationId("-redacted-",
clientKey: "-redacted-")
PFAnalytics.trackAppOpenedWithLaunchOptions(launchOptions)
}
Any ideas as to how I might fix this or where I might have gone wrong?
You might wait for a better answer in which somebody explains swift unwrapping and optional types as it relates to parse objects (I wish I was qualified to give such an answer). In the meantime a quick fix is to bypass the object["foo"] sugar, and use the the functional form of property access, like object.objectForKey("foo").
I tried it and have the same result.
I also did try to do the
testObject.setValue("bar", forKey: "foo")
And same error occur. Seem like it is inserting "nil" instead of the value or object. I don't why.
What I can suggest though, is use the Objective-C files in Parse.com and then create a bridging header file.
Then do the code provided in Swift language - the one in the AppDelegate.swift and the one with the viewDidLoad.
The code should work.
I think there must be a problem/incompatibility with their new framework for the Swift Language . I'm not sure about it.
Incase the same error occurs, use the
testObject.setValue("bar", forKey: "foo")
in exchange with:
testObject["foo"] = "bar"
Though I read this...
I don't know if this is related to the problem here on their starter project:
'PFObject' does not have a member named 'subscript'

Initialising swift view controller with nib name in objc class

In my app I have a view controller written in Swift. I imported it in to app delegate which is written in objective c. I try to create an object of the swift view controller like this
ListAllSongsViewController *songListVC = [[ListAllSongsViewController alloc]initWithNibName:#"ListAllSongsViewController" bundle:nil];
The ListAllSongsViewController is written in swift. The project compile without any issue but when executing the above line the app crashes & stops at init method of ListAllSongsViewController
There is nothing in the log, it just stops. Zombie & All exception break points are enabled.
P.S. It only crashes in device (iOS 7.1), but works fine in simulator
Update :
Getting the same issue even if I use the default swift initialiser
ListAllSongsViewController(nibName: "ListAllSongsViewController", bundle: nil)
Usually occurs when you passed a wrong nibName. Considering it crashes only in device, I think you've made a mistake about the case of the string ListAllSongs, because the Mac/Simulator's file system is case insensitive while the device is not.

Resources