Realm crash when try [RLMRealm defaultRealm] - cocoapods

I added Realm pod to my tvos project. However it crash when I just try:
[RLMRealm defaultRealm]
It crash in simulator and device. I created a tvos empty project, added the Realms pod and it works. So I guess it's something related with the current project.
If the problem appear in the line 361 of RLMRealm file.
try {
realm->_realm = [self openSharedRealm:config error:error];
}
catch (SchemaMismatchException const& exception) {
if (configuration.deleteRealmIfMigrationNeeded) {
BOOL success = [[NSFileManager defaultManager] removeItemAtURL:configuration.fileURL error:nil];
if (success) {
realm->_realm = [self openSharedRealm:config error:error];
} else {
RLMSetErrorOrThrow(RLMMakeError(RLMException(exception)), error);
return nil;
}
} else {
RLMSetErrorOrThrow(RLMMakeError(RLMException(exception)), error);
return nil;
}
}
It executes RLMSetErrorOrThrow(RLMMakeError(RLMException(exception)), error); but the error is nil and it doesn't give me any extra information

Related

Xcode error? Use of undeclared identifier [duplicate]

I have following snippets of code that fetches contacts by using block:
if (&ABAddressBookCreateWithOptions != NULL) {
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_sync(dispatch_get_main_queue(), ^{
if (error) {
//...
} else if (!granted) {
//...
} else {
// access granted
//...
}
});
});
It works fine on both 7.1.2 and 8.1.3 versions.
However when I try to change dispatch_get_main_queue to dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0) it works on 8.1.3 but crashes on 7.1.2
if (&ABAddressBookCreateWithOptions != NULL) {
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_sync(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{ // BAD ACCESS
if (error) {
//...
} else if (!granted) {
//...
} else {
// access granted
//...
}
});
});
The QOS_CLASS_ identifiers were introduced in iOS 8. You need to use the DISPATCH_QUEUE_PRIORITY_ identifiers if you want to support iOS 7.

CloudKit didReceiveRemoteNotification not called on the Mac

