Initialization error [duplicate] - variables

This question already has answers here:
How to initialize properties that depend on each other
(4 answers)
Closed 5 years ago.
let screenSize = UIScreen.main.bounds.height
let IS_IPHONE_4_OR_LESS = screenSize < 568.0
"Cannot use instance member within property initializer before self is available" this is the error am getting when executing the code.

Try this :
you need to create constant with static
static let screenSize = UIScreen.main.bounds.height
static let IS_IPHONE_4_OR_LESS = screenSize < 568.0

You can use this way to check which iPhone you are using :
struct ScreenSize{
static let width = UIScreen.main.bounds.size.width
static let height = UIScreen.main.bounds.size.height
static let maxLength = max(ScreenSize.width, ScreenSize.height)
static let minLength = min(ScreenSize.width, ScreenSize.height)
static let scale = UIScreen.main.scale
static let ratio1619 = (0.5625 * ScreenSize.width)
}
struct DeviceType{
static let isIphone4orLess = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength < 568.0
static let isIPhone5 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 568.0
static let isIPhone6 = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 667.0
static let isIPhone6p = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.maxLength == 736.0
}
then use this as :
if DeviceType.isIPhone5 {
//Do iPhone 5 Stuff
}

Constants refer to fixed values that a program may not alter during its execution. IS_IPHONE_4_OR_LESS is a constant hence it need the fix value at the time of initialisation of a class hence the error. In your case its computing the value based on the screen height so you can declare it as a computed property like below
class Constants: NSObject {
let screenSize = UIScreen.main.bounds.size.height
var IS_IPHONE_4_OR_LESS: Bool {
return screenSize < 568
}
}

You can not use any instance variable while initialising the property instead of that you should use below code.
class constant : NSObject {
let screenSize = UIScreen.main.bounds.height
var IS_IPHONE_4_OR_LESS = false
override init() {
IS_IPHONE_4_OR_LESS = screenSize < 568.0
}
}

Swift uses two-phase initialization for it's variables.
Class initialization in Swift is a two-phase process. In the first
phase, each stored property is assigned an initial value by the class
that introduced it. Once the initial state for every stored property
has been determined, the second phase begins, and each class is given
the opportunity to customize its stored properties further before the
new instance is considered ready for use.
So you cannot access instance variables before you intitialize them. You can use a getter for this variable Try using this
let screenSize = UIScreen.main.bounds.height
var IS_IPHONE_4_OR_LESS :Bool{
get{
return screenSize < 568.0
}
}

Related

Objective-C enum value into Swift enum

