App stops working after adding messageUI.framework - xcode

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.

Related

How to observe ABPersonView changes for ABPerson

I know that ABPersonView is not KVO complaint. My issue is that despite declared property of ABPersonView being retained every time I access the property I get different object. Am I doing something wrong or is this correct that every time there was a change in ABPersonView I have to update model with new ABPerson object? Using El Capitan GM.
ABPersonView:
#property (readwrite, retain) ABPerson *person;
// An ABPerson record for display.
// Raises if person originates from ABAddressBook's +sharedAddressBook.
// Person must be exist in an ABAddressBook created and manipulated on the main thread only.
// When person is nil, displays an empty selection state.
Code:
#import "AppDelegate.h"
#import AddressBook;
static void * ABPersonVCContext = &ABPersonVCContext;
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#property (strong) ABPerson *person;
#property (strong) ABPersonView *personView;
#property (strong) ABAddressBook *book;
#property (assign, getter=isEditing) BOOL editing;
#property NSTimer *timer;
#end
#implementation AppDelegate
- (instancetype)init {
self = [super init];
if (self) {
_book = [[ABAddressBook alloc] init];
NSString *vCardRepresentation = #"BEGIN:VCARD\r\nVERSION:3.0\r\nN:AA;BB;;;\r\nFN:\r\nEND:VCARD\r\n";
NSData *vCardData = [vCardRepresentation dataUsingEncoding:NSUTF8StringEncoding];
_person = [[ABPerson alloc] initWithVCardRepresentation:vCardData];
[_book addRecord:_person];
[self addObserver:self forKeyPath:#"editing"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:ABPersonVCContext];
#ifdef DEBUG
NSLog(#"%s %d %s", __FILE__, __LINE__, __PRETTY_FUNCTION__);
NSLog(#"%#",_person);
#endif
}
return self;
}
- (void)awakeFromNib
{
self.personView = [[ABPersonView alloc] initWithFrame:self.window.contentView.frame];
self.personView.person = self.person;
[self.window.contentView addSubview:self.personView];
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(reverseEditing) userInfo:NULL repeats:YES];
[self.timer fire];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == ABPersonVCContext) {
if ([keyPath isEqualTo:#"editing"]) {
#ifdef DEBUG
NSLog(#"%s %d %s", __FILE__, __LINE__, __PRETTY_FUNCTION__);
NSLog(#"%#",self.personView.person);
#endif
}
} else {
#try {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
#catch (NSException *exception) {
;
}
#finally {
;
}
}
}
- (void)reverseEditing
{
self.editing = !self.editing;
}
#end
EDIT:
The new object comes from different addressBook instance:
(lldb) po [newPerson addressBook]
<ABAddressBook: 0x6080000d50e0>
(lldb) po self.book
<ABAddressBook: 0x6080000c4130>
(lldb) po [self.person addressBook]
<ABAddressBook: 0x6080000c4130>
EDIT2:
Even registering for notifications does not help because different object is being modified.
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(changeOccured:) name:kABDatabaseChangedNotification object:nil];
[nc addObserver:self selector:#selector(changeOccured:) name:kABDatabaseChangedExternallyNotification object:nil];
Unfortunately every call to person property of personView triggers ABPersonViewAPIAdapter that converts CNContact to ABPerson. So if one doesn't want to use CNContact on El Capitan he has to propagate edited ABPerson back to the model object.
One can try following code (hope this will save some time to someone)
NSLog(#"%#",[self.personView performSelector:#selector(addressBook) withObject:nil]);
NSLog(#"%#",[self.personView performSelector:#selector(_APIAdapter) withObject:nil]);
NSLog(#"%#",[self.personView performSelector:#selector(_contact) withObject:nil]);

Navigation between NSVIewController

I am very new to MAC OSX app development.
In my application I have three NSViewControllers, which are PracticeController, NoteController and QuestionController. I have to navigate to NoteViewController from PracticeController and QuestionController and comeback to the viewController from which NoteController has navigated.
For example: when we navigate to NoteController from PracticeController, then when we tap on back button from NoteController I have to come to PracticeController, and when we navigate to NoteController from QuestionController, then when we tap on back button from NoteController I have to come to QuestionController.
Please help me how to do this? I am badly searching for it. Thanks.
well, after a long time search, I found a open source library which ports the UIKit to MacOSX.
https://github.com/BigZaphod/Chameleon.git
But it's too complicated for me, so I wrote my own Navigation controller.
NSNavigationController.h
#import <Cocoa/Cocoa.h>
#class BaseViewController;
#interface NSNavigationController : NSResponder
#property (nonatomic, strong) BaseViewController *rootViewController;
- (id)initWithRootViewController:(BaseViewController *)rootViewController;
- (NSView*)view;
- (void)pushViewController:(BaseViewController *)viewController animated:(BOOL)animated;
- (BaseViewController *)popViewControllerAnimated:(BOOL)animated;
#end
NSNavigationController.m
#import "NSNavigationController.h"
#import "AppDelegate.h"
#import "BaseViewController.h"
#interface NSNavigationController ()
#property (nonatomic, strong) NSMutableArray *viewControllerStack;
#end
#implementation NSNavigationController
- (id)initWithRootViewController:(BaseViewController *)rootViewController
{
self = [super init];
if (self) {
self.rootViewController = rootViewController;
self.rootViewController.navigationController = self;
self.viewControllerStack = [[NSMutableArray alloc] initWithObjects:self.rootViewController, nil];
}
return self;
}
- (NSView*)view
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
return topViewController.view;
}
- (void)pushViewController:(BaseViewController *)viewController animated:(BOOL)animated
{
if (viewController != nil) {
[self removeTopView];
[self.viewControllerStack addObject:viewController];
viewController.navigationController = self;
[self addTopView];
}
}
- (BaseViewController *)popViewControllerAnimated:(BOOL)animated
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
[self removeTopView];
[self.viewControllerStack removeLastObject];
[self addTopView];
return topViewController;
}
- (void)removeTopView
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
[topViewController.view removeFromSuperview];
}
- (void)addTopView
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
AppDelegate *delegate = (AppDelegate*)[NSApp delegate];
[delegate.window.contentView addSubview:topViewController.view];
}
#end
BaseViewController.h
#import <Cocoa/Cocoa.h>
#class NSNavigationController;
#interface BaseViewController : NSViewController
#property (nonatomic, weak) NSNavigationController *navigationController;
#end
BaseViewController.m
#import "BaseViewController.h"
#interface BaseViewController ()
#end
#implementation BaseViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
}
return self;
}
#end
It's the simplest NavigationController. I didn't implement the view animation. Hope it can help.

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;
}

