Failed to use CGPoint, the struct, in Swift - swift

My Situation:
I have learnt Swift for a while and Swift is my only language I've learnt for iOS Development, which means I did not learn Objective-C Systematically. I can just read OC Code a little.
I got a CGPoint problem when I tried to translate a OC project to Swift project.
Objective-C Code:
- (void)drawFramesetter:(CTFramesetterRef)framesetter
attributedString:(NSAttributedString *)attributedString
textRange:(CFRange)textRange
inRect:(CGRect)rect
context:(CGContextRef)c
{
.
.
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, textRange, path, NULL);
CFArrayRef lines = CTFrameGetLines(frame);
NSInteger numberOfLines = CFArrayGetCount(lines);
CGPoint lineOrigins[numberOfLines]; // *** The place I had been obstructed! ***
.
.
.
}
My Question:
I have no idea why this line of code, declared as CGPoint lineOrigins[numberOfLines], have no * to create an instance variable, lineOrigins ?
My unproven guess is that CGPoint is a struct rather than a Class, but it's still so mysterious to me that created an instance variable without * and =.
Another point confused me is [numberOfLines]. Is [numberOfLine] an array?
Please teach me how to translate CGPoint lineOrigins[numberOfLines]; into Swift or show me some hints.
An big appreciation for your guide and time.
Ethan Joe

The line
CGPoint lineOrigins[numberOfLines];
Creates a C array of CGPoint objects.
It's written inside a function, so it creates a local (stack) variable.
That code will only compile if numberOfLines is a compile-time constant, because the compiler has to allocate a fixed amount of space for your array on the stack at compile time.
C structs are simple "templates" that interpret a block of memory as containing one or more scalar values. The values are stored sequentially in memory.
A C array is also a way of looking at a block of memory, as a sequential series of one or more scalar "things." Those scalar things can be simple scalars like integers, or they can be structs.
When you define a C array like in your example, the compiler makes memory space for the full array, and sets the variable to a pointer to the first element.
The type of lineOrigins is actually type "pointer to CGPoint". In C, an array type and a pointer to an object of that type are interchangeable. It is a bit like a Swift unsafe buffer pointer. There's no range checking.
EDIT:
A similar Swift declaration would be:
var lineOrigins = [CGPoint]()
or, to pre-fill it with a bunch of zero points:
var lineOrigins = [CGPoint](count: numberOfLines, repeatedValue: CGPointZero)

CGPoint is a C struct, which should translate into a C structure.
CGPoint lineOrigins [...] is a local variable named lineOrigins, which is an array of struct CGPoint.
CGPoint lineOrigins [numberOfLines] is a local variable named lineOrigins, which is an array of struct CGPoint with numberOfLines elements.
There is an array init method where you pass the number of array elements, and one array element which is duplicated.

Related

Pointer dereferencing Swift

In C & Objective C, we used to dereference a pointer and get the value as follows:
p->a = 1
or int x = p->a
But I can't find an equivalent in Swift. I have a return type UnsafePointer to AudioStreamBasicDescription? whose member values I need to read.
You use the pointee property on your UnsafePointer to access the memory it points to. So your C example would read as let x = p.pointee.a.

Does Swift have quadratic string concatenation when using var?

