xcodeswiftuiconstraintspreviewxcode14

Xcode preview error - '@objc' can only be applied to an extension of a class


I am using Xcode 14.2 with both a SwiftUI file as well as an Objective-C file. It uses NotificationCenter to change my text and labels that I have within my SwiftUI. Part of my text (fourLinesText) is being cut off when it runs on an iPhone 8 but am unable to see it because the preview will not display anything and gives an error stating:

'@objc' can only be applied to an extension of a class

I have tried changing the class to @Objc extension class but am given the error: Expected type name in extension declaration

How can I restore the preview so I can see my app run in it?

enter image description here

enter image description here

enter image description here

Swift code:

import Foundation
import SwiftUI

@objc public protocol CMWUploadViewV2Delegate: NSObjectProtocol {
    @objc func uploadOKButtonPushed()
    @objc func uploadAbortButtonPushed()
    @objc func uploadErrorLogButtonPushed()
    @objc func uploadRetryButtonPushed()
}

@objc class CMWSTUploadViewV2Controller: UIViewController {
   
    @IBOutlet var ProgressBarView: UIView!
    
    // embed SwiftUI into the UIKit storyboard view controller
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let childView = UIHostingController(rootView: ContentView())
        addChild(childView)
        childView.view.frame = ProgressBarView.bounds
        ProgressBarView.addSubview(childView.view)
        childView.didMove(toParent: self)
        
    }
    
    @objc weak var delegate: CMWUploadViewV2Delegate?
    
    //creating function for dictionary to store changes and create notification
    //This takes a value between 0 and 1 
    @objc func UpdateUploadProgress(progressValue: Float)
    {
        //First, we need to normalize the value which is between 0 and 0.99 to 0 and 0.8999996
        let normalizedValue = progressValue * 0.8999996
        let valueUpdate:[String: Float] = ["ProgressValue": normalizedValue]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateUploadProgress"), object: nil, userInfo:valueUpdate)
    }
    
    @objc func UpdateInitialText(InitialTextParameter: String)
    {
        let textUpdate:[String: String] = ["InitialTextParameter": InitialTextParameter]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateInitialText"), object: nil, userInfo:textUpdate)
    }
    
    @objc func UpdateAddressText(AddressTextParameter: String)
    {
        let textUpdate:[String: String] = ["AddressTextParameter": AddressTextParameter]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateAddressText"), object: nil, userInfo:textUpdate)
    }
    
    @objc func UpdateOrangeText(OrangeTextParameter: String)
    {
        let textUpdate:[String: String] = ["OrangeTextParameter": OrangeTextParameter]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateOrangeText"), object: nil, userInfo:textUpdate)
    }
    
    @objc func UpdateGreySubText(GreySubTextParameter: String)
    {
        let textUpdate:[String: String] = ["GreySubTextParameter": GreySubTextParameter]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateGreySubText"), object: nil, userInfo:textUpdate)
    }
    
  
    @objc func UpdateControllerTypeText(ControllerTypeTextParameter: String)
    {
        let textUpdate:[String: String] = ["ControllerTypeTextParameter": ControllerTypeTextParameter]
        NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateControllerTypeText"), object: nil, userInfo:textUpdate)
    }
    
     @objc func UpdateConnectionTypeText(ConnectionTypeTextParameter: String)
     {
         let textUpdate:[String: String] = ["ConnectionTypeTextParameter": ConnectionTypeTextParameter]
         NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateConnectionTypeText"), object: nil, userInfo:textUpdate)
     }
    
     @objc func UpdateStatusText(StatusTextParameter: String)
     {
         let textUpdate:[String: String] = ["StatusTextParameter": StatusTextParameter]
         NotificationCenter.default.post(name:NSNotification.Name("COM.CMW.UpdateStatusText"), object: nil, userInfo:textUpdate)
     }
    
    struct ContentView: View {
        //creating vars
        @State var progressValue: Float = 0.3
        //let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
        @State private var degress: Double = -110
        //@State var GreySubText = ""
        let label = UILabel()
        @State var buttonText1 = ""
        @State var buttonText2 = ""
        @State var controllerTypeText = ""
        @State var connectionTypeText = "CAN"
        @State var statusText = "Status text here"
        @State var fourLinesText = "More status text here. Controller responding. This text will be 4 lines in length. 1234567891011121314151617181920. Controller responding. This text will be 4 lines in length. 1234567891011121314151617181920. Controller responding. This text will be 4 lines in length. 1234567891011121314151617181920"
        @State var initialText = "Resetting to upload mode."
        
        //setting up notification center to listen to addresses
        let publisher = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateUploadProgress"))
        let publisher8 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateInitialText"))
        //let publisher6 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateAddressText"))
        //let publisher7 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateOrangeText"))
        //let publisher5 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateGreySubText"))
        let publisher2 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateControllerTypeText"))
        let publisher3 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateConnectionTypeText"))
        let publisher4 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateStatusText"))
        
        //display
        var body: some View {
            VStack {
                Spacer()
                    .frame(height: 70)
                
                if #available(iOS 16.0, *) {
                    Label(initialText, systemImage: "clock")
                        .font(.title)
                        .foregroundColor(Color(hex: "000"))
                        .fontWeight(.bold)
                        .onReceive(publisher8) { obj in
                            let initialTextVal = obj.userInfo?["InitialTextParameter"] as? String
                            initialText = initialTextVal!
                        }

                } else {
                    // Fallback on earlier versions
                    Label(initialText, systemImage: "clock")
                        .font(.title)
                        .foregroundColor(Color(hex: "000"))
                        .onReceive(publisher8) { obj in
                            let initialTextVal = obj.userInfo?["InitialTextParameter"] as? String
                            initialText = initialTextVal!
                        }
                }
                    
                    
                ZStack{
                    //background rectangle
                    RoundedRectangle(cornerRadius: 25)
                        .fill(Color(hex: "494949"))
                        .frame(width: 300, height: 300)
                    
                    ProgressBar(progress: self.$progressValue)
                        .frame(width: 250.0, height: 250.0)
                        .padding(40.0)
                        .onReceive(publisher) { obj in
                            let progVal = obj.userInfo?["ProgressValue"] as? Float
                            progressValue = progVal!
                            }
                    
                    ProgressBarTriangle(progress: self.$progressValue).frame(width: 280.0, height: 290.0).rotationEffect(.degrees(degress), anchor: .bottom)
                        .offset(x: 0, y: -150)
                }
                
                //***Controller, Connection, and Status labels/text
                Spacer()
                    .frame(height: 20)
                VStack(alignment :.leading, spacing: 30) {
                    HStack {
                        if #available(iOS 16.0, *) {
                            Label("Controller type:", image: "ControllerIcon")
                                .foregroundColor(Color(hex: "000"))
                                .fontWeight(.bold)
                        } else {
                            // Fallback on earlier versions
                            Label("Controller type:", image: "ControllerIcon")
                                .foregroundColor(Color(hex: "000"))
                        }
                        Text(controllerTypeText)
                        //app crashes when following code active:
                        //onReceive(publisher2) { obj in
                            //let controllerTextVal = //obj.userInfo?["ControllerTypeTextParameter"] as? String
                            //controllerTypeText = controllerTextVal!
                        //}
                    }
                    
                    HStack {
                        if #available(iOS 16.0, *) {
                            Label("Connection type:", image: "CANIconSmall")
                                .foregroundColor(Color(hex: "000"))
                                .fontWeight(.bold)
                        } else {
                            // Fallback on earlier versions
                            Label("Connection type:", image: "CANIconSmall")
                                .foregroundColor(Color(hex: "000"))
                        }
                        Text(connectionTypeText)
                            .onReceive(publisher3) { obj in
                                let connectionTextVal = obj.userInfo?["ConnectionTypeTextParameter"] as? String
                                connectionTypeText = connectionTextVal!
                            }
                    }
                    
                    HStack {
                        if #available(iOS 16.0, *) {
                            Label("Status:", image: "StatusIcon")
                                .foregroundColor(Color(hex: "000"))
                                .fontWeight(.bold)
                        } else {
                            // Fallback on earlier versions
                            Label("Status:", image: "StatusIcon")
                                .foregroundColor(Color(hex: "000"))
                        }
                        
                    }
                    
                    //four lines of status text
                    Text(fourLinesText)
                        .foregroundColor(Color(hex: "000"))
                        .lineLimit(4)
                        .multilineTextAlignment(.leading)
                        .onReceive(publisher4) { obj in
                            let statusTextVal = obj.userInfo?["StatusTextParameter"] as? String
                            fourLinesText = statusTextVal!
                        }
                    
                    Spacer()
                }
                .padding(.leading, 20)
                .padding(.trailing, 20)
            }
        }
        
        public struct ProgressBar: View {
            //creating vars
            @Binding var progress: Float
            @State var addressText = "0x1c000"
            @State var orangeText = "Orange Text"
            @State var GreySubText = ""
            
            let publisher7 = NotificationCenter.default.publisher(for:
                NSNotification.Name("COM.CMW.UpdateOrangeText"))
            let publisher6 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateAddressText"))
            let publisher5 = NotificationCenter.default.publisher(for: NSNotification.Name("COM.CMW.UpdateGreySubText"))
            
            public func UpdateProgressValue(progressValue: Float)
            {
                progress = progressValue
            }
            
            var body: some View {
                
                VStack (alignment :.center, spacing: 30){
                    HStack {
                        Label("Address:", systemImage: "target")
                            .foregroundColor(Color(hex: "8f8f8f"))
                            .padding(.top, 15)
                        Text(addressText)
                            .foregroundColor(Color(hex: "8f8f8f"))
                            .padding(.top, 15)
                            .onReceive(publisher6) { obj in
                                let addressTextVal = obj.userInfo?["AddressTextParameter"] as? String
                                addressText = addressTextVal!
                            }
                    }
                    ZStack {
                        
                        Circle()
                            .trim(from: 0.35, to: 0.85)
                            .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                            .opacity(0.3)
                            .foregroundColor(Color.gray)
                            .rotationEffect(.degrees(54.5))
                        
                        Circle()
                            .trim(from: 0.35, to: CGFloat(self.progress))
                            .stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .round))
                            .fill(AngularGradient(gradient: Gradient(stops: [
                                .init(color: Color.init(hex: "daff00"), location: 0.39000002),
                                .init(color: Color.init(hex: "00ff04"), location: 0.5999999),
                                .init(color: Color.init(hex: "32E1A0"), location: 0.8099997)]), center: .center))
                            .rotationEffect(.degrees(54.5))
                        
                        VStack(alignment :.center, spacing: 10) {
                            
                            Text("824").font(Font.system(size: 44)).bold().foregroundColor(Color.init(hex: "ffffff"))
                            
                            if #available(iOS 16.0, *) {
                                Label(orangeText, systemImage: "clock")
                                    .foregroundColor(Color(hex: "FF6600"))
                                    .fontWeight(.bold)
                                .onReceive(publisher7) { obj in
                                    let statusTextVal = obj.userInfo?["OrangeTextParameter"] as? String
                                    orangeText = statusTextVal!
                                }
                            } else {
                                // Fallback on earlier versions
                                Label(orangeText, systemImage: "clock")
                                    .foregroundColor(Color(hex: "FF6600"))
                                .onReceive(publisher7) { obj in
                                    let statusTextVal = obj.userInfo?["OrangeTextParameter"] as? String
                                    orangeText = statusTextVal!
                                }
                            }
                            
                            Text(GreySubText)
                                .foregroundColor(Color(hex: "8f8f8f"))
                                .multilineTextAlignment(.center)
                                .onReceive(publisher5) { obj in
                                    let GreySubTextVal = obj.userInfo?["GreySubTextParameter"] as? String
                                    GreySubText = GreySubTextVal!
                                }
                            
                        }
                    }
                    
                }
                
            }
            
        }
        
        struct ProgressBarTriangle: View {
            @Binding var progress: Float
            
            
            var body: some View {
                ZStack {
                    Image("triangle").resizable().frame(width: 10, height: 10, alignment: .center)
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
}
    extension Color {
        init(hex: String) {
            let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
            var int: UInt64 = 0
            Scanner(string: hex).scanHexInt64(&int)
            let a, r, g, b: UInt64
            switch hex.count {
            case 3: // RGB (12-bit)
                (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
            case 6: // RGB (24-bit)
                (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
            case 8: // ARGB (32-bit)
                (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
            default:
                (a, r, g, b) = (1, 1, 1, 0)
            }
            
            self.init(
                .sRGB,
                red: Double(r) / 255,
                green: Double(g) / 255,
                blue:  Double(b) / 255,
                opacity: Double(a) / 255
            )
        }
        
    }

Objective C code:

-(void)summerTestUploadViewController
{
    CMWSTUploadViewV2Controller* myView = [[UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:@"ID_CMW_UPLOADVIEWV2_VIEW"];
 //   myView.delegate = self;
    [self presentViewController:myView animated:YES completion:^{
        [myView UpdateUploadProgressWithProgressValue:0.7];
        [myView UpdateInitialTextWithInitialTextParameter:@"Initial text here"];
        [myView UpdateAddressTextWithAddressTextParameter:@"Address text here"];
        [myView UpdateOrangeTextWithOrangeTextParameter:@"Orange text here"];
        [myView UpdateGreySubTextWithGreySubTextParameter:@"Grey sub text here"];
        [myView UpdateControllerTypeTextWithControllerTypeTextParameter:@"Controller text here"];
        [myView UpdateConnectionTypeTextWithConnectionTypeTextParameter:@"Connection text here"];
        [myView UpdateStatusTextWithStatusTextParameter:@"Status text here. 4 lines of text will be allowed in this area.  4 lines of text will be allowed in this area.  4 lines of text will be allowed in this area.  4 lines of text will be allowed in this area.  4 lines of text will be allowed in this area."];
        
    }];
}

Solution

  • When I remove the attribute @objc for the class CMWSTUploadViewV2Controller it allows me to view it in the preview pane to see how my constraints behave.