xcode calculator app method

I'm doing a calculator app base on a online tutorial, itunes.apple. com/itunes-u/ipad-iphone-application- development/ id473757255 (tut 2)
I followed every step closely and all was fine, until the finishing step of a method call performOperation. When I build and run, the numbers and enter function work fine. Only the operation method is not working. So I presume that the main trouble is with the operation method.
BrainCalculator.h
#interface CalculatorBrain : NSObject
-(void) pushOperand: (double)operand;
-(double) performOperation: (NSString*) operation;
#end
BrainCalculator.m
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray* _operandStack;
#end
#implementation CalculatorBrain
#synthesize _operandStack;
-(NSMutableArray *)operandStack
{
if (!_operandStack){
_operandStack= [[NSMutableArray alloc ]init];
}
return _operandStack;
}
-(void)pushOperand:(double)operand{
NSNumber *operandObject = [NSNumber numberWithDouble:operand];
[self.operandStack addObject:operandObject];
}
-(double)popOperand{
NSNumber *operandObject= [self.operandStack lastObject];
if (operandObject) [self.operandStack removeLastObject];
return [operandObject doubleValue];
}
-(double)performOperation:(NSString *)operation
{
double result = 0;
if ([operation isEqualToString:#"+"]){
result=[self popOperand] + [self popOperand];
}else if ([#"*" isEqualToString:operation]){
result = [self popOperand] * [self popOperand];
}else if ([operation isEqualToString:#"-"]){
double subtrahend = [self popOperand];
result = [self popOperand] - subtrahend;
}else if( [operation isEqualToString:#"/"]){
double divisor = [self popOperand];
if (divisor) result = [self popOperand] / divisor;
}
[self pushOperand:result];
return result;
}
#end
Initially, it seem to me that the performOperation method was pretty fishy, so I tried fiddling the
}else if ([#"*" isEqualToString:operation]){
to
}else if ([operation isEqualToString:#"*"]){
hoping it would work, but sadly it didn't.
Just for additional information
viewcontroller.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringANumber;
#property (nonatomic, strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display;
#synthesize userIsInTheMiddleOfEnteringANumber;
#synthesize brain= _brain;
-(CalculatorBrain*)brain
{
if(!_brain)_brain = [[CalculatorBrain alloc]init];
return _brain;
}
- (IBAction)digitPressed:(UIButton *)sender {
NSString * digit= [ sender currentTitle];
if (userIsInTheMiddleOfEnteringANumber){
self.display.text = [self.display.text stringByAppendingString:digit];
}
else{
self.display.text=digit;
self.userIsInTheMiddleOfEnteringANumber = YES;
}
}
- (IBAction)enterPressed {
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
}
- (IBAction)operationPressed:(UIButton *)sender {
if (self.userIsInTheMiddleOfEnteringANumber){
[self enterPressed];
}
NSString *operation = [sender currentTitle];
double result = [self.brain performOperation:operation];
self.display.text = [NSString stringWithFormat:#"%g", result];
}
#end
help will be greatly appreciated as I'm practising xcode to prepare myself for my final year major project.

Expected expression error

What does this Expected expression error mean on this line of code:
[super setNilValueForKey:key];
Code:
#import "Person.h"
#implementation Person
- (id) init
{
self = [super init];
expectedRaise = 5.0;
personName = #"New Person";
return self;
}
- (void)dealloc
{
[personName release];
[super dealloc];
}
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqual:#"expectedRaise"])
{
[self setExpectedRaise:0.0];
}
else
{
[super setNilValueForKey:key];
}
}
#synthesize personName;
#synthesize expectedRaise;
#end
.h:
#import <Foundation/Foundation.h>
#interface Person : NSObject
{
NSString *personName;
float expectedRaise;
}
#property (readwrite, copy) NSString *personName;
#property (readwrite) float expectedRaise;
#end
If you really got
[super setNilValueForKey:<#key#>];
in your code, the solution should be as simple as
[super setNilValueForKey:key];
isEqual is the wrong method since I wanted to compare to a string value isEqualToString is correct.
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqualToString:#"expectedRaise"])
{
[self setExpectedRaise:0.0];
}
else
{
[super setNilValueForKey:key];
}
}

Resources