Theos %log doesn't work - theos

Here is a theos demo, it can hook successfully in iOS10.2, but I cannot find the %log info in syslog, why?
%hook SBApplication
-(id)displayName {
%log;
return %orig;
}
%end

Logging has been increasingly less stable in recent iOS versions for whatever reason and because of that most people use a different approach for debugging. My personal go-to is to create a UIAlertController with title / message set to the debugging information I want to see.
To display it on the highest view controller, you can use:
[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:alertController animated:YES completion:nil];

Related

The goback function of WKWebView does not execute javascript code

In UIWebView, if i call the function goback, the previous page will be present and execute its js code and set title on navigation bar. However, this do not work in wkwebview, it seems that wkwebview cache something and the js code is not executed.
I think the WKWebView is actually the more correct behaviour regarding the load event.
I have found that the pageshow event is better suited for code that needs to run on navigation changes.
Something like this should work in the WKWebView:
window.addEventListener('pageshow', function(event) {
// We were just shown again. Either initial load or due to
// navigation.
});
I was having a similar problem and the webpage was't being reloaded (on iOS 9.2 or higher versions) because it was showing a cached one, when calling goBack.
'Fixed' that clearing the cache data before calling goBack on the WKWebView. I still don't know if it is an iOS bug or Apple just decided to change the default behaviour from iOS 9.2.
In Objective-C would be something like this:
- (void)goBack {
[self cleanCacheWithCompletionHandler:^{
[super goBack];
}];
}
- (void)cleanCacheWithCompletionHandler:(void (^)(void))completionHandler {
if ([WKWebsiteDataStore class]) {
NSSet *websiteDataTypes = [NSSet setWithArray:#[ WKWebsiteDataTypeDiskCache,
WKWebsiteDataTypeMemoryCache]];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:completionHandler];
} else {
completionHandler();
}
}
Note that I subclassed WKWebView in the sample code and that you have to check the availability of WKWebsiteDataStore as it is new to iOS 9.

iOS 6 and Location Services not working

I've updated my iOS SDK to version 6. After that I've compiled my app (works fine in iOS 4 & iOS 5) but now the location services doesn't work. My delegate isn't receiving any update and the upper location arrow is not appearing... I'm starting the service as the usual way:
[locationManager startUpdatingLocation];
My project is non ARC.
What is happening? This is driving me crazy...
Thanks in advance.
Make sure you have a CFBundleDisplayName in your project's .plist file. Adding that key fixed it for me.
Just set the property pausesLocationUpdatesAutomatically of Location Manager to NO. This is a new feature of IOS 6 that disable Location Updates when application runs in background. The default value of this property is YES.
This is a change in iOS6:
You need to implement locationManager:didUpdateLocations: instead of locationManager:didUpdateToLocation:fromLocation to be notified when the location is updated.
You should also read the documentation about startUpdatingLocation.
In my case, I had the location manager under a different class and I was calling this class from the main controller. This was not working and the didUpdateLocations was not called.
//
// LocationServices.h
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationServices : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property (nonatomic, retain) CLLocationManager *locationManager;
- (void)startLocationServices;
#end
// LocationServices.m
#import "LocationServices.h"
#implementation LocationServices
#synthesize locationManager, currentLocation;
- (void)startLocationServices {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.pausesLocationUpdatesAutomatically = NO;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
if ([CLLocationManager locationServicesEnabled]) {
[locationManager startUpdatingLocation];
} else {
NSLog(#"Location services is not enabled");
}
}
////////////////////////////////////////////////
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation* location = [locations lastObject];
NSLog(#"Updated: latitude %+.6f, longitude %+.6f\n",
location.coordinate.latitude,
location.coordinate.longitude);
}
#end
// Main controller
- (void)viewDidLoad {
[super viewDidLoad];
.....
LocationServices *locationSerices = [[LocationServices alloc]init];
[locationSerices startLocationServices];
......
}
The above code does not work. Why? I do not know ....you can easily lose interest when you spend so much time trying to do a thing that is supposed to be simple. iOS is very complicated and unfriendly programming environment. There are many ways to do one thing, only one works, you cannot mix and match without introducing a problem. You have to do everything by the book or you or you get nothing. Not even a hint that you did something wrong ... frustrating ...
Instead when I implemented
locationManager:(CLLocationManager *)manager didUpdateLocations:
in the main controller everything worked fine
The issue seems to be resolved in IOS 6.1 Beta2 - http://www.youtube.com/watch?v=aFZR0eMUV74
setting CFBundleDisplayName solved the problem for me. Same thing location update was never called, just set the info.plist parameter and it start working.
I've tried everything in plist files, cleans, rebuilds, new targets, configurations, etc, etc, etc. Nothing worked. But FINALLY I've fixed it. I had to create a new Xcode 4.5 project from scratch, reconfigure it, add file by file and framework by framework manually. It seems that my old XCode project had something internally incompatible with last XCode. I write this here because maybe it can save someone's next 10 hours of work.
Am I being too simplistic here? Under Privacy, Locations looks the same as it did in previous issues.What's all the fuss about?

