iOS – NSMutableArray and Block Copy - objective-c

Currently I’m trying to get the hang of a block copy with my current project. The structure of the copy is an NSMutableArray that contains NSIntegers, NSStrings another NSMutableArray and two Objects… Those objects in turn hold NSStrings. The Array contains Objects which hold an NSInteger and Two Objects which contain strings…
I believe I am supposed to use the Block Copy method for coping objects… Code is below…
I am aware the code is not releasing properly… I tried to make the code smaller for your benefit.
Any insight you could shed would be awesome.
//Main controller Excerpt
//Insert Position Information into temporary node point... Node Points can have multiple Positions (or rather you can face multiple directions at the node. Each Node has 3-4 of these.
[newNode.positionArray insertObject:[newPosition copy] atIndex:currentPosition];
Insert the temporary node into the Node Array.
[nodeArray insertObject:[newNode copy] atIndex:count];
//Main Controller Excerpt
//
// Node.h
//
#import <Foundation/Foundation.h>
#class Sequence;
#class Position;
#interface Node : NSObject {
NSInteger Id;
NSInteger currentPosition;
NSString *title;
NSMutableArray *positionArray;
Sequence *forwardSequence;
Sequence *backSequence;
}
-(id) copyWithZone: (NSZone *) zone;
#property (nonatomic, assign) NSInteger Id;
#property (nonatomic, assign) NSInteger currentPosition;
#property (nonatomic, assign) NSString *title;
#property (nonatomic, retain) NSMutableArray *positionArray;
#property (nonatomic, retain) Sequence *forwardSequence;
#property (nonatomic, retain) Sequence *backSequence;
#end
//
// Node.m
//
#import "Sequence.h"
#import "Position.h"
#import "Node.h"
#implementation Node
#synthesize Id;
#synthesize currentPosition;
#synthesize positionArray;
#synthesize title;
#synthesize forwardSequence;
#synthesize backSequence;
-(id) copyWithZone: (NSZone *) zone {
Node *nodeCopy = [[Node allocWithZone: zone] init];
nodeCopy.Id = Id;
nodeCopy.currentPosition = currentPosition;
nodeCopy.positionArray = [positionArray copy];
nodeCopy.title = title;
nodeCopy.forwardSequence = [forwardSequence copy];
nodeCopy.backSequence = [backSequence copy];
return nodeCopy;
}
#end
//
// Position.h
//
#import <Foundation/Foundation.h>
#class Sequence;
#interface Position : NSObject <NSCopying> {
NSInteger Id;
Sequence *leftSequence;
Sequence *rightSequence;
}
#property (nonatomic, assign) NSInteger Id;
#property (nonatomic, retain) Sequence *leftSequence;
#property (nonatomic, retain) Sequence *rightSequence;
-(id) copyWithZone: (NSZone *) zone;
#end
//
// Position.m
//
#import "Sequence.h"
#import "Position.h"
#implementation Position
#synthesize Id;
#synthesize leftSequence;
#synthesize rightSequence;
-(id) copyWithZone: (NSZone *) zone {
Position *positionCopy = [[Position allocWithZone: zone] init];
positionCopy.Id = Id;
positionCopy.leftSequence = [leftSequence copy];
positionCopy.rightSequence = [rightSequence copy];
return positionCopy;
}
#end
//
// Sequence.h
//
#import <Foundation/Foundation.h>
#interface Sequence : NSObject <NSCopying> {
NSInteger numberOfFrames;
NSString *imageNameScheme;
NSString *endFrame;
}
-(id) copyWithZone: (NSZone *) zone;
#property (nonatomic, assign) NSInteger numberOfFrames;
#property (nonatomic, copy) NSString *imageNameScheme;
#property (nonatomic, copy) NSString *endFrame;
#end
//
// Sequence.m
// MCIT
//
#import "Sequence.h"
#implementation Sequence
#synthesize numberOfFrames;
#synthesize imageNameScheme;
#synthesize endFrame;
-(id) copyWithZone: (NSZone *) zone {
Sequence *sequenceCopy = [[Sequence allocWithZone: zone] init];
sequenceCopy.numberOfFrames = numberOfFrames;
sequenceCopy.imageNameScheme = imageNameScheme;
sequenceCopy.endFrame = endFrame;
return sequenceCopy;
}
#end
Works like a charm now thanks all. :D

