I am following a tutorial on the Metaio website - Creating a New AR Application, and it seems to work (I get the Metaio splash screen, and the watermark shows up on the camera view when I build and run it on an ipad.
I'm trying to get the Hello World tutorial to work, using code directly copied from the Metaio SDK, but I am not able to get the model to appear over the racking image.
The implementation file code is below - I am getting no errors when I run it on an ipad, and get the camera view etc, but no 3d model - any suggestions? Thx:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void) viewDidLoad
{
[super viewDidLoad];
// load our tracking configuration
NSString* trackingDataFile = [[NSBundle mainBundle] pathForResource:#"TrackingData_MarkerlessFast"
ofType:#"xml"
inDirectory:#"Assets"];
if(trackingDataFile)
{
bool success = m_metaioSDK->setTrackingConfiguration([trackingDataFile UTF8String]);
if( !success)
NSLog(#"No success loading the tracking configuration");
}
// load content
NSString* metaioManModel = [[NSBundle mainBundle] pathForResource:#"metaioman"
ofType:#"md2"
inDirectory:#"Assets"];
if(metaioManModel)
{
metaio::IGeometry* theLoadedModel = m_metaioSDK->createGeometry([metaioManModel UTF8String]);
if( theLoadedModel )
{
// scale it a bit up
theLoadedModel->setScale(metaio::Vector3d(1.0,1.0,1.0));
}
else
{
NSLog(#"error, could not load %#", metaioManModel);
}
}
}
#end
Did you also use the xml tracking file, that should be in the assets folder?
As I see it, it could come from several errors:
- The tracking image doesn't have the same name in the xml file and in your folders
- the tracking file is empty or contains errors
Maybe you could share the xml tracking file as well so we could help you more.
Good luck
Related
I have an app with a Today extension. Using App Groups, I am able to have a single repository for both the app and the extension. However, I must be missing something as the solution only partially works. If I am in the App I can add a record and will see that same record in the widget. However, if a change the value of a column, for example, setting a boolean from true to false. The app won't see the change if it were made in the extension and vice versa. I am saving the change to Core Data:
_record?.managedObjectContext?.save()
Using DB Browser, I am able to verify that the change was made; is in the DB. Clearly, I am missing something. Any ideas would be appreciated.
Make sure you're using the same db in both sides
- (void)viewDidLoad {
[super viewDidLoad];
if ([self.extensionContext respondsToSelector:#selector(setWidgetLargestAvailableDisplayMode:)]) { // iOS 10+
[self.extensionContext setWidgetLargestAvailableDisplayMode:NCWidgetDisplayModeExpanded];
} else {
self.preferredContentSize = CGSizeMake(0, 110.0); // iOS 10-
}
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreAtURL:[MagicalRecord urlAppGroupStore]];
}
As you can see i'm using magical record but I'm specifying to use the share sqlite file
NSString *const kAppGroupIdentifier = #"group.com.carlosduclos.myapp";
+ (NSURL *)urlAppGroupStore {
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:kAppGroupIdentifier];
return [groupURL URLByAppendingPathComponent:#"mydb.sqlite"];
}
I've done a lot of reading and research in trying to come up with a solution to my problem and can't seem to make my code work the way I want, or the way it should. What I want to do is be able to have different buttons play different, short sounds, without overlapping each other if I decide to click another sound button before another sound button's audio is finished. I've successfully got to the point where they play their designated sound using SystemSoundID, but they still overlap when I click on multiple buttons.
Below is a sample of my code:
Interface file:
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
}
-(IBAction)Sound:(id)sender;
#end
Implementation file:
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
#implementation ViewController : UIViewController
- (IBAction)Sound:(id)sender
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"Sound" ofType:#"mp3"];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theAudio play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I would appreciate the help more than you know, as I've spent quite some time trying to get it to work the way it should. If you have any questions for me please let me know! Thank you very much.
-Michael
I have the understanding that when you play an AudioSystemSound that it will play until completion. This method of playing Audio isn't a highly functional one and only really supposed to be used for simple "clicks" and "dings" etc. For a more comprehensive audio suite of features perhaps you could look at using the AVFoundation library with AVAudioPlayer where you can call "stop" to cease playing the called sound.
https://developer.apple.com/av-foundation/
Edited addition to the above answer:
In your .h file make sure you include;
#import AVFoundation;
and then create an AV player with;
AVAudioPlayer *playAudio
In your .m file add this block of code below in your method that needs to play the sound. Of course adjust the song/audiofile name and format appropriately;
NSString *backgroundMusic = [[NSBundle mainBundle]
pathForResource:#"insertSongNameHere" ofType:#"mp3"];
playAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:insertSongNameHere] error:NULL];
playAudio.numberOfLoops = -1;
[playAudio play];
Note: Number of loops being -1 means repeat forever. You can of course make that whatever number you like though. I hope that all helps, if not let me know and I'll see what I can do to assist!
In Xcode 5.0.2
I create a blank single view app for iPhone,
then add a "male.png" image to the project,
drag a UIImageView to the storyboard
and finally add the following code to the viewDidLoad:
_imageView.image = [UIImage imageNamed:#"male.png"];
This works well:
Then I add the 4 files from JMImageCache project and change the ViewController.m to:
#import "ViewController.h"
#import "JMImageCache.h"
static NSString* const kAvatar = #"http://gravatar.com/avatar/55b3816622d935e50098bb44c17663bc.png";
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[_imageView setImageWithURL:[NSURL URLWithString:kAvatar]
placeholder:[UIImage imageNamed:#"male.png"]];
}
#end
Unfortunately, this results in app crash with the error message Thread 1: EXC_BAD_ACCESS:
At his webpage Jake Marsh (the author of JMImageCache) notes:
JMImageCache purposefully uses NSString objects instead of NSURL's to make things easier and cut down on [NSURL URLWithString:#"..."] bits everywhere. Just something to notice in case you see any strange EXC_BAD_ACCESS exceptions, make sure you're passing in NSString's and not NSURL's.
But (as an iOS programming newbie) I don't understand, what exactly does Mr. Marsh mean - since his file UIImageView+JMImageCache.m declares the 1st argument for the public method as NSURL:
- (void) setImageWithURL:(NSURL *)url placeholder:(UIImage *)placeholderImage {
[self setImageWithURL:url key:nil placeholder:placeholderImage];
}
Is the note maybe outdated and how could I fix my app?
That's a bug in JMImageCache. setImageWithURL:key:placeholder:completionBlock: calls itself, exhausting the stack.
To work around the bug, call the longer form of the method:
[_imageView setImageWithURL:[NSURL URLWithString:kAvatar]
key:nil
placeholder:[UIImage imageNamed:#"male.png"]
completionBlock:nil
failureBlock:nil];
Or, use an older version of the library (e.g. 0.4.0). Looks like the bug was introduced in 1af09be78a.
I have a UIDocument based app, without iCloud support. The user is able to create documents, and save them to app's Document directory.
I have also created few "sample" documents, and passing them with the app's bundle. I want the user to be able to open sample documents the same way as they can open their own documents:
NSArray *samplesContent = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"doco" subdirectory:#"Samples"];
for (NSURL *sampleURL in samplesContent) {
Doco *doco = [[Doco alloc] initWithFileURL:sampleURL];
[doco disableEditing];
[doco openWithCompletionHandler:^(BOOL success) {
if (success) {
[self.docos addObject:doco];
if (self.docos.count >= samplesContent.count) {
[self.tableView reloadData];
}
} else DLog(#"Failed to open %#", [sampleURL pathExtension]);
}];
}
What I am seeing is this:
On viewDidLoad, docs array gets populated with sample docs and displayed in the tableView the first time app launches. No issues here, all is smooth and nice.
Then I back out of the view with the following code to close all open docs:
int count = 0;
for (Doco *doco in self.docos) {
if (doco.documentState == UIDocumentStateNormal) {
[doco closeWithCompletionHandler:nil];
count++;
}
}
DLog(#"Closed %i docs", count);
When I open the view again, the array of docs should get populated again and tableView re-populated, but nothing happens.
The completion handler below never gets called, although the URL is pointing to the same file and it is valid:
[doco openWithCompletionHandler:^(BOOL success) {}
I do not have this issue for user generated docs stored in Documents, so my assumption is that it has something to do with auto-save, that gets called on read-only bundle and fails
But I am sort of stuck on this part, any help will be appreciated.
The problem has already been identified, but I think it's worth describing a couple of simple solutions since including sample documents in an app's bundle is not uncommon.
So the problem is that the sample document is trying to save changes when it is closed, but saving cannot succeed in a read-only app bundle.
I think there are two main solutions here:
Copy the sample document into the Documents directory, where it can be treated like any other document and saved successfully (if you want user edits to the sample document to be saved, use this approach).
Prevent the document from trying to save (for read-only sample documents).
So here are some simple examples...
1. Copy sample documents into Documents directory
On first launch (or indeed whenever you decide to 'refresh' the sample document), use NSFileManager to copy the file into place:
- (void)refreshSampleDocuments
{
NSArray *sampleFromURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"doc" subdirectory:#"Samples"];
for (NSURL *sampleFromURL in sampleFromURLs) {
NSString *sampleFilename = [sampleFromURL lastPathComponent];
NSURL *sampleToURL = [[self documentsDirectoryURL] URLByAppendingPathComponent:sampleFilename];
// ...
// Do some checks to make sure you won't write over any user documents!
// ....
NSError *error;
BOOL copySuccessful = [[NSFileManager defaultManager] copyItemAtURL:sampleFromURL toURL:sampleToURL error:&error];
if (!copySuccessful) {
// Handle error...
}
}
}
2. Prevent sample documents from trying to save
This approach is much simpler (for read-only documents), and easier than trying to prevent updates wherever they might occur in the document.
When closeWithCompletionHandler: is called on UIDocument, autosaveWithCompletionHandler: is invoked to ensure the document file is saved before closing. This in turn invokes hasUnsavedChanges to decide whether a save is necessary. So if hasUnsavedChanges returns NO, then any invocation of the autosaving mechanism will result in no changes being written out.
(N.B. manually calling saveToURL:forSaveOperation:completionHandler: will still force a save, regardless of what hasUnsavedChanges returns.)
So in your UIDocument subclass, override hasUnsavedChanges to return NO if the document is read-only.
#interface MyDocument : UIDocument
#property(nonatomic, getter = isReadOnly) BOOL readOnly;
#end
#implementation MyDocument
- (BOOL)hasUnsavedChanges
{
return [self isReadOnly] ? NO : [super hasUnsavedChanges];
}
#end
If UIDocument is updated it will try to save changes on close.
Since UIDocument was loaded from read-only bundle, I had to make sure that it does not get updated, otherwise close block returns success=NO, and document is not closed...
Hi I'm trying to use the CIKernel class
I don't understand why is it that I keep getting these errors:
AdriansFilter.m:23:29: error: receiver 'CIKernel' for class message is a forward declaration [4]
AdriansFilter.m:23:28:{23:28-23:62}: error: no known class method for selector 'kernelsWithString:' [4]
I've tried importing QuartzCore framework but it still doesn't work. I'm stuck because I really cannot determine what is the real issue here. Could somebody help me please?
my h file looks like this:
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#interface AdriansFilter: CIFilter
{
CIImage *inputImage;
CIColor *inputColor;
NSNumber *inputDistance;
NSNumber *inputSlope;
}
#end
my m file looks like this
#import "AdriansFilter.h"
#implementation AdriansFilter
static CIKernel *hazeRemovalKernel = nil;
- (id)init
{
if(hazeRemovalKernel == nil)
{
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
NSString *code = [NSString stringWithContentsOfFile: [bundle
pathForResource: #"MyHazeRemoval"
ofType: #"cikernel"]];
NSArray *kernels = [CIKernel kernelsWithString: code];
hazeRemovalKernel = [kernels objectAtIndex:0];
}
return [super init];
}
#end
You haven't imported a header where the interface for CIKernel is defined. By searching the Apple developer documentation, I don't find a CIKernel class reference for iOS. This suggests to me that the CIKernel class is not available on iOS.
In Xcode, click on CIKernel in your source file to put the text cursor there, then open the right column (also known as Utilities) of the Xcode window, then select the quick help inspector tab. If the selected class is available for iOS, you should see documentation for the class and a reference to which header file declares it. When I try this with the CIKernel class selected in an iOS project, I just get "No Quick Help".