Before you vote on this question I would like to how dumb what I am trying to do is. Maybe I still don't understand properly enums.
So, I am working on a project that uses an Obj-C framework. This framework contains enums:
typedef enum : NSInteger
{
kImageSizeUnknown = 0,
kImageSize75,
kImageSize110,
kImageSize170,
kImageSize220,
kImageSize300,
kImageSize450,
kImageSize720,
kImageSize1080,
/* Size aliases */
kImageSizeThumbnail = kImageSize75,
kImageSizeSmall = kImageSize170,
kImageSizeMedium = kImageSize450,
kImageSizeLarge = kImageSize720,
kImageSizeXLarge = kImageSize1080
} GnImageSize;
I want somehow be able to declare a Swift enum that returns values of the Obj-C enum (That might be the silly part).
That is how I have at the moment.
enum GNImageSize:Int, CaseIterable{
case thumbnail
case sizeSmall
func toGnImageSize() -> GnImageSize {
switch self {
case .thumbnail:
return kImageSizeThumbnail
case .sizeSmall:
return kImageSizeSmall
}
}
static func toGnImageSize(sizeType:GNImageSize) -> GnImageSize {
switch sizeType {
case .thumbnail:
return kImageSizeThumbnail
case .sizeSmall:
return kImageSizeSmall
}
}
}
However when I do:
enum GNImageSize:Int, CaseIterable{
case thumbnail = GnImageSize.kImageSizeThumbnail
case sizeSmall = GnImageSize.kImageSizeSmall
}
I get the following error message:
Raw value for enum case must be a literal
Thank you.
EDIT
Function that comunicates with Obj-c functions
func getArtworkURL(forImageType imageType:GNImageSize, shouldFindAlternatives:Bool, highQualityFirst:Bool)->URL?{
if let asset = coverArt()?.asset(GnImageSize(rawValue: imageType.rawValue)), let assetURL = asset.urlHttp(){
return URL(string:assetURL)
}
else{
if shouldFindAlternatives{
if highQualityFirst{
for size in GNImageSize.allCases.reversed(){
if let asset = coverArt()?.asset(GnImageSize(rawValue: size.rawValue)), let assetURL = asset.urlHttp(){
return URL(string:assetURL)
}
}
}
else{
for size in GNImageSize.allCases{
if let asset = coverArt()?.asset(GnImageSize(rawValue: size.rawValue)), let assetURL = asset.urlHttp(){
return URL(string:assetURL)
}
}
}
}
}
return nil
}
Where
-(nullable GnAsset*) asset: (GnImageSize)imageSize;
The five size aliases have the (raw) values 1, 3, 6, 7, 8 so declare a Swift enum
enum GNImageSize : Int {
case thumbnail = 1
case small = 3
case medium = 6
case large = 7
case xLarge = 8
}
To use the Int value in Swift use for example
GNImageSize.thumbnail.rawValue
Alternatively create a custom enum with static properties to map the types
enum GNImageSize {
static let thumbnail = GnImageSize(0)
static let small = GnImageSize(3)
static let medium = GnImageSize(6)
static let large = GnImageSize(7)
static let xLarge = GnImageSize(8)
}
I don't understand that in 2018 ObjC frameworks still use the Stone-age syntax typedef enum : NSInteger { ... } Foo; rather than Swift compliant syntax typedef NS_ENUM (NSInteger, Foo) { ... }; The latter syntax exists for 6 years (iOS 6, macOS 10.8).
That raw-value style enum grammar error.
raw-value-assignment → = raw-value-literal
raw-value-literal → numeric-literal | static-string-literal | boolean-literal
So, only numeric(numbers like -7, 0x10, 0b010), static string(characters in quotes, like "foo") and boolean(true or false) literals are allowed there.
Anything else won't work.

add a object to a array in my class

I want to add an object (from a different class) to an array in my class.
When I try to do that I get this
error: 0xC0000005: Access violation writing location
0x0000000000000000
I create the object (to be added) in the main function and I use the push method in the main function to add this object to my Parking_Lot class.
My code:
void Parking_Lot::push(Cars const &car)
{
time_t t = time(NULL);
struct tm Today = *localtime(&t);
if (is_full())
{
printf("Parking lot is full!!\n");
return;
}
if (Today.tm_hour < OpeningT.tm_hour && Today.tm_hour > ClosingT.tm_hour)
{
printf("Parking lot is now closed!!\n");
printf("Opening time: from %02d:%02d to %02d:%02d\n", OpeningT.tm_hour, OpeningT.tm_min, ClosingT.tm_hour, ClosingT.tm_min);
}
else if (Today.tm_hour == OpeningT.tm_hour || Today.tm_hour == ClosingT.tm_hour)
{
if(Today.tm_min > OpeningT.tm_min || Today.tm_min < ClosingT.tm_min) Lot[front++] = car;
else
{
printf("Parking lot is now closed!!\n");
printf("Opening time: from %02d:%02d to %02d:%02d\n", OpeningT.tm_hour, OpeningT.tm_min, ClosingT.tm_hour, ClosingT.tm_min);
}
}
else if(Today.tm_hour > OpeningT.tm_hour && Today.tm_hour < ClosingT.tm_hour) Lot[front++] = car;
}
where the car is the object I want to add and the Lot is the array in my class that I want to add the object to.
The constructor of my class:
Parking_Lot::Parking_Lot(int s)
{
Cars* Lot = new Cars[s+1];
size = s;
front = 0;
}
What am i doing wrong here and how can I fix it?
The problem is in your constructor:
Parking_Lot::Parking_Lot(int s)
{
Cars* Lot = new Cars[s+1];
size = s;
front = 0;
}
You define a new and separate variable Lot inside the constructor. It will not be related to any possible member variable you might have with the same name.
You need to initialize the member variable instead:
Parking_Lot::Parking_Lot(int s)
{
Lot = new Cars[s+1];
size = s;
front = 0;
}

