繁体   English   中英

使用NSURL运行swift代码时出错EXC_BAD_INSTRUCTION

[英]Error EXC_BAD_INSTRUCTION while running swift code with NSURL

因此,我构建了一个应用程序,可以从iTunes商店加载数据,以显示包含艺术家姓名,歌曲名称和专辑名称的搜索结果。 我使用JSON做到了这一点,并且应用程序在我添加的搜索栏的第一次运行时工作正常。 我在导航栏中有一个UITextField ,名为@IBOutlet ,名为@IBOutlet ,该按钮是一个@IBAction函数,它从@IBAction一个字符串,然后从iTunes Store中获取数据。 我加载应用程序很好,它构建成功,第一次搜索工作。 例如,如果我搜索AC / DC,则会加载: http//imgur.com/mipnLWr 如果我再次尝试搜索,我会得到这个: http//imgur.com/hDqrcHm ,该应用程序冻结了以前的结果,并且在控制台中出现此错误:

fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb) 

和我在UITableViewController SongsTableViewController子类中的错误:

Thread 1: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0)

这是我的SongsTableViewController类:

import UIKit

class SongsTableViewController: UITableViewController {
    var theSearch = ""
    @IBOutlet weak var searchTerm: UITextField!
    @IBAction func search(sender: AnyObject) {
        theSearch = "\(searchTerm.text)"
        println("searched")
        self.fetchData()
    }
    var songs = [Song]()
    private let cache = NSCache()
    private func fetchData() {
        let url = NSURL(string: "http://itunes.apple.com/search?term=\(theSearch)&country=us")
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(url!, completionHandler: {
            data, response, error in
            if let taskError = error {
                //handle error
            }
            else {
                let httpResponse = response as NSHTTPURLResponse
                switch httpResponse.statusCode {
                case 200:
                    println("got 200")
                    self.parseJson(data)
                default:
                    println("request failed: \(httpResponse.statusCode)")
                }
            }
        })
        task.resume()
    }

    func parseJson(data: NSData) {
        var error: NSError?
        let json : AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments, error: &error)
        if error == nil {
            if let unwrappedJson: AnyObject = json {
                parseSongs(json: unwrappedJson)
            }
        }
    }
    private func parseSongs(#json: AnyObject) {
        songs = []
        if let array = json["results"] as? [[String : AnyObject]] {
            for songDictionary in array {
                if let title = songDictionary["trackName"] as? NSString {
                    if let artist = songDictionary["artistName"] as? NSString {
                        if let albumName = songDictionary["collectionName"] as? NSString {
                            if let artworkUrl = songDictionary["artworkUrl100"] as? NSString {
                                let song = Song(title: title, artist: artist, albumName: albumName, artworkUrl: artworkUrl)
                                songs.append(song)
                            }
                        }
                    }
                }
            }
            dispatch_async(dispatch_get_main_queue()) {
                self.tableView.reloadData()
            }
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
    }

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        return songs.count
    }

    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "\(theSearch) Songs"
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        let song = songs[indexPath.row]
        cell.textLabel?.text = song.title
        cell.detailTextLabel?.text = song.albumName
        if let image = cache.objectForKey(song.artworkUrl) as? UIImage {
                cell.imageView?.image = image
        }
        else {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
                let data = NSData(contentsOfURL: NSURL(string: song.artworkUrl)!)
                let image = UIImage(data: data!)
                self.cache.setObject(image!, forKey: song.artworkUrl)
                dispatch_async(dispatch_get_main_queue()) {
                    self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
                }
            }
        }
        return cell
    }

    /*
    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the specified item to be editable.
        return true
    }
    */

    /*
    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            // Delete the row from the data source
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } else if editingStyle == .Insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
    */

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the item to be re-orderable.
        return true
    }
    */


    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
        let detailViewController = segue.destinationViewController as SongDetailViewController
        let cell = sender as UITableViewCell
        let indexPath = tableView.indexPathForCell(cell)!
        let song = songs[indexPath.row]
        detailViewController.song = song

    }


}

和我的SongsDetailViewController

import UIKit

class SongDetailViewController: UIViewController {
    var song: Song?;
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var artistLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.updateView();
        // Do any additional setup after loading the view.
    }
    func updateView() {
        println("Code Monkey");
        titleLabel.text = song?.title
        artistLabel.text = song?.artist
    }

}

我的歌班:

import Foundation

struct Song {
    var title: String;
    var artist: String;
    let albumName: String = "";
    let artworkUrl: String = "";
}

