linking dictionary to custom initialiser terminating - reason: '-[__NSCFArray isFileURL]: - xcode

please be patient im a nuubie at this
I'm writing a custom init for first time, the sentance01text loads fine so i know the plist is reading ok :) but i cant seem to get my sentance01Timing timings to work ><
this method should pass the sentance01Timing typed by the user which is the objectForKey which should load the relevant array into the audioIntervals array
at the moment I'm using an NSString to access the dictionary and pass this to the array audiointervals
but this seems to be wrong and causes the error anyhelp would be appreciated.
i dont understand why it worked for the text but not this?
terminating - reason: '-[__NSCFArray isFileURL]:
probably Im doing something really dumb >< please help if you can
ps am having to use my old mac (my nice one is being repaired at the moment - so will be using non arc - then updating the code when I get my nice mac back, so just keep it in mind
its why im not releasing any objects at the moment...)
HelloWorld.m
#import "HelloWorldLayer.h"
#import "TextWithAudioHilight.h"
#implementation HelloWorldLayer
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
HelloWorldLayer *layer = [HelloWorldLayer node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init])) {
TextWithAudioHilight *pagetext = [[TextWithAudioHilight alloc]initWith5:#"test words here,\nmore words, more words.."
sentance01Timing:#"TimingSEN01"
withSoundNamed:nil];
[self addChild:pagetext];
}
return self;
}
- (void) dealloc
{
[super dealloc];
}
#end
TextWithAudio.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface TextWithAudioHilight : CCLayer {
}
#property(nonatomic,retain)NSString *sentance01text;
#property(nonatomic,retain)NSString *sentance01Timing;
#property(nonatomic,retain)NSString *soundNamed;
-(id)initWith5:(NSString *)sentance01text sentance01Timing:(NSString *)sentance01Timing withSoundNamed:(NSString *)soundNamed;
#end
TextWithAudio.m
#import "TextWithAudioHilight.h"
#implementation TextWithAudioHilight
#synthesize sentance01text = _sentance01text;
#synthesize sentance01Timing = _sentance01Timing;
#synthesize soundNamed = _soundNamed;
-(id)initWith5:(NSString *)sentance01text sentance01Timing:(NSString *)sentance01Timing withSoundNamed:(NSString *)soundNamed
{
self = [super init];
if(self)
{
CGSize size = [[CCDirector sharedDirector] winSize];
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"AudioTimings" ofType:#"plist"];
NSDictionary* myDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
//needs create array that has timing information as an array from the plist
//NSString *Text01timing = [myDictionary objectForKey:#"sentance01Timing"];
NSString *Text01timing = [myDictionary objectForKey:_sentance01Timing];
NSMutableArray * audioIntervals = [NSMutableArray arrayWithContentsOfFile:Text01timing];
NSLog(#"Text01timing %f",audioIntervals);
//needs to create a label and put the text in it
CGSize maxSize = {800, 200};
CGSize actualSize = [sentance01text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:20]
constrainedToSize:maxSize lineBreakMode:UILineBreakModeWordWrap];
CGSize containerSize = { actualSize.width, actualSize.height };
CCLabelTTF *label = [CCLabelTTF labelWithString:sentance01text dimensions:containerSize
alignment:UITextAlignmentLeft fontName:#"Helvetica"
fontSize:20];
// Center label
label.position = ccp( size.width /2 , size.height/6 );
label.color = ccc3(80, 80, 80);
// Add label to this scene
[self addChild:label z:7];
}
return self;
}
#end
AudioTimings.plist
<plist version="1.0">
<dict>
<key>TimingSEN01</key>
<array>
<real>0.044444</real>
<real>0.143054</real>
<real>0.213886</real>
<real>0.48055</real>
<real>0.844434</real>
<real>1.345817</real>
<real>1.470816</real>
<real>1.577759</real>
<real>2.020809</real>
<real>2.331917</real>
</array>
</dict>
</plist>

With many thanks to trojanfoe I was able to fix the problem
the main problem was that my initialised objects wernt retained
if you do see a better way of things in the code please say as my goal is to learn (but baby steps! its all pretty new!!)
im doing this on my old mac laptop (so its not for arc - as i cant test it at the moment)
but maybe it will help someone else...
so creating my textmangerclass:
#interface TextManagerWithpageNum : CCLayer
{
//create the properties you need notice the underscore
//NSString *_varName;
NSString *_background;
NSString* _text; //myText
NSString* _soundFile;
NSString* _audioInterval;
NSString* _currPageNumber;
}
declare the #property which gives access to the value accessor (getter) and mutator (setter)
//#property(nonatomic, strong)NSString* background; - in arc
#property(nonatomic, retain) NSString* background;
#property(nonatomic, retain) NSString* text;
#property(nonatomic, retain) NSString* soundFile;
#property(nonatomic, retain) NSString* audioInterval;
#property(nonatomic, retain) NSString* currPageNumber;
and implementation .m
//#synthesize varName = _varName;
#synthesize background = _background;
#synthesize text = _text;
#synthesize soundFile = _soundFile;
#synthesize audioInterval = _audioInterval;
#synthesize currPageNumber = _currPageNumber;
-(id)initWithBackground:(NSString *)background
textFromPlist:(NSString *)text
soundNamed:(NSString *)soundFile
audioIntervalPlist:(NSString *)audioInterval
CurrentPage:(NSString *)currPageNumber
{
self = [super init];
if(self)
{
//_varName = varName;
_text = text;
_audioInterval = audioInterval;
_soundFile = soundFile;
_currPageNumber = currPageNumber;
/*here is where I was having the problem - its important to manually retain
and dealloc or you wont be able to use your objects created!*/
//audio interval
_audioInterval= [[myDictionary objectForKey:audioInterval]retain];//***please retain me! and dont forget to dealloc! :)
NSLog(#"audio Intervals %#",audioInterval);
hello world
TextManagerWithpageNum *Mypage =
[[TextManagerWithpageNum alloc]initWithBackground:#"Page01Bg.png"textFromPlist:#"Page01Text"soundNamed:#"Page01" audioIntervalPlist:#"AudioTimings" CurrentPage:5];
[self addChild:Mypage];
//hope the practicle example of where i stuffed up helps someone else
since its more fun to learn by someone elses mistakes :P

Related

Programmatically tagging in Mavericks from an Sandboxed App

I am writing to a file in an sandboxed app and later trying to set the tags for it using -[NSURL setResourceValue:theTags forKey:NSURLTagNamesKey error:&theTaggingError];. I am not getting any errors (i.e, tags are successfully applied once) but eventually file is kind of replaced and tags are lost. This is only in sandboxed app; if I turn off sandboxing things work fine. In sandboxed mode, if I set tags without writing to the file - again things work fine.
In essence, I am unable to set tags of a file after writing to it. How can I fix it? Any insights?
Sample Code:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
NSWindow *_window;
NSURL *_saveURL;
NSSavePanel *_savePanel;
}
#property (assign) IBOutlet NSWindow *window;
#property (retain) NSURL *saveURL;
#property (retain) NSSavePanel *savePanel;
- (IBAction)writeAndTag:(id)sender;
- (IBAction)justTag:(id)sender;
#end
#implementation AppDelegate
#synthesize window = _window;
#synthesize saveURL = _saveURL;
#synthesize savePanel = _savePanel;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.savePanel = [NSSavePanel savePanel];
}
- (IBAction)writeAndTag:(id)sender
{
[self.savePanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
self.saveURL = [self.savePanel URL];
NSString *testString = #"Hello!";
NSError *error = nil;
[testString writeToFile:[self.saveURL path] atomically:NO encoding:NSUTF8StringEncoding error:&error];
if(error)
{
NSLog(#"Err in saving: %#" ,error);
error = nil;
}
// Tag is lost here
BOOL success = [self.saveURL setResourceValue:[NSArray arrayWithObjects:#"Test", nil] forKey:NSURLTagNamesKey error:&error];
NSLog(#"Tagging success: %#", (success)?#"YES":#"NO");
if(error)
{
NSLog(#"Err in tagging: %#" ,error);
}
}];
}
- (IBAction)justTag:(id)sender
{
// Works fine
[self.saveURL setResourceValue:[NSArray arrayWithObjects:#"Test", nil] forKey:NSURLTagNamesKey error:NULL];
}
#end

App stops working after adding messageUI.framework

App stops working after adding messageUI.framework
I have a fully working App created and I want to add some new features. I added the messageUI.framework and it stoped working. If I delete the Framework it works again, but this is not the idea.
The error I received is:
-[Account initWithCoder:]: unrecognized selector sent to instance 0x1cd953a0
I have a custom NSObject called Account and I get the error when loading it:
myAccounts = [[NSMutableArray alloc] init];
myAccounts = [NSKeyedUnarchiver unarchiveObjectWithFile:savePath]; //Crashes in this line
When it was previously saved with:
[NSKeyedArchiver archiveRootObject:myAccounts toFile:savePath];
Can it be caused by some overlapping variables or something like that?
Notes:
Account.h is like:
#define kAccName #"name"
#define kAccID #"identifier"
#define kAccInitAmount #"initAmount"
#define kAccActive #"active"
#import <Foundation/Foundation.h>
#import "Transfer.h"
#interface Account : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *identifier;
#property (nonatomic) double initAmount;
#property (nonatomic) BOOL active;
- (id)initWithID:(NSString *)ident;
#end
And Account.m is:
#import "Account.h"
#implementation Account
#synthesize name;
#synthesize identifier;
#synthesize initAmount;
#synthesize active;
- (id)init {
self = [super init];
if (self) {
self.active = TRUE;
}
return self;
}
- (id)initWithID:(NSString *)ident {
self = [super init];
if (self) {
self.active = TRUE;
self.identifier = ident;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:kAccName];
self.identifier = [decoder decodeObjectForKey:kAccID];
self.initAmount = [decoder decodeDoubleForKey:kAccInitAmount];
self.active = [decoder decodeBoolForKey:kAccActive];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.name forKey:kAccName];
[encoder encodeObject:self.identifier forKey:kAccID];
[encoder encodeDouble:self.initAmount forKey:kAccInitAmount];
[encoder encodeBool:self.active forKey:kAccActive];
}
#end
I just hit this problem, I cannot tell you exactly why, but refactor your Account object to any other name, I used Accounts, and it works. Something at runtime in the MessageUI.framework is colliding with your Account object name.

MapKit pin title not showing

The location is working but the title isn't appearing, most strange.
location.latitude = (double) 51.501468;
location.longitude = (double) -0.141596;
// Add the annotation to our map view
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"ABC" andCoordinate:location];
[self.mapView addAnnotation:newAnnotation];
// [newAnnotation release];
MapViewAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapViewAnnotation : NSObject <MKAnnotation> {
NSString *title;
CLLocationCoordinate2D coordinate;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d;
#end
and MapViewAnnotation.m
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize title, coordinate;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
title = ttl;
coordinate = c2d;
return self;
}
#end
[newAnnotation release] is remmed out to keep the ARC happy :-)
Any ideas?
This did the trick:
[mapView selectAnnotation:newAnnotation animated:YES];
previously the title would only show if you clicked on the Pin.
you call annotation delegates refer this link, mapkit-example-in-iphone
That code looks fine (except for the non-standard implementation of the init method).
The most likely reason the title (callout) isn't appearing is that in your viewForAnnotation delegate method, you are not setting canShowCallout to YES (it defaults to NO).
In the viewForAnnotation delegate method, after you create the MKAnnotationView, set canShowCallout to YES.
Unrelated to the title/callout not showing, the init method in your MapViewAnnotation class should be implemented like this:
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
self = [super init];
if (self) {
title = ttl;
coordinate = c2d;
}
return self;
}

EXC_BAD_ACCESS when I close my window, which is also my application's delegate

I wrote a Cocoa Application and I got EXC_BAD_ACCESS error when I'm closing an application window. I read that this error usually means problems with memory, but I have ARC mode on and I don't need care about releasing e.t.c. (xCode forbids me to call this functions and manage memory automatically).
Error is pointing at line return NSApplicationMain(argc, (const char **)argv); in main function.
Here's my application's code:
.h file:
#interface MainDreamer : NSWindow <NSWindowDelegate>
{
NSTextField *dreamField;
NSTableView *dreamTable;
NSImageView *dreamview;
NSMutableArray *dreamlist;
NSMutableArray *dataset;
}
#property (nonatomic, retain) IBOutlet NSTextField *dreamField;
#property (nonatomic, retain) IBOutlet NSTableView *dreamTable;
#property (nonatomic, retain) IBOutlet NSImageView *dreamview;
#property (nonatomic, retain) IBOutlet NSMutableArray *dreamlist;
#property (nonatomic, retain) IBOutlet NSMutableArray *dataset;
#property (assign) IBOutlet NSWindow *window;
#end
.m file:
#implementation MainDreamer
#synthesize window;
#synthesize dataset;
#synthesize dreamField;
#synthesize dreamlist;
#synthesize dreamview;
#synthesize dreamTable;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
NSString *applicationPath = [[NSBundle mainBundle] bundlePath];
NSString *filename = [applicationPath stringByAppendingPathComponent:#"dreams"];
NSLog(self.description);
dreamlist = [[NSMutableArray alloc] init];
dataset = [[NSMutableArray alloc] init];
dataset = [NSKeyedUnarchiver unarchiveObjectWithFile:filename];
if([dataset count] != 0) {
int i = 0;
while (i < [dataset count]) {
Dream *dr = [[Dream alloc] init];
dr = [dataset objectAtIndex:i];
[dreamlist addObject: dr.dreamname];
i++;
}
}
[dreamTable reloadData];
}
-(void)applicationWillTerminate:(NSNotification *)notification{
NSString *applicationPath = [[NSBundle mainBundle] bundlePath];
NSString *filename = [applicationPath stringByAppendingPathComponent:#"dreams"];
[NSKeyedArchiver archiveRootObject:dataset toFile:filename];
NSLog(#"finish");
}
- (void) mouseUp:(NSEvent *)theEvent{
long index = [dreamTable selectedRow];
Dream *dr = [[Dream alloc] init];
dr = [dataset objectAtIndex:index];
dr.dreampicture = dreamview.image;
[dataset replaceObjectAtIndex:index withObject:dr];
NSLog(self.description);
}
- (void) tableViewSelectionDidChange: (NSNotification *) notification{
long row = [dreamTable selectedRow];
Dream *dr = [[Dream alloc] init];
dr = [dataset objectAtIndex: row];
if(dr.dreampicture != NULL)
dreamview.image = dr.dreampicture;
NSLog(#"selected row changed");
}
Class "Dream":
#interface Dream : NSObject <NSCoding>
{
NSString *dreamname;
NSImage *dreampicture;
}
#property (retain) NSString* dreamname;
#property (retain) NSImage* dreampicture;
-(id)initWithCoder:(NSCoder *)aDecoder;
-(void)encodeWithCoder:(NSCoder *)aCoder;
#end
What is wrong, why EXC_BAD_ACCESS occurs?I remind that I have xCode 4 with Automatic Reference Counting (ARC)
Thanks
UPDATE
I used Profile to find zombie event. So I found out this: An Objective-C message was sent to a deallocated object(zombie( at adress 0x108d85230)
Responsible Caller - [NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed: saveWindows:]
I had this function in code:
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender{
return TRUE;
}
However after I putted it in comments, this zombie event continue to occur.
The crash is caused by the fact that you made the window your application's delegate. When you close the window, that is the last release that kills it off, and if it's the last window you had up, it causes the application to ask its delegate whether it should quit. Since the window you just killed off is the application's delegate, you get that crash.
Longer explanation and suggestion of solution in my answer on your subsequent question.
This is wrong:
dataset = [[NSMutableArray alloc] init]; // WRONG
dataset = [NSKeyedUnarchiver unarchiveObjectWithFile:filename];
Why? You first allocate an empty array, and store that in the instance variable dataset. But in the next line, you replace the empty array with whatever +unarchiveObjectWithFile: returns. Why is this a problem? Well, if you read the docs, you'll see that it returns nil if the file is not found. This means that you now replace the empty array with nil, and all messages you send to dataset will be ignored (messages to nil are silently ignored in Objective-C)
I assume you actually want load the dataset from file, and only if that failed, start with an empty dataset:
dataset = [NSKeyedUnarchiver unarchiveObjectWithFile:filename];
if (dataset==nil) dataset = [[NSMutableArray alloc] init];
You have a similar error later on:
Dream *dr = [[Dream alloc] init]; // WRONG
dr = [dataset objectAtIndex:index];
You create a Dream object, and then replace it immediately with something from the dataset. What you actually want to do is:
Dream *dr;
dr = [dataset objectAtIndex:index];
or shorter:
Dream *dr = [dataset objectAtIndex:index];
Then again, you could replace the while loop with a fast-enumeration-style for loop:
for (Dream *dr in dataset) {
[dreamlist addObject: dr.dreamname];
}
Finally, to get to a point, I don't think the EXC_BAD_ACCESS actually occurs in main.h. I assume you use Xcode 4. Please use the thread/stack navigator in the right sidebar when debugging to find the actual position where the error occurs.
It could be that the error actually occurs in applicationWillTerminate:, because you try to archive dataset, which is probably nil, and it's probably not allowed to archive nil.
With ARC you should use strong and weak instead of retain and assign.

Archiving and Unarchiving results in Bad Access

I'm having trouble setting up a model object to save the visual state of user generated CALayers in a simple graphics application for the iphone.
I'm attempting to save the background color and frame of all the current layers on screen by passing those properties to model objects which implement the NSCoding protocol and then into an NSMutableArray which the app delegate owns. Then I archive the array with NSKeyedArchiver and store it in the NSUserDefaults.
Each CALayer's backgroundColor property is converted to a UIColor to be encoded by the model object for storage. I think that I'm unarchiving the array incorrectly or not restoring state from the unarchived array correctly. When I attempt to access the UIColor object that was store in the model object, I get an EXC_BAD_ACCESS.
I thought it was possibly a bug with encoding UIColor objects so tried pulling the values out of the CGColorRef with the CGColorGetComponents function and storing them in an array to encode and archive, but I had the same result of bad access after unarchiving, so I think I'm just doing it wrong.
This is my model object:
#interface AILayerData : NSObject <NSCoding> {
UIColor* color;
CGRect frame;
}
#property (retain) UIColor* color;
#property (assign) CGRect frame;
#end
#implementation AILayerData
#synthesize color;
#synthesize frame;
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeObject:color forKey:#"color"];
[coder encodeCGRect:frame forKey:#"frame"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[AILayerData alloc] init];
if (self != nil)
{
color = [coder decodeObjectForKey:#"color"];
frame = [coder decodeCGRectForKey:#"frame"];
}
return self;
}
#end
And this is my archiving implementation:
#implementation AppDelegate
- (void)applicationWillTerminate:(UIApplication *)application {
NSArray *layersArray = viewController.view.layer.sublayers;
dataArray = [NSMutableArray array];
for(AILayer *layer in layersArray)
{
AILayerData *layerData = [[AILayerData alloc] init];
layerData.frame = layer.frame;
UIColor *layerColor = [UIColor colorWithCGColor:layer.backgroundColor];
layerData.color = layerColor;
[dataArray addObject:layerData];
[layerData release];
}
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:layerDataArray] forKey:#"savedArray"];
}
#end
And here is where I restore state:
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
spaceView = [[AISpaceView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = spaceView;
[spaceView release];
spaceView.delegate = self;
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:#"savedArray"];
if (dataRepresentingSavedArray != nil) {
[self restoreStateWithData:dataRepresentingSavedArray];
}
}
- (void)restoreStateWithData:(NSData *)data
{
NSArray *savedLayers = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if (savedLayers != nil) {
NSArray *restoredLayers = [[NSArray alloc] initWithArray:savedLayers];
for(AILayerData *layerDataObject in restoredLayers) {
UIColor *layerColor = layerDataObject.color;
AILayer *newLayer = [[AILayer alloc] init];
newLayer.backgroundColor = layerColor.CGColor;
newLayer.frame = layerDataObject.frame;
newLayer.isSelected = NO;
[self.view.layer addSublayer:newLayer];
[newLayer release];
}
[restoredLayers release];
[spaceView.layer layoutSublayers];
}
}
#end
Any help with this is greatly appreciated. I'm pretty much a noob. I was encoding, archiving and unarching an NSArray of NSNumbers converted from the color's floats in pretty much the same way and getting bad access.
You certainly want to retain the color in initWithCoder:
color = [[coder decodeObjectForKey:#"color"] retain];
or, with the dot syntax as color was declared as a retain property:
self.color = [coder decodeObjectForKey:#"color"];
You are over-releasing layerColor: You don't own it (layerDataObject does), but you are releasing it.
It looks like NSCoder for iPhone doesn't respond to -encodeWithCGRect:
Source: http://17.254.2.129/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/Reference/NSCoder.html

Resources