How to override the NSPersistentStoreCoordinator in UIManagedDocument - sqlite

I have an application that uses Core Data through UIManagedObjectDocument. I am trying to add encryption to the underlying SQLite database by using Encrypted Core Data (https://github.com/project-imas/encrypted-core-data). From the description for ECD, I need to create a new type of NSPersistentSroreCoordinator. However, I cannot seem to do this with a UIManagedObjectDocument since it creates its own internal NSPersistenStoreCoordinator (which s marked private).
I create the database with this line:
UIManagedDocument* managedDoc = [[UIManagedDocument alloc] initWithFileURL:url];
I tried subclassing UIManagedDocument and creating it this way with no luck:
UIManagedDocument* managedDoc = [[EncryptedManagedDocument alloc] initWithFileURL:url];
And my implementation of the class:
#interface EncryptedManagedDocument()
#property (nonatomic,retain,readonly) NSPersistentStoreCoordinator *encryptedStoreCoordinator;
#end
#implementation EncryptedManagedDocument
#synthesize encryptedStoreCoordinator = _encryptedStoreCoordinator;
-(NSPersistentStoreCoordinator*)encryptedStoreCoordinator
{
if (_encryptedStoreCoordinator)
return _encryptedStoreCoordinator;
_encryptedStoreCoordinator = [EncryptedStore makeStore:[self managedObjectModel]:#"SOME_PASSCODE"];
return _encryptedStoreCoordinator;
}
-(NSPersistentStoreCoordinator*)persistentStoreCoordinator
{
return self.encryptedStoreCoordinator;
}
#end
Does anyone know the right way to do this?
Thanks!

I'm going to say this is not possible. UIManagedDocument wraps things up nicely and is a great time saver for the common case, but to enable my scenario I created an EncryptedManagedDocument class that is similar to UIManagedDocument but gave me control to create my own persistent store coordinator.
Thanks, everyone.

Related

Working with in memory FeatureSet and Feature DotSpatial

I'm a beginner with DotSpatial and I'm stuck with a problem.
I try to work with in memory feature (to keep them only in Map) until the user hit save button.
The basic idea is that the user imports some dxf files and creates featureset based on layer name if the FeatureSet doesn't all ready exist, and for each polyline from dxf creates feature which will be added into a featureset.
public IFeature AddPoligons(EntityObject polyline, List<Text> textInDxf)
{
IFeatureSet featureSet = null;
//Getting the right featureset from map
foreach (var x in appManager.Map.GetPolygonLayers())
{
if (!string.Equals(x.DataSet.Name, layerName)) continue;
featureSet = x.DataSet as FeatureSet;
break;
}
var polygon = CreatePolygon(polyline);
//Creating feature and adding to FeatureSet
var feature = featureSet.AddFeature(polygon);
//Populating DataRow with information
AddinfoIntoDataTable(feature, polygon, textInDxf);
return feature;
}
Everything thing looks fine, the map is updated with new polygons, can select them, view information from datatable BUT, when I try to delete a selected feature (polygon) it throws an IndexOutOfRange exception.
What I'm doing wrong there?
Please help! Thank you and sorry for my poor English.
P.S.
When I created the featureSet first I saved it on the disk and then loaded into map with Map.AddLayer() method.
Meanwhile I found the solution somewhere on CodePlex-DotSpatial forum, and was posted by Jany.
The idea is to call this pice of code after each action against a FeatureSet (add, remove, move)
featureLayer.DataSet.UpdateExtent();
featureLayer.DataSet.InitializeVertices();
featureLayer.LabelLayer?.CreateLabels();
if(save)
{
featureLayer.DataSet.Save();
featureLayer.DataSet.Close();
}
featureLayer.AssignFastDrawnStates();
AppManager.Map.Refresh();
AppManager.Map.ResetBuffer();
where featureLayer is IFeatureLayer.
There is one problem:
If we save the project with AppManager.Serialization.SaveProject() and then open the project AppManager.Serialization.OpenProject() the issue appear again.
As a solution for this I call my Save method after open the project and on short is look like this:
public void Save()
{
foreach(var featureLayer in AppManager.Map.GetPolygonLayers())
{
featureLayer.DataSet.Save();
}
}
Hope that helps someone.

bundle sqlite database with app and stringByAppendingPathComponent error

There are probably many other questions I don't even know to ask yet since I'm new to app programming.
I initially created the database from within the app, copied it to my working folder (which is probably not where it should ultimately reside), then appended my records (about 1,000 of them) from a text file.
The first two questions that come to mind are:
- what folder should the database be in?
- how does it get deployed with the app?
I found quite few examples using the following lines in persistentStoreCoordinator function:
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"myDatabase.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
But the first line gives me the pre-compile error: "Receiver type 'NSURL' for instance message does not declare a method with selector 'stringByAppendingPathComponent:'. Why is it not working for me?
And is this in fact the best way to bundle my database with the rest of the app?
Thanks!
Easiest solution is to use NSUrl instead of NSString. SO user #trapper already provided a solution in the below link.
importing sqlite to coredata
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Database.sqlite"];
// If the database doesn't exist copy in the default one
if (![storeURL checkResourceIsReachableAndReturnError:NULL])
{
NSURL *defaultStoreURL = [[NSBundle mainBundle] URLForResource:#"Database" withExtension:#"sqlite"];
if ([defaultStoreURL checkResourceIsReachableAndReturnError:NULL])
{
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager copyItemAtURL:defaultStoreURL toURL:storeURL error:NULL];
}
}

Javascript permission denied error when using Atalasoft DotImage

Have a real puzzler here. I'm using Atalasoft DotImage to allow the user to add some annotations to an image. When I add two annotations of the same type that contain text that have the same name, I get a javascript permission denied error in the Atalasoft's compressed js. The error is accessing the style member of a rule:
In the debugger (Visual Studio 2010 .Net 4.0) I can access
h._rule
but not
h._rule.style
What in javascript would cause permission denied when accessing a membere of an object?
Just wondering if anyone else has encountered this. I see several people using Atalasoft on SO and I even saw a response from someone with Atalasoft. And yes, I'm talking to them, but it never hurts to throw it out to the crowd. This only happens in IE8, not FireFox.
Thanks, Brian
Updates: Yes, using latest version: 9.0.2.43666
By same name (see comment below) I mean, I created default annotations and they are named so they can be added with javascript later.
// create a default annotation
TextData text = new TextData();
text.Name = "DefaultTextAnnotation";
text.Text = "Default Text Annotation:\n double-click to edit";
//text.Font = new AnnotationFont("Arial", 12f);
text.Font = new AnnotationFont(_strAnnotationFontName, _fltAnnotationFontSize);
text.Font.Bold = true;
text.FontBrush = new AnnotationBrush(Color.Black);
text.Fill = new AnnotationBrush(Color.Ivory);
text.Outline = new AnnotationPen(new AnnotationBrush(Color.White), 2);
WebAnnotationViewer1.Annotations.DefaultAnnotations.Add(text);
In javascript:
CreateAnnotation('TextData', 'DefaultTextAnnotation');
function CreateAnnotation(type, name) {
SetAnnotationModified(true);
WebAnnotationViewer1.DeselectAll();
var ann = WebAnnotationViewer1.CreateAnnotation(type, name);
WebThumbnailViewer1.Update();
}
There was a bug in an earlier version that allowed annotations to be saved with the same unique id's. This generally doesn't cause problems for any annotations except for TextAnnotations, since they use the unique id to create a CSS class for the text editor. CSS doesn't like having two or more classes defined by the same name, this is what causes the "Permission denied" error.
You can remove the unique id's from the annotations without it causing problems. I have provided a few code snippets below that demonstrate how this can be done. Calling ResetUniques() after you load the annotation data (on the server side) should make everything run smoothly.
-Dave C. from Atalasoft
protected void ResetUniques()
{
foreach (LayerAnnotation layerAnn in WebAnnotationViewer1.Annotations.Layers)
{
ResetLayer(layerAnn.Data as LayerData);
}
}
protected void ResetLayer(LayerData layer)
{
ResetUniqueID(layer);
foreach (AnnotationData data in layer.Items)
{
LayerData group = data as LayerData;
if (group != null)
{
ResetLayer(data as LayerData);
}
else
{
ResetUniqueID(data);
}
}
}
protected void ResetUniqueID(AnnotationData data)
{
data.SetExtraProperty("_atalaUniqueIndex", null);
}

Finding duration of a video using directshowlib-2005

My asp.net(c#) method looks as follows:
static public bool GetVideoLength(string fileName, out double length)
{
DirectShowLib.FilterGraph graphFilter = new DirectShowLib.FilterGraph();
DirectShowLib.IGraphBuilder graphBuilder;
DirectShowLib.IMediaPosition mediaPos;
length = 0.0;
try
{
graphBuilder = (DirectShowLib.IGraphBuilder)graphFilter;
graphBuilder.RenderFile(fileName, null);
mediaPos = (DirectShowLib.IMediaPosition)graphBuilder;
mediaPos.get_Duration(out length);
return true;
}
catch
{
return false;
}
finally
{
mediaPos = null;
graphBuilder = null;
graphFilter = null;
}
}
I got the duration with the above method. But my problem is i can't delete the physical file
after my operation. I used
File.Delete(FilePath);
While performing this action i got an exception as follows:
"The process cannot access the file because it is being used by another process."
My Os is windows 7(IIS 7)
Any one please help me to sort this out?
I've got no experience in coding directshow apps in C#, but plenty of experience in C++.
DirectShow is based on a technology called COM - which uses reference counting to tell it when an object is in use.
It would use a COM object to represent the IGraphBuilder for example.
In C++, we would have to deconstruct the graph, by removing all its filters, then release the graph.
I understand that C# has its own garbage collection etc., but unless you explicitly release the objects you use, they'll remain in memory.
It seems from the code you've quoted, that the graph is still opened, even though playback may have finished. In that case, it'll hold a reference to the file which you've played back, which would explain why you can't delete it - e.g. there's a read lock on the file.
Hope this points you in the right direction!

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor) and another like this=>InsertJCDC(fakeBox).
When I stub out the parent I want to return fakePor. But when I run the code it returns null instead. Here is the unit test.
[Test]
public void PorBLL_InsertByPorInsertCV_DoingGoodCase()
{
// Startup object mapper
_Bootstrapper.Bootstrap();
// create the mock for generic Crud
IGenericCrud mockGenericCrud = MockRepository.GenerateMock<IGenericCrud>();
PorInsertCV fakePor = new PorInsertCV();
PorBoxInsertCV fakeBox = new PorBoxInsertCV();
// build fake return
PorEO fakePorNewRow = new PorEO();
fakePorNewRow.PorId = 22;
// stub parent and child insert routines.
mockGenericCrud.Stub(c => c.InsertJCDC<PorEO, PorInsertCV>(fakePor)).Return(fakePorNewRow);
mockGenericCrud.Stub(c => c.InsertJCDC<PorBoxEO, PorBoxInsertCV>(fakeBox)).Return(null);
ObjectFactory.Inject(typeof(IGenericCrud), mockGenericCrud);
IPorBLL localWithMock = ObjectFactory.GetInstance<IPorBLL>();
// build user args to csll bll with and use for insert
PorInsertCV userArgs = new PorInsertCV();
userArgs.AccessionNbr = "364-80-0007";
userArgs.NbrBoxes = 11;
userArgs.RegId = 20;
userArgs.TransmitedDt = Convert.ToDateTime("1/30/1980");
// call the bll using the stub
localWithMock.InsertByPorInsertCV(userArgs);
}
Any help is greatly appreciated
I can't really follow your code that well, but I'll give it a shot.
From my skills of deduction, this line here is the one giving you issues:
mockGenericCrud.Stub(c => c.InsertJCDC<PorEO, PorInsertCV>(fakePor)).Return(fakePorNewRow);
Because you're expecting fakePorNewRow to be returned when you call localWithMock.InsertByPorInsertCV(userArgs); - yeah?
If that's your case, what your problem is, is that it will only return fakePorNewRow when it is given fakePor ... not userArgs as you have given it.
Tell me if I'm completely off track.
HTHs,
Charles
Ps. You might want to add the tag of which mocking framework you are using to the question.

Resources