How to convert this Swift syntax into Objective C?

I'm converting a swift project to objective c, but i get some trouble because i don't know how to convert follow code. Please help me. Thanks!
public enum UPCarouselFlowLayoutSpacingMode {
case fixed(spacing: CGFloat)
case overlap(visibleOffset: CGFloat)
}
and
fileprivate var currentPage: Int = 0 {
didSet {
let character = self.items[self.currentPage]
self.infoLabel.text = character.name.uppercased()
self.detailLabel.text = character.movie.uppercased()
}
}
The first (an enum with associated values) has no direct equivalent in Objective-C. For your particular example, you could use something like this:
typedef NS_ENUM(NSInteger, UPCarouselFlowLayoutSpacingMode) {
UPCarouselFlowLayoutSpacingModeFixed,
UPCarouselFlowLayoutSpacingModeOverlap
};
typedef struct {
UPCarouselFlowLayoutSpacingMode mode;
CGFloat amount;
} UPCarouselFlowLayoutSpacing;
You would just pass around values of type UPCarouselFlowLayoutSpacing. You could create helper functions to make these easier to create, e.g.
UPCarouselFlowLayoutSpacing UPCarouselFlowLayoutSpacingMakeFixed(CGFloat spacing) {
UPCarouselFlowLayoutSpacing value;
value.mode = UPCarouselFlowLayoutSpacingModeFixed;
value.amount = spacing;
return value;
}
UPCarouselFlowLayoutSpacing UPCarouselFlowLayoutSpacingMakeOverlap(CGFloat visibleOffset) {
UPCarouselFlowLayoutSpacing value;
value.mode = UPCarouselFlowLayoutSpacingModeOverlap;
value.amount = visibleOffset;
return value;
}
For the second, you can override the setter method of your Objective-C class's currentPage property:
- (void)setCurrentPage:(NSInteger)page {
_page = page;
MovieCharacter *character = self.items[page];
self.infoLabel.text = character.name.localizedUppercaseString;
self.detailLabel.text = character.movie.localizedUppercaseString;
}

Objective C/Swift conversion: How to do this in swift?