Attempting to create USE_BLOCK_IN_FRAME ... EXC_BAD_ACCESS with NSFetchedResultsController

This is an update to my problem. I am receiving this warning now when the program aborts.
warning: Attempting to create USE_BLOCK_IN_FRAME variable with block that isn't in the frame.
I can't find much information on what this means.
This has me baffled. I get the EXC_BAD_ACCESS error. I have NSZombieEneabled (which helped with an earlier problem), but there is no call stack to trace.
I have some nearly identical code that is working with respect to another fetched result controller.
This seems to have something to do with the relationships between the job entity and its associated client entity. The relationship is [job entity] <<--> [client entity].
Initially, I see that the code works without error where the job entity corresponding to the selected row has no client entity linked through a relationship. So in the case where it fails, this points to a client entity, but when it doesn't fail, the pointer is nil.
When I encounter this problem, I start the application and go directly to the job picker view and select a cell. It's at that point that the problem occurs.
I did an experiment by starting the application and going to the client picker view first, knowing that a fetch would occur of all of the client entities. Then I went to the job picker view and selected a cell. The problem did not occur.
Since I am just trying to pass a pointer to a job entity that was already fetched, I don't understand what's happening.
By the way, the code was working fine before I switched to using NSFetchedResultsControllers. I like what they can do for me, but there are some dynamics going on here that I haven't figured out.
The logging is not showing me anything I understand toward resolving the problem.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
userState.selectedJob = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"\n\n(1 Pick) indexPath: %#\n",indexPath);
NSLog(#"\n\n(1 Pick) userState: %#\n",userState);
NSLog(#"\n\nnumber of Objects in job fetchresultscontroller = %d", [[fetchedResultsController fetchedObjects] count] );
NSLog(#"\n\n(1 Pick) selected job: %#\n",[self.fetchedResultsController objectAtIndexPath:indexPath]); // This line is causing the problem...
NSLog(#"\n\n(1 Pick) selected job: %#\n",userState.selectedJob); // Omitting the line above, this line fails
[self.navigationController pushViewController:userState.jobInfoTVC animated:YES];
}
The debug output is
2011-05-07 09:27:04.142 job1[6069:207]
(1 Pick) indexPath: <NSIndexPath 0x5952590> 2 indexes [0, 3]
2011-05-07 09:27:04.142 job1[6069:207]
(1 Pick) userState: <UserStateObject: 0x5919970>
2011-05-07 09:27:04.143 job1[6069:207]
number of Objects in job fetchresultscontroller = 4
(gdb)
The final code should be as simple as this, which led me to all of the logging:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
userState.selectedJob = [self.fetchedResultsController objectAtIndexPath:indexPath]; // Original failure was at this line
[self.navigationController pushViewController:userState.jobInfoTVC animated:YES];
}
I use the singleton userState to keep track of what the user has done. So I keep last selectedJob and selectedClient entity pointers there. This has worked okay before I switched to NSFetchedResultsController.
I have also had a problem with Attempting to create USE_BLOCK_IN_FRAME variable with block that isn't in the frame. Although mine wasn't anything to do with NSFetchedResultsControllers.
Possibly Your Problem
I noticed you mention you are using a singleton, so maybe your problem is solved at this link:
http://npenkov.com/2011/08/01/solving-issues-like-warning-attempting-to-create-use_block_in_frame-variable-with-block-that-isnt-in-the-frame/
From the link:
Exactly in session manager I used the macro, before #synthesize – this was the problem, static definitions should not appear before synthesized methods. So if you have something like:
SYNTHESIZE_SINGLETON_FOR_CLASS(SessionManager)
#synthesize loggedUserId, ...
Just replace it with:
#synthesize loggedUserId, ...
SYNTHESIZE_SINGLETON_FOR_CLASS(SessionManager)
enter code here
My problem
The problem I had was to do with duplicating a variable declaration, in this case the variable inherited from NSManagedObject :
- (void)functionThatDoesSomething {
VariableInheritedFromNSMObj *variableA = nil;
for (VariableInheritedFromNSMObj *variableA in [self containerObject]) {
NSLog(#"a = %#\n", [variableA name]);
}
[variableA setName:#"StackOverflow"];
}
Moving the first line, where variableA is initialised to nil, to after the loop fixed the problem. In my production code I then changed the name of one of the variables.
Hope that helps you or someone else who comes across this problem. This error seems to manifest itself in many different ways.
Is the deployment target OS version set to a lower one than you have debugging support for in Xcode 4.2? When this happened to me, the deployment target had somehow changed to 4.1, but I only had the 4.3 simulator without the additional debugging support for 4.0-4.1.
There are ways to fix this:
Install the debug symbols for your lower OS version from the Xcode preferences. Go to downloads, components and install OS 4.0 - 4.1 Device Debugging Support (or earlier if you need it).
Set the deployment target to 4.3 or higher.
If you choose the former, it's probably worth ticking the box in preferences to download the updates automatically.

NSManagedObjectModel versionIdentifiers

The documentation for NSManagedObjectModel -versionIdentifiers says,
The Core Data framework does not give models a default identifier, nor does it depend this value at runtime. For models created in Xcode, you set this value in the model inspector.
I am not sure, but I think that setting version identifiers might help me as I go about coding model migration policy classes. Does anyone know how one might set these identifiers in Xcode? I have poked around a fair bit without success.
Thanks.
Okay, well this approach did not end up being helpful for me. I solved my Core Data migration debugging problems with the following code:
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"Spark.sqlite"]];
NSError *error = nil;
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
URL:storeUrl
error:&error];
if (!sourceMetadata)
NSLog(#"sourceMetadata is nil");
else
NSLog(#"sourceMetadata is %#", sourceMetadata);
On the other, I just now figured out the answer to my original questions, fwiw.
If you go to your project window and select a .xcdatamodel file and 'get info', then most of the time you will get a 'File "Xxx.xcdatamodel" Info' window - with 'General', 'Targets', 'Build' and 'Comments' tabs. (Yes, the "most of the time" part has me confused.)
However, if you then select your .xcdatamodel file again and 'get info', you will (probably) get a very different inspector - one called 'Data Model "Xxx" Info'. This window has two tabs: 'Appearance' and 'Versioning'. The Versioning tab lets you set the Model Version Identifier.
Bottom line: Setting the Model Version Identifier in Xcode is akin to making your way to Platform 9 3/4 - but unlike 9 3/4 once you get there, it's not really clear why you'd want to be there.

What do I have to do to get Core Data to automatically migrate models?

I have read the documentation about automatic /lightweight migration for Core Data models - but I am having problems implementing it.
As I understand it the application should notice that the model it has and the model that exists on a device already are not the same. If you have only added attributes or relationships and similar simple changes then the model should be upgraded automatically.
Any pointers - do I need to set something in Xcode?
I've now found out that this is quite simple - once you know where to look.
In my AppDelegate I set-up the NSPersistentStoreCoordinator - and you need to add some options to this to tell it to handle auto-migrate:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle error
NSLog(#"Problem with PersistentStoreCoordinator: %#",error);
}
Then you need to do a little trick in xCode:
Select your xcdatamodel file
Select the Design Menu at the top - then Data Model - then choose Add Model Version
Your xcdatamodel file will then get moved into a new directory with the same name as your xcdatamodel file but with the extension xcdatamodeld - there will be a second file in this directory with a 2 in the name. Select the new file and then Design->Data Model->Set Current Version (in Xcode 4 you do this)
If you have already made the changes that have caused your project to be incompatible - take these changes out of the original xcdatamodel file. If you have yet to make the changes - then just edit the 2.xcdatamodel file (the one you just made current version).
Now when you install this version onto a device that has the old model - it will automatically upgrade that model to the new model.
This seems great and as simple as I wanted - but I think you need to be careful during development as you change a model - otherwise you will have to create a new version for each change.
I think what I will do is that I will keep all of the changed files and then once I get ready to deploy my update I'll delete all the in-between files and just deploy with the oldest and latest models.
UPDATE (15/07/2011):
Thanks to #rockstarberlin for pointing out there is updated documentation at apple:
Xcode 4: Setting a Managed Object Model’s Current Version
Update: 8/19/2013 better link:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html
This was incredibly helpful. The Apple documentation was -- as usual -- woefully incomplete. I recommend doing a clean build, as I ran into an error "Can't merge models with two different entities xxx" when I first ran after making these changes. The clean build fixed it up.
Grouchal's answer is perfect...but if you are still having the "Can't merge models with two different entities xxx" even after cleaning up the build several times...Your might have issues with how the managedObjectModel is being loaded...take at look at this one...which helped me fix it..
core data migration problems
Also, if you stumbled upon this post, like I did, after getting the "The model used to open the store is incompatible with the one used to create the store" error and you are just debugging using the simulator and wanting to completely replace the old model installed, you can just Reset the Simulator app or deleting your app from the simulator would probably work as well.
It didn't occur to me to try this until reading the posts here, at which point I realized that I had installed the app in the simulator and then subsequently changed the model, causing the aforementioned run-time error.
To follow up on Santthosh's answer, figured I'd post the code snippet right here instead. You need to create your managedObjectModel with initWithContentsOfURL: instead of mergedModelFromBundles: otherwise you'll get error:
Can't merge models with two different
entities XXX and XXX
If your Model file is named "Model", here's how you create the managedObjectModel:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Model" ofType:#"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
Credit to this blog post.
the menu in Xcode 4 changed a bit. here´s a description how to do it in Xcode 4:
Xcode 4: Setting a Managed Object Model’s Current Version
I've had this issue for years, and I tried all of these answers to no avail. Today I finally figured out what I was doing wrong. Very simple problem, but I overlooked it. When creating a newer version of the data model, if you are ADDING columns make sure to mark them as OPTIONAL. If you do not the simple migration will not work because the new column values will not be filled in.
As soon as I made sure my new columns has "optional" checked, I tried the migration again and it worked.
I stumbled onto this post because of a different problems, but the error was "The model configuration used to open the store is incompatible with the one that was used to create the store."
Here was my problem and the solution to it. In my model, I was using configurations. I had some of the entities being stored in one file and the others in a second file. (I have some defaults that might periodically need to get downloaded, and it would be an incredible pain to merge them into the whole). Anyhow, I made a new entity. The program seemed to run fine, but whenever I'd quit, I got the above error.
The solution there was to look at my configurations, realize that I had an entity that wasn't currently in any of the configurations, and add it to one. Runs like a dream.
This won't fix the OP's problem. But maybe some frustrated person who lands here via google will be in the boat I was in :)
iOS 4.0+
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"model" withExtension:#"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Minor edit to #Grouchal's awesome instructions above for Xcode version 5:
Old:
2. Select the Design Menu at the top - then Data Model - then choose Add Model Version
Version 5+:
2. Select the Editor menu, then Add Model Version…, type your Version name and Based on model (select your original model from the list)

Resources