I am using the following CKNotification Info and this seems to work fine:
CKNotificationInfo *note = [[CKNotificationInfo alloc] init];
note.alertBody = #"Something Happened";
note.shouldBadge = NO;
note.shouldSendContentAvailable = NO;
When something changes on an iOS device, my Mac app receives a Push notification based on a subscription with this notification. However, didReceiveRemoteNotification is never called so I can't process the event. I need to be able to refresh and fetch new changes. How do I do that?
Calling registerForRemoteNotificationTypes: and implementing didRegisterForRemoteNotificationsWithDeviceToken:
should be enough code, and the App ID should include the Push Notifications service.
I'm using CloudKit in a cross-platform (iOS/OS X) app to synchronize favorites between devices like so:
// OS X specific code
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[NSApp registerForRemoteNotificationTypes:NSRemoteNotificationTypeNone];// silent push notification!
}
- (void)application:(NSApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[self.favCon handleCloudKitNotificationWithUserInfo:userInfo];
}
Note the usage of NSRemoteNotificationTypeNone which means silent push notification! This is how I set up CloudKit in the FavController class:
- (void)getOrCreateFavZoneWithCompletionHandler:(successCompletionHandler)handler {
// check if FavZone exists op
__block int createZone = 0;
CKFetchRecordZonesOperation *fetchRecZonesOp = [[CKFetchRecordZonesOperation alloc] initWithRecordZoneIDs:#[[FavController favRecordZoneID]]];
CKModifyRecordZonesOperation *saveRecZoneOp = [[CKModifyRecordZonesOperation alloc] initWithRecordZonesToSave:nil recordZoneIDsToDelete:nil];
fetchRecZonesOp.fetchRecordZonesCompletionBlock = ^(NSDictionary *recordZonesByZoneID, NSError *operationError) {
if (recordZonesByZoneID.count == 0) {// zone doesn't exist
createZone = 1;
CKRecordZone *favZone = [[CKRecordZone alloc] initWithZoneName:UTXAFavZoneName];
saveRecZoneOp.recordZonesToSave = #[favZone];
NSLog(#"Creating new Zone %#", favZone.zoneID.zoneName);
} else {
NSLog(#"Zone %# already exists.", [FavController favRecordZoneID].zoneName);
}
};
// create FavZone op
saveRecZoneOp.modifyRecordZonesCompletionBlock = ^(NSArray *savedRecordZones, NSArray *deletedRecordZoneIDs, NSError *operationError) {
[self successCompletionHandler:(savedRecordZones.count == createZone) error:operationError informDelegate:YES handler:handler];
};
[saveRecZoneOp addDependency:fetchRecZonesOp];
[[FavController favDatabase] addOperation:fetchRecZonesOp];
[[FavController favDatabase] addOperation:saveRecZoneOp];
}
- (void)subscribeToFavChanges:(successCompletionHandler)handler {
// get current subscription
[[FavController favDatabase] fetchSubscriptionWithID:UTXAFavConCKSubscriptionID completionHandler:^(CKSubscription *subscription, NSError *error) {
if (subscription) {
NSLog(#"using existing subscription: %#", subscription);
[self successCompletionHandler:YES error:nil informDelegate:NO handler:handler];
} else {
CKSubscription *sub = [[CKSubscription alloc] initWithZoneID:[FavController favRecordZoneID]
subscriptionID:UTXAFavConCKSubscriptionID
options:0];// "You must specify 0 for this parameter. Zone subscriptions currently do not support any options."
[[FavController favDatabase] saveSubscription:sub completionHandler:^(CKSubscription *subscription, NSError *error) {
NSLog(#"created new subscription: %# %#", subscription, error);
[self successCompletionHandler:(error == nil) error:error informDelegate:YES handler:handler];
}];
}
}];
}
As soon as I add or remove a record on one device, I'll get a notification on all other device, which I handle like so in the FavController class:
/// #abstract Handle push notifications sent by iCloud.
/// #discussion App delegates call this method when they receive a push notification through didReceiveRemoteNotification.
/// Currently, only airport favorites produce a PN, it is of type CKNotificationTypeRecordZone.
/// #param userInfo The userInfo dict tied to each push notification.
- (void)handleCloudKitNotificationWithUserInfo:(NSDictionary *)userInfo {
[self recursivelyCheckForPreviousCloudKitNotifications];
}
- (void)recursivelyCheckForPreviousCloudKitNotifications {
CKFetchNotificationChangesOperation *fetchOp = [[CKFetchNotificationChangesOperation alloc] initWithPreviousServerChangeToken:_defCon.notificationChangeToken];
__weak CKFetchNotificationChangesOperation *weakOp = fetchOp;
fetchOp.notificationChangedBlock = ^(CKNotification *notification) {
[self handleNotification:notification];
};
fetchOp.fetchNotificationChangesCompletionBlock = ^( CKServerChangeToken *serverChangeToken, NSError *operationError) {
NSLog(#"new notification change token: %#", serverChangeToken);
_defCon.notificationChangeToken = serverChangeToken;
if (weakOp.moreComing) {
NSLog(#"more coming!!");
[self recursivelyCheckForPreviousCloudKitNotifications];
} else {
NSLog(#"done handling notification changes.");
}
};
[[FavController favContainer] addOperation:fetchOp];
}
- (void)handleNotification:(CKNotification *)notification {// withCompletionHandler:(successCompletionHandler)handler {
if (notification.notificationType == CKNotificationTypeRecordZone) {// make sure we handle only zone changes
CKRecordZoneNotification *noti = (CKRecordZoneNotification *)notification;
if ([noti.recordZoneID.zoneName isEqualToString:[FavController favRecordZoneID].zoneName]) {
// received an update for the fav zone
[self queuedFavUpdateFromCloud];
} else {
// received an update for an unknown zone
NSLog(#"WARNING: received an update for an unknown zone: %#", noti.recordZoneID.zoneName);
}
} else {
NSLog(#"WARNING: received unknown notification: %#", notification);
}
}
Okay I've finally figured it out. If you use a CKNotificationInfo for your alerts, didReceiveRemoteNotification will NOT be called on the Mac until and unless you set CKNotificationInfo.soundName to an empty string! This looks like a bug only in OS X (10.10 & 10.11 so far) but can be worked around by this simple change.

Get "GeneratedUID" programmatically in COCOA

I'm trying to get system GeneratedUID programmetically, i'm able to get the UID from command line using "dscl . -search /Users GeneratedUID 00052AE8-5000-6000-9007-666F6B666A66"
Can anyone help how to get this GeneratedUID programmetically?
This worked for me. It returns the first GeneratedUID that it finds for the current user, or nil if none are found.
There are lots of errors to handle, making the logic more complicated than it really should be.
-(NSString*) getGeneratedUID {
NSString* retval = nil;
ODSession *mySession = [ODSession defaultSession];
NSError *err;
ODNode *myNode = [ODNode nodeWithSession:mySession type:kODNodeTypeAuthentication error:&err];
NSString* username = NSUserName();
ODQuery *myQuery = [ODQuery queryWithNode: myNode
forRecordTypes: kODRecordTypeUsers
attribute: kODAttributeTypeRecordName
matchType: kODMatchEqualTo
queryValues: username
returnAttributes: kODAttributeTypeStandardOnly
maximumResults: 0
error: &err];
if (err) {
NSLog(#"Error creating current user query: %#", [err localizedDescription]);
}
else {
NSArray* queryResults = [myQuery resultsAllowingPartial:NO error:&err];
if (err) {
NSLog(#"Error executing current user query: %#", [err localizedDescription]);
}
else {
if ( [queryResults count] > 0 ) {
ODRecord* firstQueryResult = [queryResults objectAtIndex:0];
NSArray* uidValues = [firstQueryResult valuesForAttribute:#kDS1AttrGeneratedUID error:&err];
if (err) {
NSLog(#"Error getting GeneratedUID attribute for current user: %#", [err localizedDescription]);
}
else {
if ([uidValues count] > 0) {
retval = (NSString*) [uidValues objectAtIndex:0];
}
else {
NSLog(#"No GeneratedUID values for current username: %#", username);
}
}
}
else {
NSLog(#"No results from current user query for username: %#", username);
}
}
}
return retval;
}
just use the following code to retrive UID.... import the SecurityConfiguration.framework before you add the code..
NSString* GetConsoleUser(uid_t* p_uid, gid_t* p_gid) {
NSString* name = (NSString*)CFBridgingRelease(SCDynamicStoreCopyConsoleUser(
NULL, p_uid, p_gid));
return name ;
}
you have to play around the string to get the "UID".

How to correctly set application badge value in iOS 8?

Old method
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
is now gives error Attempting to badge the application icon but haven't received permission from the user to badge the application.
Then I tried to use new API (that I'm think is related to badge value)
CKModifyBadgeOperation * operation = [[CKModifyBadgeOperation alloc] initWithBadgeValue:50];
[operation setModifyBadgeCompletionBlock:^(NSError *error) {
NSLog(#"%#", error);
}];
[operation start];
But I'm receiving error <CKError 0x165048a0: "Not Authenticated" (9/1002); "This request requires an authenticated account">
How to set badge or receive some new permissions?
In addition to Daij-Djan's answer: it's possible to stack the enums so you can request them all at once. Like follows:
UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
Debug output mentions I should ask for Application Badge permission
to modify the badge under ios8 you have to ask for permissions
let settings = UIUserNotificationSettings(forTypes: UIUserNotificationType.Badge, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
or in objC
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
Additional info for previous posts (in complete to registerUserNotificationSettings):
Apple makes new API for registering notifications and working with badges.
See WWDC 2014 session video , text version
and documentation.
User can change permissions for every UIUserNotificationType (UIUserNotificationTypeBadge, UIUserNotificationTypeSound, UIUserNotificationTypeAlert) in Settings.
Before changing badge you must check permissions.
Code sample from my AppDelegate:
#ifdef __IPHONE_8_0
- (BOOL)checkNotificationType:(UIUserNotificationType)type
{
UIUserNotificationSettings *currentSettings = [[UIApplication sharedApplication] currentUserNotificationSettings];
return (currentSettings.types & type);
}
#endif
- (void)setApplicationBadgeNumber:(NSInteger)badgeNumber
{
UIApplication *application = [UIApplication sharedApplication];
#ifdef __IPHONE_8_0
// compile with Xcode 6 or higher (iOS SDK >= 8.0)
if(SYSTEM_VERSION_LESS_THAN(#"8.0"))
{
application.applicationIconBadgeNumber = badgeNumber;
}
else
{
if ([self checkNotificationType:UIUserNotificationTypeBadge])
{
NSLog(#"badge number changed to %d", badgeNumber);
application.applicationIconBadgeNumber = badgeNumber;
}
else
NSLog(#"access denied for UIUserNotificationTypeBadge");
}
#else
// compile with Xcode 5 (iOS SDK < 8.0)
application.applicationIconBadgeNumber = badgeNumber;
#endif
}
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
The CurrentUserNotificationSettings method is available in the UI application instance and will give you the most up-to-date user notification preferences.
Working with badge number:
[self setApplicationBadgeNumber:0];
instead of
application.applicationIconBadgeNumber = 0;
PS: Checking at compiling (#ifdef __IPHONE_8_0) due to the need to build in Xcode5 and Xcode6.
If you do not have this need, the code can be simplified.
I write a class to handle it when I use swift:
class ZYUtility
{
/// Set badge
class func setApplicationBadgeNumber(badge: Int) {
if ZYUtility.SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO("8.0") {
if UIApplication.sharedApplication().currentUserNotificationSettings().types & UIUserNotificationType.Badge != nil {
UIApplication.sharedApplication().applicationIconBadgeNumber = badge
} else {
println("No permission to set badge number")
}
} else {
UIApplication.sharedApplication().applicationIconBadgeNumber = badge
}
}
/// System check
class func SYSTEM_VERSION_EQUAL_TO(version: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(version,
options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedSame
}
class func SYSTEM_VERSION_GREATER_THAN(version: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(version,
options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedDescending
}
class func SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(version: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(version,
options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedAscending
}
class func SYSTEM_VERSION_LESS_THAN(version: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(version,
options: NSStringCompareOptions.NumericSearch) == NSComparisonResult.OrderedAscending
}
class func SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(version: String) -> Bool {
return UIDevice.currentDevice().systemVersion.compare(version,
options: NSStringCompareOptions.NumericSearch) != NSComparisonResult.OrderedDescending
}
}
update to 8.3, ObjC: we should add Daij-Djan script to replace NSLog(#"access denied for UIUserNotificationTypeBadge"); in Spidy & KepPM solution above. Hope this help s.o.

Is there some straightforward documentation on implementing the Game Center?

I'm trying to implement Game Center into my ios7 game (Xcode 5), but the material in the apple docs and the stuff I've seen online doesn't seem to work very well.
These are the two main methods I'm using wish produce no errors but I don't get any data either:
- (void) retrieveTopTenScores
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
leaderboardRequest.identifier = kLeaderboardID;
leaderboardRequest.range = NSMakeRange(1,10);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
// Handle the error.
}
if (scores != nil)
{
// Process the score information.
} else {
NSLog(#"scores retrieved successfully but no scores in the leaderboard");
}
}];
}
}
-(void)submitMyScore
{
//This is the same category id you set in your itunes connect GameCenter LeaderBoard
GKScore *myScoreValue = [[GKScore alloc] initWithLeaderboardIdentifier:kLeaderboardID];
myScoreValue.value = 5123123;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted");
}
}];
}
So I'm looking for some simple example code to do this successfully...
thanks
rich
I see nothing wrong with your code. Is the player authenticated when you run it?, what error are you getting? If you look for sample GameKit code there is some at iOS 6 Advanced Cookbook from Erica Sadun, but nothing you shouldn't be able to figure out reading the API.
the answer is this for submitting scores in iOS7 to the game centre
Game Center Helper/Manager/Control (Object).h
+ (gamecenterhelper/manager/control *)sharedInstance;
-(void)reportScore:(int64_t)score forLeaderboardID:(NSString*)identifier;
Game Center Helper/Manager/Control (Object).m
-(void)reportScore:(int64_t)score forLeaderboardID:(NSString*)identifier
{
GKScore *scoreReporter = [[GKScore alloc] initWithLeaderboardIdentifier: identifier];
scoreReporter.value = score;
scoreReporter.context = 0;
NSArray *scores = #[scoreReporter];
[GKScore reportScores:scores withCompletionHandler:^(NSError *error) {
}];
}
viewcontroller.h
#import "gamecenterhelper/manager/control"
viewcontroller.m
[[gamecenterhelper/manager/control sharedInstance] reportScore:(int64_t) forLeaderboardID:(NSString*)];
//in place of int64_t place your integer you want uploaded, and instead on NNString* add your leaderboard identifier

Resources