I am really new to Xcode. I don't quite understand exactly what it means when you initialize variables in certain places, but my code works so this isn't the issue... for now. Anyway, here is a my .h file. Everywhere there is a "----" it just means there is code there.
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
NSInteger charactersLocked[3] = {0,0,1};
int charSel = 0;
#interface Tutorial : UIViewController
{
-------
}
------
#end
So I need to access the array charactersLocked in a different .m file, lets call it File2 and this one File1. When I try to #import "File1.h" in File2.m, the program crashes and gives me this error for both charactersLocked and charSel:
duplicate symbol _charactersLocked in:
/Users/me/Library/Developer/Xcode/DerivedData/SpaceRace-
apawbkpiogvbvddranqfltyybuqr/Build/Intermediates/SpaceRace.build/Debug-
iphoneos/SpaceRace.build/Objects-normal/arm64/Tutorial.o
/Users/me/Library/Developer/Xcode/DerivedData/SpaceRace
apawbkpiogvbvddranqfltyybuqr/Build/Intermediates/SpaceRace.build/Debug-
iphoneos/SpaceRace.build/Objects-normal/arm64/Space.o
I have no idea what this is. I've tried looking for solutions online, but none of them seem to work. I am not importing the .m file by accident. If there is an easier way to just get access to that specific array, please let me know. Sorry if this post was formatted horribly, it is my first time so bear with me. Thank you.
The short answer to your question is located in this answer; you need to declare your variables as extern for the compiler to know that you want to use it in multiple files.
This is very rarely done in Objective-C though, because its heritage as an object-oriented programming language means that global state in programs is most often handled in class methods or singleton classes. Without knowing too much about your program, I am going to guess that you want a singleton class, something like CharacterLocker, which would look like this:
CharacterLocker.h
#interface CharacterLocker : NSObject
{
NSInteger charactersLocked[3];
}
+ (id) sharedObject;
#property NSInteger* charactersLocked;
#end
CharacterLocker.m
#implementation CharacterLocker
#synthesize charactersLocked;
+ (void) sharedObject
{
static CharacterLocker *singleton = nil;
// Required so that multiple calls to sharedObject don't create two
static dispatch_once_t pred;
dispatch_once(&pred, ^{ singleton = [[CharacterLocker alloc] init]; });
return singleton;
}
- (id) init
{
if ( self = [super init] )
{
charactersLocked[0] = 0;
charactersLocked[1] = 0;
charactersLocked[2] = 1;
}
return self;
}
#end
Then, in your code, you call [CharacterLocker sharedObject].charactersLocked to access the array.
Related
I have an Objective-C class that populates a std:vector with millions of points. The structure of the vector is:
typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;
So a CGContour is a vector of CGPoints and CGContours is a vector of the CGContour vector.
I need to access this data in a Swift class somehow. I don't want to use an NSArray because it has a huge overhead compared to using vector (it is like 10x as big and slow).
What would be the most efficient way to get millions of CGPoints accessible in Swift from my Objective-C class?
Edit:
I am populating my CGContours vector like this:
contourVector = CGContours(contours.size());
populatedContourNum = 0
//contours is OpenCV's contours
for( long c = 0; c < contours.size(); c++) {
if (populatedContourNum >= contourVector.size()) {
contourVector.resize(contourVector.size() + 1);
}
contourVector[populatedContourNum] = CGContour(contours[c].size());
for( long pointNum = 0; pointNum < contours[c].size(); pointNum++ )
{
contourVector[populatedContourNum][pointNum] = CGPointMake(contours[c][pointNum].x * scale,
contours[c][pointNum].y * scale);
}
populatedContourNum++;
}
Some parts are not clear enough but I will try to show you some example.
First of all, you need to prepare a class which can access your contourVector. (I cannot see if it is an instance field or a global variable, if it is an instance field, you may use the existing class.)
Create a header for the prepared class, again you may utilize the existing header, but this header needs to be compiled both in C-context and in C++ context. So, if your existing header contains some declaration which cannot be compiled in C-context, you may need separated two headers or some #ifs.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface YourClass : NSObject
- (NSInteger)contoursSize;
- (NSInteger)contourSizeAtIndex:(NSInteger)index;
- (CGPoint *)contourAtIndex:(NSInteger)index;
//...
#end
NS_ASSUME_NONNULL_END
Then add 3 methods to the class specified in the header:
#import "YourClass.h"
#import <vector>
typedef std::vector<CGPoint> CGContour;
typedef std::vector<CGContour> CGContours;
static CGContours contourVector;
#implementation YourClass
- (NSInteger)contoursSize {
return contourVector.size();
}
- (NSInteger)contourSizeAtIndex:(NSInteger)index {
return contourVector[index].size();
}
- (CGPoint *)contourAtIndex:(NSInteger)index {
return contourVector[index].data();
}
#end
Please do not forget to include the header inside your Project-Bridging-Header.h:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "YourClass.h"
You need to create a Swift side wrapper class, as you cannot create UnsafeBufferPointer in Objective-C.
class YourClassWrapper {
let yourInstance = YourClass()
var count: Int {
return yourInstance.contoursSize()
}
subscript(index: Int) -> UnsafeBufferPointer<CGPoint> {
guard 0..<count ~= index else {fatalError("Index \(index) out of bounds \(0..<count)")}
let start = yourInstance.contour(at: index)
let count = yourInstance.contourSize(at: index)
return UnsafeBufferPointer(start: start, count: count)
}
}
With these preparations above, you can access each CGPoint as:
let wrapper = YourClassWrapper()
let point = wrapper[0][1]
Or you can get the pointer to the first element in CGContour as:
let ptr = wrapper[0].baseAddress!
You may need to modify some parts to fit this into your actual code. Hope you can make it.
I've been trying to work with MATLAB classes & structs in order to develop a traffic simulation. I have not worked actively with MATLAB classes before, so it gets a bit tricky at times. This questions involves manipulating a struct, which is a property of a class.
Top-level access
vehicles_handle = VehiclesHandle;
vehicles_handle.CreateVehicles(InitialTrafficDensity);
vehicles_handle.vehicles(1)
Class definition
classdef VehiclesHandle
%VEHICLESHANDLE Summary of this class goes here
% Detailed explanation goes here
properties
active_vehicles_count
vehicles
end
methods (Access = public)
function obj = VehiclesHandle
obj.active_vehicles_count = 0;
obj.vehicles = struct('lane',0,'position',0,'velocity',0);
end
function obj = CreateVehicles(obj,InitialTrafficDensity)
obj.active_vehicles_count = obj.active_vehicles_count + 1;
obj.vehicles(1).lane = 1;
obj.vehicles(1).position = 3;
obj.vehicles(1).velocity = 3;
obj.vehicles(2).lane = 2;
obj.vehicles(2).position = 3;
obj.vehicles(2).velocity = 3;
end
Now, I can't see the output as expected (which is vehicles_handle.vehicles(1)), I see them the properties of the vehicle 1 as 0's. The situation changes, of course, when I put then in the function VehiclesHandle, but I want to handle creation of vehicles this way.
I know that the code might not be the most efficient way to handle this, but I really do want to learn about handling a struct in this class without pain. Thanks for all the constructive comments and help in advance.
Getting rid of the problem is quite easy:
classdef VehiclesHandle
has to be
classdef VehiclesHandle < handle
And to understand why, please read Comparison of Handle and Value Classes.
I have many class in my library almost 300, and I want to generate instance name by loop. In other words I wanna instead of this approach(witch has many code line):
X:This is my problem:
var cm1: Cm1 = new Cm1();
var cm2: Cm2 = new Cm2();
var cm3: Cm3 = new Cm3();
...
use like this approach (less than 10 code lines):
Y:I think this is solution:
for (var i: uint = 1; i < 4; i++)
{
var getChildByName("cm" + i): getChildByName("Cm" + i) = new getChildByName("Cm" + i);
}
but I know above code does not work, is there any way to make them !
-What am I actually trying to solve?
Make many variable by a few line code and save time and size app!
-Why do I have ~300 classes and why are you trying to create them in a loop at once?
This is about to data of request application!
-What do these classes do that you unconditionally need one of each all at the same time?
Because those data would show at first time!
First, it is better to store the classes in an Array or Object rather than an external variable for each item. if you want to access them by name, better to use object:
var classList:Object=new Object();
Then in your loop:
for(var i:uint=1;i<NumberOfClasses;i++){
classList["cm"+i.toString()]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
getDefinitionByName is used to make Constructors using String;
Note: if your classes contain a package directory, you should include it. for example:
getDefinitionByName("myclasses.cm.Cm123")();
Then you can access them using Bracket syntax:
classList["cm123"].prop=val;
And don't forget to:
import flash.utils.getDefinitionByName;
I Hope it will help.
EDIT
to use Array instead of object, the loop should be:
for(var i:uint=1;i<NumberOfClasses;i++){
classList[i]=new (getDefinitionByName("Cm"+i.toString()) as Class)();
}
then to access them:
addChild(classList[0]);//0 or any other index;
On a lot of NSURLConnection examples I see the following lines:
NSURLConnection *theConnection = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
if(theConnection)
{
webData = [[NSMutableData data]retain];
}
else
...
I wonder - what is this supposed to do? and why does it work? I thought that data is an accessor method, and since your not calling it on an instanciated object, it will return nil, and by retaining it you actually do nothing.
This is the way I have seen to get data on connections like this:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:url] delegate:self startImmediately:YES];
if( connection )
{
while (!finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
finished is an ivar that gets set to YES on connectionDidFinishLoading:
Can anyone clear this up for me? Which should be used and what's the difference?
[NSMutableData data] is not an accessor but a so-called class method. You probably know [NSMutableData alloc], that too is a class method and means it is tied to the class but not an instance. The typical way to denote that a method is a class method is by prefixing it with a plus: +[NSMutableData data].
In this case, the method is inherited from the NSData class (but does return an NSMutableData instance, since you're calling it on that class).
An implementation might look like this:
#interface NSMutableData
+ (id)data
{
return [[[self alloc] init] autorelease];
}
#end
Note that self in this case is the NSMutableData class.
In other languages like C++, C# and Java (AFAIK) these would be methods that you specify with the static keyword.
I've been using C-style functions, but I just learned they can't see instance variables. So I was advised to convert them to Objective-C methods.
NSString* myfunc ( int x )
becomes:
- (NSString *)myfunc:(int)x
and
myString = myfunc(x);
becomes
myString = [myString myfunc:x];
??
This compiles with ominous warnings, but does not work. What have I misunderstood?
It looks like your call is incorrect. Perhaps try:
NSString *myString = [self myfunc:x];
As far as I understand, you send the -myfunc: message to a NSString object. So the -myfunc: method should be declared in NSString class (or a category of NSString).
If this is what you want to do, you don't need to return the object itself as the result of the method: you can modify its instance variables in the method implementation. The method call (or message sending) looks like:
[myString myfunc:x];
If you want to send the message to an object of another class and return a string, your method declaration is correct but must appear in your class implementation and the receiver of the message (this is the item on the left in the square brackets) must be of that class:
#implementation MyClass
-(NSString *)myfunc:(int)x
{
NSString * returnString;
...// do something with x, returnString and instance variables
return returnString;
}
#end;
...
MyClass * myobj = [[MyClass alloc] init];
NSString * myString = [myobj myfunc:42];
As a second answer, I am trying to understand your problem through all your recent questions.
At the beginning, there was a C function returning a pointer to a NSString object:
NSString * myfunc( int x )
{
... // Do something with x
NSString * myString = #"MYDATA";
... // Do something with myString
return myString;
}
Then, you wanted to add in that function some code about an UIImage object:
image1.image = [UIImage imageNamed:#"image1.png"];
You were advised to convert the function to a method. If you want to access .image instance variable, this method has to belong to the class of image1 object (let's say this is AlanImage class). Something like this:
#interface AlanImage : NSObject {
UIImage image;
}
- (NSString *) myfuncWithParam: (int) x;
#end;
#implementation AlanImage
- (NSString *) myfuncWithParam: (int) x
{
NSString * myString = #"MYDATA";
image = [UIImage imageNamed:#"image1.png"];
return myString;
}
#end
Third, you didn't know what was the receiver of the method. My investigations tend to lead to your image object as a good candidate:
aNiceString = [image myfunc:aNiceInteger];
Finally (this question), not getting a satisfying answer, you reworded your third question, with success this time as it happens.
I am curious to get a more complete view of your project in order to give you some hints. Anyway, it seems that you are learning Objective-C and object oriented concepts: congratulations and stay motivated!
You haven't worked out what Object Oriented Programming is. With [theObject method] you can only call methods belonging to the specific instance.
I am not sure that following trick correctly work for a "general" objective-c, but in apple implementation you can do such:
#interface SomeClass: NSObject {
int m_someVariable;
...
};
- (NSString *) someMethod;
...
#end
#implementation SomeClass
...
//pure c function with extra one parameter
//for accessing to instance variables
static NSString privatePlainCeeMethod(SomeClass *my, int fortyTwo) {
NSString *str;
//access to a instance variable as for a usual
//cee structure field: my->fieldName
...
return [NSString stringWithFormat:#"someVariable:%d, fortyTwo:%d",
my->m_someVariable, fortyTwo];
};
- (NSString *) someMethod {
...
return privatePlainCeeMethod(self,42);
};
...
#end
I use such trick to divide a big objc method on observable private simple functions. These functions (a) do not pollute class interface and (b) are invoked faster than objc method.