I'm trying to convert this example here:
https://github.com/NilStack/NKWatchChart
to swift2-code. I'm having problems with exactly this part:
data01.getData = ^(NSUInteger index) {
CGFloat yValue = [data01Array[index] floatValue];
return [NKLineChartDataItem dataItemWithY:yValue];
};
getData is defined as follows:
public class NKLineChartData : NSObject {
public var color: UIColor!
public var alpha: CGFloat
public var itemCount: UInt
public var getData: LCLineChartDataGetter!
The LCLineChartDataGetter is a type alias:
public typealias LCLineChartDataGetter = (UInt) -> NKLineChartDataItem!
I'm pretty new to objective-c and swift, so maybe someone can point me to how the assignment can be done using swift!
I found the solution myself. The equivalent in Swift is:
data01.getData = {(index : UInt) -> NKLineChartDataItem in
let yValue : CGFloat = CGFloat(data01Array[Int(index)] as! NSNumber)
return NKLineChartDataItem.init(y: yValue)
}
Maybe someone has a better/shorter solution but the above seems to work ;)
The thing being assigned to getData in Obj-C is a block that takes an integer parameter and returns a NKLineChartDataItem. (Check something like http://goshdarnblocksyntax.com if you need help remembering these.)
In Swift, the formal syntax for the corresponding closure looks like this:
data01.getData = { (index: UInt) -> NKLineChartDataItem! in
// body
}
But you can also use type inference to shorten it:
data01.getData = { index in
// body
}
Looking at more of the example from the NKWatchChart readme you linked to:
NSArray * data01Array = #[#60.1, #160.1, #126.4, #0.0, #186.2, #127.2, #176.2];
NKLineChartData *data01 = [NKLineChartData new];
data01.color = NKGreen;
data01.alpha = 0.9f;
data01.itemCount = data01Array.count;
data01.inflexionPointStyle = NKLineChartPointStyleTriangle;
data01.getData = ^(NSUInteger index) {
CGFloat yValue = [data01Array[index] floatValue];
return [NKLineChartDataItem dataItemWithY:yValue];
};
You can probably shorten this even more through native Swift types:
let data01Array: [CGFloat] = [60.1, 160.1, 126.4, 0.0, 186.2, 127.2, 176.2]
let data01 = NKLineChartData()
data01.color = NKGreen
data01.alpha = 0.9
data01.itemCount = data01Array.count
data01.inflexionPointStyle = .Triangle;
data01.getData = { NKLineChartDataItem(y: data01Array[$0]) }
You don't need to convert swift to objective-c to make it run in your project. Just drag the swift into your project and Xcode will automatically generate a bridging header for you

Function and delegate literals in D

Reading TDPL about function and delegate literals (5.6.1)
auto f = (int i) {};
assert(is(f == function));
I've got an assertion failure. Is this assertion correct?
I tried the following:
int z = 5;
auto f = (int i) { return i < 5; };
auto d = (int i) { return i < z; };
assert(is(typeof(f) == typeof(d)));
Assertion is valid there. Actually f is a delegate, not a function even if it doesn't need a frame pointer to access local variables. Is this a bug?
Also, I do not understand how assert(is(f == function)); should work.
I tried assert(is(f == delegate)); but it was failed also. What's wrong?
I use DMD32 D Compiler v2.053
UPDATE
auto f = (int i) {};
assert(is(typeof(f) == delegate))
Works correct, although there is no reason to be a delegate
But
auto f = function (int i) {};
assert(is(typeof(f) == void function(int))); // correct
assert(is(typeof(f) == function)); // failed!!!!!
Miracle. It seems D2 is not ready for production use yet.
"f" is a variable. The is expression compares types. This should work:
assert(is(typeof(f) == delegate));
If you want to create a function instead of a delegate, you can use the function literal syntax:
auto f = function (int i) { ... };
assert(is(typeof(f) == function)); // should be true
If the function literal syntax is not used, the literal is assumed to be delegate (Expressions, look under "Function Literals". This makes sense because D should not change the type based on the whether the body of the literal needs the stack frame (this would be super screwy). EDIT: TDPL does actually specify that the compiler will infer a function instead of a delegate if it can, regardless of the "function" keyword. This seems like a poor idea to me, so this might be something that has been dropped.
As to why the is(f == function) doesn't work, this looks like a regression.
You might find isFunctionPointer and isDelegate helpful.
Update:
See this, taken from traits.d:
template isSomeFunction(/+###BUG4217###+/T...)
if (/+###BUG4333###+/staticLength!(T) == 1)
{
enum bool isSomeFunction = isSomeFunction_bug4333!(T).isSomeFunction;
}
private template isSomeFunction_bug4333(T...)
{
/+###BUG4333###+/enum dummy__ = T.length;
static if (is(typeof(& T[0]) U : U*) && is(U == function))
// T is a function symbol.
enum bool isSomeFunction = true;
else static if (is(T[0] W) || is(typeof(T[0]) W))
// T is an expression or a type. Take the type of it and examine.
static if (is(W F : F*) && is(F == function))
enum bool isSomeFunction = true; // function pointer
else enum bool isSomeFunction = is(W == function) || is(W == delegate);
else enum bool isSomeFunction = false;
}
I think it might explain some things.
In other words:
void main()
{
static if (is(typeof(&main) T : T*)) static assert( is(T == function));
static if (is(typeof(&main) U)) static assert(!is(U == function));
}