If your intent is to make this a copyable class, then you need to declare that it conforms to the NSCopying protocol like so:
#interface Node: NSObject <NSCopying> {
Falling to declare the protocol can cause other objects to believe that the class is uncopyable even if it has a copyWithZone: method.

Related

Swift: "Mapper is not a type", using custom mapping class for arrays in swift and Objective C

I have an 2 objective C classes:
Class 1 scanDatabase (Scans a database and puts that into a mutable array)
Class 2 Mapper (Is a mapping class for the database scan "model")
In objective C this successfully scans the database and puts it into a mutable array. Using the mapping class I can access individual groups of elements (AlbumTitles) like so:
for (Mapper *mapper in scanResult) {
NSLog(#"%#", mapper.AlbumTitle);
}
Everything is working as it should and I can return individual elements from my array i.e as above I am only returning album titles.
I then need to use that array in Swift. I call the objective C in my Swift class and again it runs fine and creates the array. This is done with:
let scanTable = ScanTable();
let scanMapper = Mapper();
scanTable.scanTableDo();
but when I try to retrieve a particular set of items like Album title as I did in the objective C for loop above I get the error "scanMapper is not a type" (scanMapper is my swift instance of the objective C mapper class:
I tried two different ways and both have the same error:
for mapper: scanMapper in scanTable.scanResult {
print("\(mapper.AlbumTitle)")
}
for object in scanTable.scanResult as! [scanMapper] {
print("\(mapper.AlbumTitle)")
}
Can I use an objective C class as a model/mapper and not sure whether I would need to recreate it in Swift.
I will include the mapper and scanTable .h and .m code just in case it is needed, plus the bridging header:
Mapper.h:
#import <Foundation/Foundation.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
#interface Mapper : AWSDynamoDBObjectModel <AWSDynamoDBModeling>
#property (nonatomic, strong) NSNumber *SongID;
#property (nonatomic, strong) NSString *Artist;
#property (nonatomic, strong) NSString *SongURL;
#property (nonatomic, strong) NSString *Location;
#property (nonatomic, strong) NSNumber *UserRatings;
#property (nonatomic, strong) NSNumber *AVGUserRating;
#property (nonatomic, strong) NSString *Category;
#property (nonatomic, strong) NSString *PictureURL;
#property (nonatomic, strong) NSNumber *SongDuration;
#property (nonatomic, strong) NSString *SongTitle;
#property (nonatomic, strong) NSNumber *AVGMusicianRating;
#property (nonatomic, strong) NSString *AlbumTitle;
#end
Mapper.m
#import <AWSDynamoDB/AWSDynamoDB.h>
#import "Mapper.h"
#implementation Mapper
+ (NSString *)dynamoDBTableName {
return #"Songs";
}
+ (NSString *)hashKeyAttribute {
return #"SongID";
}
#end
ScanTable.h:
#import <Foundation/Foundation.h>
#import <AWSDynamoDB/AWSDynamoDB.h>
#interface ScanTable : NSObject
- (void) scanTableDo;
#property (nonatomic, strong) NSMutableArray *scanResult;
#end
ScanTable.m
#import "ScanTable.h"
#import "Mapper.h"
#implementation ScanTable
- (void) scanTableDo {
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
AWSDynamoDBScanExpression *scanExpression = [AWSDynamoDBScanExpression new];
scanExpression.limit = #10;
[[dynamoDBObjectMapper scan:[Mapper class]
expression:scanExpression]
continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(#"The request failed. Error: [%#]", task.error);
}
if (task.exception) {
NSLog(#"The request failed. Exception: [%#]", task.exception);
}
if (task.result) {
AWSDynamoDBPaginatedOutput *paginatedOutput = task.result;
NSMutableArray *scanResult = [[NSMutableArray alloc] initWithArray:paginatedOutput.items]; //// ADDED /////
for (Mapper *mapper in scanResult) {
NSLog(#"%#", mapper.AlbumTitle);
}
}
return nil;
}];
}
#end
//EDITED ADDED BRIDGING HEADER//
MySampleApp-Bridging-Header.h:
//
// MySampleApp-Bridging-Header.h
// MySampleApp
#import "ScanTable.h"
#import "Mapper.h"
#import "Hello World.h"
Thanks for your help
The problem is just as the error explains, you're attempting to cast the items in your array to scanMapper, which is a variable holding an instance of Mapper, not the Mapper type itself. Assuming that scanTable.scanResult is an NSArray of Mappers, try this instead:
guard let scanResult = scanTable.scanResult as? [Mapper] else {
print("scanResult was not an array of mappers!")
return
}
for mapper: Mapper in scanResult {
print("\(mapper.AlbumTitle)")
}

NSObject returns nothing XCode 6

I moved my app to XCode 6 and found this problem. I have NSObject and it stopped returning objects when initialized, I use XCode 6 iPhone 6 Simulator.
My .h file:
#import <Foundation/Foundation.h>
#interface RBGAlpha : NSObject{
NSString *red;
NSString *blue;
NSString *green;
NSString *alpha;
}
#property (nonatomic, retain) NSString *red;
#property (nonatomic, retain) NSString *blue;
#property (nonatomic, retain) NSString *green;
#property (nonatomic, retain) NSString *alpha;
-(id)initWithName:(NSString *)r bl:(NSString *)b gr:(NSString *)g al:(NSString *)a;
#end
my .m file
#import "RBGAlpha.h"
#implementation RBGAlpha
#synthesize red,blue,green,alpha;
-(id)initWithName:(NSString *)r bl:(NSString *)b gr:(NSString *)g al:(NSString *)a{
self = [super init];
if (self) {
self.red = r;
self.blue = b;
self.green = g;
self.alpha = a;
}
return self;
}
#end
I use something like this in viewDidLoad method to create my objects:
RBGAlpha *tmpObj=[[RBGAlpha alloc] initWithName:#"0.01" bl:#"0.01" gr:#"0.01" al:#"1.00"];
However, while running the app in Simulator iPhone 6 this returns nothing
Has anybody dealt with that kind of problem?
I think that you're being mislead. There is indeed a value, that is what 0x786... in the value field means.
Summary saying 0 objects is confusing. I cannot understand why it would say that, but I bet if you typed po tmpObj into LLDB it would not return nil but the address showing next to "Value".
If you want to see something more interesting from the Xcode debugger consider implementing debugQuickLookObject.
On a side note, you can omit the definition of your instances variables in
#interface RBGAlpha : NSObject{
NSString *red;
NSString *blue;
NSString *green;
NSString *alpha;
}
And you also don't need to #synthesize each of them anymore, the compiler included with Xcode 5 and up does this for you.

Incompatible pointer to integer conversion

Im learning Objective-C and im having some problems with a project.
I made a class with a method to create a new object and im having some issues trying to create a new Object, i dont know what is the best kind of proporties in this case.
Class.h
#import <Foundation/Foundation.h>
#interface ObrasData : NSObject
#property (strong) NSNumber *ID;
#property (assign) char presupuesto;
#property (assign) char descripcion;
#property (assign) char aasm_state;
#property (assign) char clienteID;
- (id)initWithID:(NSNumber*)ID presupuesto:(char)presupuesto description:(char)description aasm_state:(char)aasm_state clienteID:(char)clienteID;
#end
Class.m
#implementation ObrasData
#synthesize ID = _ID;
#synthesize presupuesto = _presupuesto;
#synthesize descripcion = _descripcion;
#synthesize aasm_state = _aasm_state;
#synthesize clienteID = _clienteID;
- (id)initWithID:(NSNumber *)ID presupuesto:(char)presupuesto description:(char)description aasm_state:(char)aasm_state clienteID:(char)clienteID{
if ((self = [super init])) {
self.ID = ID;
self.presupuesto = presupuesto;
self.descripcion = description;
self.aasm_state = aasm_state;
self.clienteID = clienteID;
}
return self;
}
And here im having the error: "Incompatible pointer to integer conversion"
ObrasData *obra1 = [[ObrasData alloc] initWithID:[NSNumber numberWithInt:1] presupuesto:100 description:#"obra de prueba" aasm_state:#"En proceso" clienteID:#"dm2"];
What im doing wrong? I want to show later the object on a listview
Class.h
#import <Foundation/Foundation.h>
#interface ObrasData : NSObject
#property (strong) NSNumber *ID;
#property (strong) NSString *presupuesto;
#property (strong) NSString *descripcion;
#property (strong) NSString *aasm_state;
#property (strong) NSString *clienteID;
- (id)initWithID:(NSNumber*)ID presupuesto:(NSString *)presupuesto description:(NSString *)description aasm_state:(NSString *)aasm_state clienteID:(NSString *)clienteID;
#end
Class.m
#implementation ObrasData
#synthesize ID = _ID;
#synthesize presupuesto = _presupuesto;
#synthesize descripcion = _descripcion;
#synthesize aasm_state = _aasm_state;
#synthesize clienteID = _clienteID;
- (id)initWithID:(NSNumber *)ID presupuesto:(NSString *)presupuesto description:(NSString *)description aasm_state:(NSString *)aasm_state clienteID:(NSString *)clienteID{
if ((self = [super init])) {
self.ID = ID;
self.presupuesto = presupuesto;
self.descripcion = description;
self.aasm_state = aasm_state;
self.clienteID = clienteID;
}
return self;
}
and call like this :
ObrasData *obra1 = [[ObrasData alloc] initWithID:[NSNumber numberWithInt:1] presupuesto:#"100" description:#"obra de prueba" aasm_state:#"En proceso" clienteID:#"dm2"];
In initWithID method second parameter input type is char but you are passing integer 100.
[[ObrasData alloc] initWithID:[NSNumber numberWithInt:1] presupuesto:100 description:#"obra de prueba" aasm_state:#"En proceso" clienteID:#"dm2"];
change presupuesto to Char

Creating a readonly version of POCO objects in Obj-C?

Suppose I have a simple DTO class like this:
#interface MYNugget
#property (nonatomic, copy) NSString *color;
#end
#implementation MYNugget
// automatic #synthesize
#end
And I then later want to store this object in another class in a way such that it is not modifiable (that is, make the color property readonly via a - (void)freeze or something.
What is the best way to accomplish this short of writing my own setters?
The standard way is to have to classes, one mutable and an immutable one.
#interface MYNugget
#property (nonatomic, copy, readonly) NSString *color;
#end
and
#interface MYMutableNugget : MYNugget
#property (nonatomic, copy, readwrite) NSString *color;
#end
Your other class would just expose a MYNugget property, ideally again as copy. That's how we do it with NSString all the time.
What I would do is set the color via the constructor only:
#interface MYNugget
#property (nonatomic, copy, readonly) NSString *color;
- (id) initWithColor:(NSString *)color;
#end
#implementation MYNugget
#synthesize color = _color;
- (id) initWithColor:(NSString *)color {
self = [super init];
if (self) {
_color = [color copy];
}
return self;
}
#end

Categories instance methods do not invoke

I have a class(Core Data Generated):
#interface Place : NSManagedObject
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSString * subtitle;
#property (nonatomic, retain) NSNumber * latitude;
#property (nonatomic, retain) NSNumber * longitude;
#end
#implementation Place
#dynamic title;
#dynamic subtitle;
#dynamic latitude;
#dynamic longitude;
#end
Adn a category for it:
#interface Place (Create)
+ (Place *)placeWithTitle:(NSString *)title
inManagedObjectContext:(NSManagedObjectContext *)context;
+(Place *) placeWithTitle:(NSString *)title andSubtitle:(NSString *)subtitle inManagedObjectContext:(NSManagedObjectContext *)context;
+(Place *) placeWithCoordinate:(CLLocationCoordinate2D) coordinate inManagedObjectContext:(NSManagedObjectContext *)context;
- (void) setLattitudeAndLongitudeByCoordinate:(CLLocationCoordinate2D) coordinate;
- (CLLocationCoordinate2D) coordinate;
#end
In this category a have to instance methods:
- (void) setLattitudeAndLongitudeByCoordinate:(CLLocationCoordinate2D) coordinate
{
self.latitude=[NSNumber numberWithDouble:coordinate.latitude];//break point HERE
self.longitude=[NSNumber numberWithDouble:coordinate.longitude];
}
-(CLLocationCoordinate2D) coordinate
{
CLLocationCoordinate2D coord;//break point HERE
coord.latitude=[self.latitude doubleValue];
coord.longitude=[self.longitude doubleValue];
return coord;
}
As you see i have to breakpoints there. Now, then i call those methods
#import "Place+Create.h"
-(void)someMethod
{
[self.place setLattitudeAndLongitudeByCoordinate:coordiante];
}
It never seem to reach those breakpoints inside the method setLattitudeAndLogitudeByCoordinate,
and debug shows that it even doesn't call them! Why?
Is someMethod ever reached? Check that using a breakpoint or an extra NSLog at its head.
If not, then your problem is somewhere else as your program flow is different than you expected it to be.
If it is reached then self.place obviously is nil. That means you never initialized it and again, your program flow is different than you thought it would be.