This question, in the old program that is implemented under UIKit, was done like this.
Condition in which the following actions are performed:
if(theApp().m_Disp.Connecttosrv(self.SelCon)) {
In the condition, the function is accessed
func theApp() -> iSPultApp!
{
return UIApplication.shared as? iSPultApp
}
Where next the class is called from the function
class iSPultApp: UIApplication {
var m_Disp: Chroot = Chroot()
Everything works there, is it possible to redo it somehow for SwiftUI?
The program goes to func theApp (), and then instead of going to the class, returns to the condition and there is an error:
if(theApp().m_Disp.Connecttosrv(self.SelCon)) {
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value.
self.SelCon is not empty, but filled with data. apparently, nil is passed in func theApp()
Thank you in advance for your help 🙏
Related
I have the variable provincias_ws which has the answer of a service, so far everything is fine but I want to know how I make the variable provincias_ws is global since I want to print it in the textFieldDidBeginEditing method
class ViewCtrl: UIViewController, ValidationDelegate, UITextFieldDelegate {
#IBOutlet weak var txt_ciudadU: SearchTextField!
override func viewDidLoad() {
super.viewDidLoad()
opciones_autocompletado()
txt_ciudadU.delegate = self
}
func opciones_autocompletado(){
txt_provinciaU.inlineMode = true
txt_ciudadU.inlineMode = true
Services.objServices.ServProv().then{
data -> Void in
let res = JSON(data)
let status = res["status"].boolValue
if(status){
let provincias_ws = res["data"]["provincias"] //How to make this variable global
}else{
let error = res["error"]["error_data"].stringValue
print(error)
}
SVProgressHUD.dismiss()
UIApplication.shared.endIgnoringInteractionEvents()
}.catch{
error -> Void in
SVProgressHUD.dismiss()
UIApplication.shared.endIgnoringInteractionEvents()
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print(provincias_ws)
}
}
Thank you in advance
One can create a "global" variable (meaning it can be access from anywhere in the project) by defining it outside of the class block.
However, it looks like what you want is a class instance variable.
Your text field txt_ciudadU is already an example of an instance variable or property of the class ViewCtrl.
This would be the same, just without #IBOutlet weak.
So would probably be (assuming it's a String):
var provincias_ws: String?
Note the ? declares it as an optional value because it will not be set until it gets set inside your block. You could also initialize it to some default or empty value (e.g. var provincias_ws = "") or you could use ! to indicate you won't be trying to unwrap it when it's nil, although it's better not to rely on that because it is error-prone. What you choose to do depends on your needs.
And you would put that at the same hierarchical level as your text field variable (i.e. right above or below it, although it could go anywhere really, as long as it's not inside a function or another block).
And you would get rid of the current let next to provincias_ws and prepend it with self. i.e.:
self.provincias_ws = res["data"]["provincias"]
The self. is necessary because it's inside a block and the compiler needs that for context.
I try to instanciate a new class from a string class name, like we can easy do in Java. I have finally wrote this function:
func stringClassFromString(_ className: String) -> AnyClass! {
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
let cls: AnyClass = NSClassFromString("\(namespace).\(className)")!;
return cls;
}
Thanks to some googling, but as soon as I tried this solution thanks to a unit test :
func test() {
let myclass = stringClassFromString("NSDate") as! NSDate.Type
let instance = myclass.init()
print(instance)
}
I have an exception (Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)) as soon as my test use the line : let namespace... I tried to see the content of the infoDictionary, he's empty. So my question is simple, is it because of the unit tests context that my dictionary is empty ? Is there any method or library (like robolectric for android) to simulate an infoDicionary for testing purpose.
I succeed to find my error, instead of using the main Bundle, I use the constructor of the Bundle class to build a Bundle which will correspond to the current context :
let namespace = Bundle(for: type(of: self)).infoDictionary!["CFBundleExecutable"] as! String;
And tadda, it's working !
I was just implementing object class to access methods and protocols. Following
import UIKit
import Foundation
import Alamofire
import SVProgressHUD
protocol ParseAPIProtocol:class {
func APIresponse(responseDict: NSDictionary)
}
class ParseAPI :NSObject{
// weak var mydelegate : MyProtocols?
weak var delegateAPI:ParseAPIProtocol?
class func ParseUrl(postparameters: [String: AnyObject]!, url:String, current:UIViewController) {
print(postparameters)
print(url)
SVProgressHUD.show()
Alamofire.request(url, method: .post, parameters: postparameters, encoding: URLEncoding.default, headers: nil).responseJSON
{
(response:DataResponse<Any>) in
switch(response.result)
{
case .success(_):
if response.result.value != nil
{
let jsonResult = (try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSDictionary
print(jsonResult)
}
break
case .failure(_):
SVProgressHUD.dismiss()
print(response.result.error as Any)
break
}
}
}
Whenever I got the jsonResult, I just want to call fun APIresponse to parse result dictionary to viewcontroller class.
I declared the method on viewcontroller and its delegate.
But when I tried to call protocol method, it doesn't give me access to the method. May be I am doing something wrong. Please look into my method.
Thanks!
The way I see it there are several issues, although it's hard to tell because you don't show the relevant code in your view controller
(how you set up the delegate, how you call your parse API).
First, you never call your delegate with the result. With your current setup this isn't even possible: you define ParseAPI to have a
delegate (instance) member but define ParseUrl as a class func. I guess this is what you meant when saying "it doesn't give me access to the method".
Try defining it as a member function and then, in the success case call the delegate:
self.delegateAPI?.APIresponse(responseDict: jsonResult)
In your view controller, instantiate a ParseAPI instance and keep it alive (for example by storing it in a strong instance member), set its delegate,
and call ParseUrl(...). This call will return pretty much immediately and later, when the request and response is handled, your delegate method will
be called.
class ViewController: UIViewController, ParseAPIProtocol
{
var parser: ParseAPI?
func somewhere()
{
self.parser = ParseAPI()
self.parser!.delegateAPI = self
self.parser!.ParseUrl(postparameters: [:], url: "...", current: self)
}
func APIresponse(responseDict: NSDictionary)
{
print("VC got response:", responseDict)
}
}
Second, the current parameter is never used, you can remove it. Either that or you can remove the whole delegate thing and replace the current parameter
with a callback, something like this:
func ParseUrl(postparameters: [String: AnyObject]!, url:String, finished: #escaping (_ response: NSDictionary?) -> Void)
{
...
// success case:
finished(jsonResult)
// failure case:
finished(nil)
}
and call it like this:
self.parser!.ParseUrl(postparameters: [:], url: "...", finished: { (response: NSDictionary?) in
// handle response
})
You can also define your callback to have an error parameter so you can act accordingly when one occurs.
And finally, while I don't know SVProgressHUD, you probably wanna call SVProgressHUD.dismiss() in the success case, too.
Why the following Swift3 code results in error value of type (NSObject) -> () -> MyView has no member getSomeButton in Xcode 8?
lazy var someButton = {
return self.getSomeButton // ERROR
}()
private func getSomeButton() -> UIButton {
return UIButton()
}
Actually, the error message is totally misleading and should be something like can't infer closure return type. Specifying variable type solves the problem. Hope this help someone.
lazy var someButton: UIButton = {
return self.getSomeButton // OK
}()
Moving from Ember 1.5.1 to 1.6.0, I've run into an issue with __nextSuper (which has been changing in the last few versions). You can see the offending code here.
And here's the relevant Ember code:
function wrap(func, superFunc) {
function superWrapper() {
var ret, sup = this.__nextSuper; // THIS LINE
this.__nextSuper = superFunc;
ret = apply(this, func, arguments);
this.__nextSuper = sup;
return ret;
}
superWrapper.wrappedFunction = func;
superWrapper.wrappedFunction.__ember_arity__ = func.length;
superWrapper.__ember_observes__ = func.__ember_observes__;
superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
superWrapper.__ember_listens__ = func.__ember_listens__;
return superWrapper;
};
What happens is, at some point, the superWrapper function gets called with window as the this value. So when I reach the line marked above, this.__nextSuper comes out to be undefined. But rather than sup simply being undefined, it throws the following error:
TypeError: Cannot read property '__nextSuper' of undefined
The thing is, when I pause in the debugger, this is defined (it's the window object). And when I paste var ret, sup = this.__nextSuper; into the console, it works as expected. And, if I go up the stack frame and check the this value, it's exactly what I expect. So I have no idea why superWrapper suddenly has a bad this value.
Finally, the most interesting part, this only happens in the browser; it works fine in PhantomJS. The changelog didn't seem to list anything to do with __nextSuper as a breaking bugfix, but obviously something has changed. How can I solve this issue?
Ember 1.6 looks to have a requirement on super method being called from the scope of the object hosting the super method (probably a bug, but I'm not positive). In your case you'd want to keep track of the scope, then call the super method using it:
(scope is the object that houses isEqual)
var scope = meta.isEqual ? meta : this.get('store').attributeTypeFor(meta.type);
if (scope.isEqual(server, value)) { ...
instead of (scope is window and explodes in 1.6+)
var isEqual = meta.isEqual || this.get('store').attributeTypeFor(meta.type).isEqual;
if (isEqual(server, value)) { ...
Here's a super simple example showing the problem (1.6+): http://emberjs.jsbin.com/yelesahe/1/edit
And working in 1.5.1: http://emberjs.jsbin.com/zedevudo/1/edit
Issue: https://github.com/emberjs/ember.js/issues/5198