In the Swift Language Reference, under String Mutability it says:
You indicate whether a particular String can be modified (or mutated) by assigning it to a variable (in which case it can be modified), or to a constant (in which case it cannot be modified)
It's unclear to me if the "it" that is mutable is the variable or the value.
For example, if I write:
var s = ""
for i in 0...100 {
s += "a"
}
Is it akin to creating an NSMutableString and calling appendString 100 times (i.e. linear cost)?
Or is it akin to creating a series of ever-larger NSString instances and combining them with stringByAppendingString (i.e. quadratic cost)?
Or perhaps it creates some kind of rope structure behind the scenes, so it's immutable and linear in aggregate?
Appending to a collection like this (while String is not itself a collection, you're essentially appending to its characters view with that code) is linear, not quadratic. A string in Swift has an internal buffer whose size is doubled whenever it fills up, which means you will see fewer and fewer reallocations as you repeatedly append. The documentation describes appending in this way as an "amortized" O(1) operation: most of the time appending is O(1), but occasionally it will need to reallocate the string's storage.
Arrays, sets, and dictionaries have the same behavior, although you can also reserve a specific capacity for an array (using reserveCapacity(_:)) if you know you'll be appending many times.
All these collections use "copy-on-write" to guarantee value semantics. Here, x and y share a buffer:
let x = "a"
let y = x
If you mutate x, it gets a new, unique copy of the buffer:
x += "b"
// x == "ab"
// y == "a"
After that, x has its own buffer, so subsequent mutations won't require a copy.
x += "c" // no copy unless buffer is full

Matlab: iterate over multiple structs

I have 5 Matlab structs. I would like to iterate over them. My current solution is the following:
all_structs = [struct1,struct2,struct3,struct4,struct5];
for single_struct = all_structs
% do stuff to each struct here
end
However, each of the structs above has a matrix with a lot of data (including some other properties). Also, whatever I change in the single_struct is not passed back to the original struct.
Question: How do I fix that? Does Matlab copy all that data again when I create the vector all_structs? Or is the data from each of the structs (struct1,...,struct5) passed by reference? Is there a better way to iterate over multiple structs?
Thanks for helping!
struct will not be passed by reference. You will need to loop over the elements in all_structs using an index and then access and modify using that index. If you need something to be treated as reference you will need to define a class for it and make the class inherit from handle. Suggested reading
for i = 1:numel(all_structs)
% do stuff to each struct here
all_structs(i).data = ones(10,5); % your code here
end
I would suggest also reading on arrayfun, though it is useful if you want to do an operation and get results. From your description it sounds like you want to modify the structs.
In case you want to modify content of original structs, without making a copy, you can use a cell array of structs names.
Then iterate the names, and use eval to modify the content.
Using eval is inefficient, so don't make it a habit...
See the following code sample:
%Create sample structs (each struct has a data element).
struct1.data = 1;
struct2.data = 2;
struct3.data = 3;
%Create a cell array containing structs names as strings.
struct_names = {'struct1', 'struct2', 'struct3'};
%Iterate all structs names
%Modify data elements of each struct using eval.
for i = 1:length(struct_names)
sname = struct_names{i}; %Get struct name from cell array.
%Evaluate a string like: 'struct1.data = struct1.data + 1;'
eval([sname, '.data = ', sname, '.data + 1;']);
end

objective-c variable length array global scope

is it possible to declare a variable length array with global scope in objective-c?
I'm making a game with a world class, which initializes the world map as a three dimensional integer array. while it's only a two dimensional side scroller, the third dimension of the list states which kinda of block goes at the coordinate given by the first two dimensions
after the initialization function, a method nextFrame: is scheduled (I'm using cocos2d and the CCDirector schedule method). I was wondering how to pass the int[][][] map array from the initialization function to the nextFrame function
I tried using global (static keyword) declaration, but got an error saying that global arrays cannot be variable length
the actual line of code I'm referring to is:
int map[xmax][ymax][3];
where xmax and ymax are the farthest x and y coordinates in the list of coordinates that defines the stage.
I'd like to somehow pass them to nextFrame:, which is scheduled in
[self schedule:#selector(nextFrame:)];
I realize I can use NSMutableArray, but NSMutableArray is kinda a headache for 3-dimensional lists of integers (I have to use wrapper numbers for everything...). is there any way to do this with integer arrays?
You can't have a statically allocated global array of dynamic dimensions in C (of which Objective C is a clean superset). But you can use a global array of any length or size (up to available memory) at runtime by using a global pointer, malloc, and array indexing arithmetic.
static int *map = NULL;
...
map = malloc (dim1 * dim2 * dim3 * sizeof(int)); // in some initialization method
if (map == NULL) { /* handle error */ } // before first array access
...
myElement = map[ index3 + dim2 * ( index2 + dim1 * index1 ) ]; // some macro might be suitable here
Or you could make Objective C getter and setter methods that checks the array and array bounds on every access, since a method can return plain C data types.
Another option, if you know the max dimensions you want to have available and are willing to use (waste) that amount of memory, is to just statically allocate the max array, and throw an exception if the program tries to set up something larger than your allowed max.
I tried using global (static keyword)
declaration, but got an error saying
that global arrays cannot be variable
length
But global array pointers can point to arrays of variable length.

Objective-C syntax

I've been studying objective-c for a few days now. I keep coming across these two structures:
NSString * somestring
(NSString *) somestring
I understand the first simply sets a pointer to an NSString object, but what does the second construct do, and when should I use it?
What's the deal with the asterix marks?
Sorry if this question doesn't make any sense, I am completely new to this language, and haven't even reached the level of asking proper questions.
Main purpose -- I'm trying to decipher this method:
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger) row forComponent: (NSInteger)component
**Also, the classes I chose don't matter. **
What you want to understand is the method declaration syntax. In Objective-C, a method has a name which looks like this doSomethingWith:andAlso:inMode:. Each colon precedes an argument. When you declare or define a method, you also specify the types of the variables and their names; the type is given in parentheses. You also prepend things with a - for instance methods and a + for static methods, as well as the (parenthesized) return type. Now, you have
- (NSString*) pickerView:(UIPickerView*)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
...
}
When we decipher this, we find that:
-: It's an instance method.
(NSString*): The return type, NSString*.
pickerView:: The first part of the method name.
(UIPickerView*)pickerView: The first argument; its name is pickerView and it has type UIPickerView*.
titleForRow:: The second part of the method name.
(NSInteger)row: The second argument; its name is row and its type is NSInteger.
forComponent:: The third part of the method name.
(NSInteger)component: The third argument; its name is component and its type is NSInteger.
Thus, putting it all together, this defines the instance method pickerView:titleForRow:forComponent:; it returns an NSString*, and the three arguments it takes are of type UIPickerView*, NSInteger, and NSInteger, respectively. This method would be called as [obj pickerView:myPV titleForRow:myRow forComponent:myComponent].
And just for further reference: in isolation, if you have NSString* str, it declares a variable of type NSString*; and if you have (NSString*)obj, it (forcefully) converts that object to have type NSString*. This has no connection to the method declaration syntax.
Edit 1: I also saw that you were asking about the asterisks. In (Objective-)C, this represents a pointer. If you have an int x, say, then when you write int y = x and then y = 3, the original value of x is unchanged. If, however, you have an int* px, then you can write px = &x. (Note that ints, declared as int, are a completely different data type than int pointers declared as int*. Writing int y = &x is garbage, as is int* py = x, and so on.) This & is the "address of" operator; it finds where x is in memory and returns it. Now, if you write int* py = px and then py = &y, this won't change px. But if you write *px, you access the value currently stored in x, and you can change it: *px = 42 sets x to 42. For various reasons, when working with objects, people tend to like to work with references to them instead of their actual values; thus, in Objective-C, you only handle objects through pointers. What this means is that you will never see NSMutableArray x, only NSMutableArray* x; and that if you have NSMutableArray* y = x, then x and y are, roughly speaking, the same, and calling [x addObject:obj] affects y as well. There are more comprehensive tutorials out there—it's worth checking them out if you don't understand pointers—but this should suffice as an overview.
Edit 2: In another comment, you say you're coming from Ruby and Python. In Ruby (and I think Python, but I've used it less), every variable is a reference. This means that the basic use of pointers for object types should be familiar; as long as you never use & or *, they'll function in pretty much the same way. The difference between pointers and references is that you can take references to objects and create pointers to pointers. For instance, many methods end in ...error:(NSDictionary**)error. This effectively provides an extra return value; in the method, if something goes wrong, they can write *error = myErrorInfo. Since function arguments are copied, error = myErrorInfo wouldn't be visible; however, the pointer's referent is still the same, and so it can be assigned to. If you then write code such as:
NSDictionary* errorDict = nil;
[obj unsafeOperation:#"http://stackoverflow.com" error:&errorDict];
You pass in a pointer to errorDict so that the unsafeOperation:error: method can write to errorDict and you can see it.
mebFace - an asterisk represents a pointer. So whenever you see (eg) "NSString *" then it means you're dealing with a pointer to a NSString object. The method you're trying to decipher returns a pointer to a string as the result. It takes three parameters: a pointer to a UIPickerView, followed by a couple of integers. The reason that you don't use an asterisk in conjunction with the integers is because they are simple integers - not objects.
You should probably start off by reading a book on the C programming language. This is what Objective-C is built on top of.
Dave
The first one is variable declaration while second is type-casting. I.e. somestring is not of type NSString* so you type-cast it into being NSString*. I believe that the latter case is mostly (if not always) seen on the right side of assignment statement.
In ObjectiveC this comes from C and is also used in many other strictly-typed languages like Java, C# and so on.
In the updated question, your method signature defines that method returns pointer to NSString - (NSString *). And it accepts 3 parameters:
Pointer to UIPickerView object;
number of row;
number of column;
Confusingly, in Objective-c, both of your examples mean different things in different contexts.
When declaring a variable (and other places, but not everywhere else) the asterisk means 'pointer to', ie…
int foo; // An int variable
int *bar; // A pointer to an int
When it comes to objective-c objects we mostly deal with pointers to them, ie.. you will not see this..
NSString myString;
you will always see this
NSString *myString;
The reason why is quite involved, but is to do with where the memory for the object is allocated (the heap) and what happens when you pass a variable to a function or method. A value passed as an argument to a method is copied. It turns out that copying our string when we pass it to a method is probably not what we intended, so we pass a pointer to the string instead, and that is copied. Imagine a string that contains the complete works of Shakesphere, roughly 5 million bytes. It is inefficient to copy it every time we pass it to a method, but a pointer to it is only 4 bytes, and a pointer gives us just as good access to the data because it, well, points to it. This approach wouldn't get us anything for the int argument tho, as the int and the pointer to the int are going to be the same size (or ballpark, at least).
Your second example is a method or a method declaration. It might help to compare it to function definition in something like javascript:
function pickerViewTitleForRowForComponent( pickerView, row, component ) {
...do something here
return result;
}
Objective-c does things slightly better, sorry, i mean differently. The above would basically look like
- pickerView: pickerView titleForRow: row forComponent: component {
...do something here
return result;
}
The arguments are the same: pickerView, row and component. However, the above isn't a valid method because it is missing type info. ie. We must explicitly say what type each argument is and also the type of the object returned from the method.
- (return type)pickerView:(argument type)pickerView titleForRow:(argument type)row forComponent:(argument type)component {
...do something here
return result;
}
As you can probably see, in your example:
return type > a pointer to an NSString object -- (NSString *)
argument1 type > a pointer to a UIPickerView object -- (UIPickerView *)
argument2 type > an NSInteger -- (NSInteger)
argument3 type > an NSInteger -- (NSInteger)