和Main.storyboard为xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14A361p" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="J4e-4J-Qag">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
    </dependencies>
    <scenes>
        <!--Songs Table View Controller-->
        <scene sceneID="o2z-qw-46Z">
            <objects>
                <tableViewController id="7pZ-HZ-fPi" customClass="SongsTableViewController" customModule="Songs" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="usS-1O-Bb9">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                        <prototypes>
                            <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="KyS-jU-iVa" detailTextLabel="v39-NZ-fKp" style="IBUITableViewCellStyleSubtitle" id="Dxe-az-DTs">
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Dxe-az-DTs" id="s0z-IA-UE6">
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="KyS-jU-iVa">
                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                            <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="v39-NZ-fKp">
                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="11"/>
                                            <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                    </subviews>
                                </tableViewCellContentView>
                                <connections>
                                    <segue destination="IaK-66-iRk" kind="show" identifier="showSongDetails" id="Qvk-MK-NHw"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                        <connections>
                            <outlet property="dataSource" destination="7pZ-HZ-fPi" id="1Fa-g3-eTG"/>
                            <outlet property="delegate" destination="7pZ-HZ-fPi" id="F2P-n2-c00"/>
                        </connections>
                    </tableView>
                    <navigationItem key="navigationItem" id="DSQ-mu-WTl">
                        <nil key="title"/>
                        <textField key="titleView" opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" id="OyO-T3-pkK" userLabel="Search">
                            <rect key="frame" x="180" y="7" width="240" height="30"/>
                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
                            <textInputTraits key="textInputTraits"/>
                        </textField>
                        <barButtonItem key="rightBarButtonItem" style="plain" id="fPc-Nn-AF7">
                            <button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="hzA-Ku-WOK">
                                <rect key="frame" x="-23" y="-15" width="133" height="30"/>
                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                <state key="normal" title="Go">
                                    <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
                                </state>
                                <connections>
                                    <action selector="search:" destination="7pZ-HZ-fPi" eventType="touchUpInside" id="9ny-cc-B47"/>
                                </connections>
                            </button>
                            <connections>
                                <action selector="search" destination="7pZ-HZ-fPi" id="Mav-7f-Nw9"/>
                            </connections>
                        </barButtonItem>
                    </navigationItem>
                    <connections>
                        <outlet property="searchTerm" destination="OyO-T3-pkK" id="LGU-GM-rOh"/>
                    </connections>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="pBf-2K-Quz" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1091" y="421"/>
        </scene>
        <!--Song Detail View Controller-->
        <scene sceneID="EY0-P9-lxp">
            <objects>
                <viewController id="IaK-66-iRk" customClass="SongDetailViewController" customModule="Songs" customModuleProvider="target" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="NcC-3p-PzZ"/>
                        <viewControllerLayoutGuide type="bottom" id="v8u-7K-8VY"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Gag-Xd-hMv">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="neB-pw-mZC">
                                <rect key="frame" x="115" y="216" width="42" height="21"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aXT-AM-FSZ">
                                <rect key="frame" x="115" y="289" width="42" height="21"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                        </subviews>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                        <constraints>
                            <constraint firstItem="neB-pw-mZC" firstAttribute="top" secondItem="NcC-3p-PzZ" secondAttribute="bottom" constant="154" id="PwZ-wP-g5X"/>
                            <constraint firstItem="aXT-AM-FSZ" firstAttribute="centerX" secondItem="neB-pw-mZC" secondAttribute="centerX" constant="3" id="SJa-en-Fsl"/>
                            <constraint firstItem="aXT-AM-FSZ" firstAttribute="top" secondItem="neB-pw-mZC" secondAttribute="bottom" constant="50" id="qCi-A1-mRH"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="artistLabel" destination="aXT-AM-FSZ" id="3tP-9I-8KR"/>
                        <outlet property="titleLabel" destination="neB-pw-mZC" id="kBk-Wt-IOE"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="nNS-Sx-Qsb" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1943" y="411"/>
        </scene>
        <!--Navigation Controller-->
        <scene sceneID="d4l-Tj-sHo">
            <objects>
                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="J4e-4J-Qag" sceneMemberID="viewController">
                    <toolbarItems/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="JSx-T8-Kzc">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <nil name="viewControllers"/>
                    <connections>
                        <segue destination="7pZ-HZ-fPi" kind="relationship" relationship="rootViewController" id="iec-gq-WSz"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="ho4-Dh-fvD" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="279" y="421"/>
        </scene>
    </scenes>
</document>

我知道解开零是坏事,但为什么要解开零呢? SongsTableViewController发生在SongsTableViewController行上, let task = session.dataTaskWithURL(url!, completionHandler: { ,其中url是已经解包的并且是nil

当您搜索名称中包含空格的歌曲时,您的应用崩溃的原因是因为这会导致无效的网址。 要构建URL,您需要进行适当的转义。 如果不这样,那么NSURL(string: ...)将返回nil。

您实际上并未检查url是否有效(不是nil),因此一旦您尝试使用它,您的应用就会崩溃。

理想情况下,您应该使用NSURLComponents构建URL。 它将采用基本URL,路径和查询参数,并将所有内容组合在一起作为有效的NSURL实例,执行所有正确的编码和转义。

如果您创建一个封装该逻辑的函数,那么您可以执行以下操作:

private func fetchData() {
    if let url = searchURLWithTerm("Foo Fighters") {
        ... rest of your code here ...
    }
}

func searchURLWithTerm(term: String) -> NSURL? {
    if let components = NSURLComponents(string: "http://itunes.apple.com/search") {
        components.queryItems = [NSURLQueryItem(name: "country", value: "US"),
            NSURLQueryItem(name: "term", value: term)]
        return components.URL
    }
    return nil
}

不要用

url!

改为使用

if let url = url {
}

确保它不是零。

现在,它不起作用的原因可能是nils,而NSURL的字符串中的实际数据更多。 每次更改时记录它,并尝试在邮递员中使用它。 如果它有效 - 您发送的请求是错误的。 如果它在邮递员中失败,那就是一个糟糕的网址。

查看NSURLConnection,发送异步请求,它使错误捕获更容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM