【问题标题】:App crash when reload button is pressed按下重新加载按钮时应用程序崩溃
【发布时间】:2015-02-24 10:47:55
【问题描述】:

我的 iOS 天气应用程序出现了一些问题。 我是 xCode 编程的新手,所以这可能是一个愚蠢的错误。 无论如何,问题是:我试图在我的单页应用程序中添加一个刷新按钮。该按钮有一个关联的 IBAction 函数,因此当它被按下时它应该被隐藏并且应该出现活动指示器。 那就是函数:

@IBAction 函数重载() {

    refreshButton.hidden = true
    refreshActivityIndicator.hidden = false
    refreshActivityIndicator.startAnimating()

}

这就是变量的声明:

@IBOutlet weak var refreshButton: UIButton!
@IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!

当我运行应用程序并按下刷新按钮时,应用程序崩溃并出现此错误:

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {

控制台不显示任何其他内容。 可能是什么问题?

// APPDELEGATE.SWIFT

导入 UIKit

@UIApplicationMain 类 AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.

    application.setStatusBarHidden(true, withAnimation: .None)

    return true
}

func applicationWillResignActive(application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

func applicationDidEnterBackground(application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

func applicationDidBecomeActive(application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

}

//VIEWCONTROLLER.SWIFT 导入 UIKit 导入基金会

类视图控制器:UIViewController {

private let apiKey = "447073dc853014a6fa37376c43d8462b"

@IBOutlet weak var iconView: UIImageView!
@IBOutlet weak var currentTimeLabel: UILabel!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var humidityLabel: UILabel!
@IBOutlet weak var precipitationLabel: UILabel!
@IBOutlet weak var summaryLabel: UILabel!

@IBOutlet weak var refreshButton: UIButton!

@IBOutlet weak var refreshActivityIndicator: UIActivityIndicatorView!


override func viewDidLoad() {

    super.viewDidLoad()

    // Do any additional setup after loading the view, typically from a nib.

    refreshActivityIndicator.hidden = true

    // base URL

    let baseURL = NSURL(string: "https://api.forecast.io/forecast/\(apiKey)/")

    // add coordinates to base url (API syntax)

    let forecastURL = NSURL(string: "44.698150,10.656846", relativeToURL: baseURL)

    // NSURL SESSION 
    //The NSURLSession class and related classes provide an API for downloading content via HTTP. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads when your app is not running or, in iOS, while your app is suspended. With the NSURLSession API, your app creates a series of sessions, each of which coordinates a group of related data transfer tasks. For example, if you are writing a web browser, your app might create one session per tab or window. Within each session, your app adds a series of tasks, each of which represents a request for a specific URL (and for any follow-on URLs if the original URL returned an HTTP redirect).

    let sharedSession = NSURLSession.sharedSession()



    let downloadTask : NSURLSessionDownloadTask = sharedSession.downloadTaskWithURL(forecastURL!, completionHandler:

        { (location: NSURL!, response: NSURLResponse!, error: NSError!) -> Void in

        if (error == nil) {

            let dataObject = NSData(contentsOfURL: location) // convert in NSData object

            // serialize NSData object in Json as Dictionary

            let weatherDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataObject!, options: nil, error: nil) as NSDictionary

            // instance of Current (Current.swift) init with weatherDictionary

            let currentWeather = Current(weatherDictionary: weatherDictionary)


            // we put the code in the main queue cause this is relative the UI, that have the first thread (concurrency)

            dispatch_async(dispatch_get_main_queue(), { () -> Void in

                self.temperatureLabel.text = "\(currentWeather.temperature)"
                self.iconView.image = currentWeather.icon!
                self.currentTimeLabel.text = "At \(currentWeather.currentTime!) it is"
                self.humidityLabel.text = "\(currentWeather.humidity)"
                self.precipitationLabel.text = "\(currentWeather.precipProbability)"
                self.summaryLabel.text = "\(currentWeather.summary)"

                // Stop refresh animation

                self.refreshActivityIndicator.stopAnimating()
                self.refreshActivityIndicator.hidden = true
                self.refreshButton.hidden = false

            })

        }


    })

    downloadTask.resume() // call sharedSession.downloadTaskWithURL -> store json data in location (local temporary memory)


}


@IBAction func reload() {
    println("PRESSED")
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

我没有任何 .h 或 .m 文件。

【问题讨论】:

  • 请检查哪一行发生了崩溃。在 func reload() 处使用断点并查看崩溃发生在哪里。要更详细地调试,请在重新加载函数中放置以下条件 if(refreshButton.hidden) { refreshButton.hidden = false; } else { refreshButton.hidden = true;} 看看这是否有效。另外请发布更多关于按钮和活动指示器初始化的代码。
  • @ArunGupta 我试图删除 func 中的所有代码,但它继续崩溃
  • @ArunGupta 也尝试检查是否 (button != nil) 但没有成功
  • 您是否检查过将属性设置为强
  • @サンディープ 不,我没有。我正在学习teamtreehouse的课程,并且我已经按照老师的方式完成了所有事情。

标签: ios xcode swift uibutton ibaction


【解决方案1】:

好的,它有效! 请不要问我为什么:) 我只是删除了代码并重写了它。它有效。称之为魔法。 谢谢大家的回答。

【讨论】:

    【解决方案2】:

    reload 函数会被调用吗?如果您使用故事板/Xib 来创建 UIButton,则在 touchUpInside 事件上链接 Xib 中的重新加载功能,或者如果您在代码中创建 UIButton 事件,则如下所示:

    在 .h 文件中创建另一个 UIButton 属性: @property(nonatomic, strong) UIButton *refresh;

    在 .m 文件中

    -(void) viewDidLoad {
    self.refresh = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [self.refresh addTarget:self 
           action:@selector(reload:) forControlEvents:UIControlEventTouchUpInside];
    [self.refresh setTitle:@"Reload" forState:UIControlStateNormal];
    self.refresh .frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
    [self.view addSubview:self.refresh];
    }
    
    
    -(void) reload:(UIButton*)sender
    {
        NSLog(@"you clicked on button %@", sender.tag);
        if(self.refresh.hidden) {
            self.refresh.hidden = false;
        } else {
            self.refresh.hidden = true;
        }
    }
    

    【讨论】:

    • 我正在使用情节提要。只需按下 alt 并将按钮拖到我的 ViewController.swift 并创建动作 IBAction。我应该把这段代码放在哪里?抱歉,我是 iOS 编程的新手。
    • 如果您使用故事板并使用故事板创建 IBAction,则此功能将自动创建。这个函数被调用了吗?在函数处放一个断点,看看它是否进入内部。在里面放一个 NSLog。忽略上面的代码。
    • 不,程序没有进入函数内部。当我单击按钮时,应用程序崩溃。功能与否。我实在想不通。
    • 请发布您的 .h、.m 和情节提要并显示检查员
    • 我已经完成了,但我只有两个 .swift 文件。没有 .h 或 .m 文件。我不能发布图片,所以我不能分享故事板。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    相关资源
    最近更新 更多