2017-12-07 20 views
0

나는이 코드를 가지고있다. 문서 디렉토리에 파일이 있는지 확인한다. 컨트롤러에 데이터를 설정하는 데 사용된다면, 파일 공급 업체를 사용한다. 번들을 생성하고 실패한 경우 빈 뷰 컨트롤러를 설정합니다.스위프트 4 대안으로하자면

변수 대신 parse(fromFile:) 메서드를 작성할 수 있도록 url 변수를 조건부로 설정하는 방법이 있습니까? 가장 직관적 인 방법은 if let url = something || let url = somethingElse으로 표시되며 대괄호 안에 parse(fromFile: url)을 수행하지만 신속하게 처리 할 수없는 것으로 보입니다.

if let url = try? FileManager().url(for: .documentDirectory, 
            in: .userDomainMask, 
            appropriateFor: nil, 
            create: true).appendingPathComponent("database.json") { 
    parse(fromFile: url) 
} else if let url = Bundle.main.url(forResource: "database", withExtension: "json") { 
    parse(fromFile: url) 
} else { 
    setUpWithNothing() 
} 
+0

이 경우에는'try! '를 사용하는 것에 대해 정말로 걱정하지 않을 것입니다. 수 있습니까? FileManager(). url (...)'도 실패합니까? 문서 디렉토리는 항상 존재해야합니다. 또한,'FileManager()'를 사용하여 새로운 것을 생성하는 대신에'FileManager.default'를 사용해야합니다. 나는 코드가 파일이 존재하는지 실제로 확인한다고 생각하지 않는다.적어도 필자는 문서에서 제안 할만한 것을 보지 못했다. – Sulthan

+0

@Sulthan, 존재 여부는 확인되지 않았지만 Documents 디렉토리의 database.json없이 코드를 실행하면 실제로 bundle에 제공된 database.json이 사용되므로 누가 알 수 있습니다. –

답변

4

내가 여러 단계에 코드를 분할하는 것이 좋습니다 :

let documentsUrl = try! FileManager.default.url(
    for: .documentDirectory, 
    in: .userDomainMask, 
    appropriateFor: nil, 
    create: true 
) 

문서 디렉토리는 항상 내가 try!를 사용하는 방법에 대해 너무 걱정하지 않다 때문에 존재한다. 하지만 걱정하면 별도로 해결해야합니다 (예 : 사용 :

guard let documentUrl = try? ... else { 
    setUpWithNothing() 
    return 
} 

다음 :

let fileUrl = documentUrl.appendingPathComponent("database.json") 

이 호출은 결코 실패하지 않는다, 파일의 존재를 확인하지 않습니다. 명시 적 존재를 확인해야합니다

parse(fromFile: databaseUrl) 

를하지만, 경우 :

let fileExists = FileManager.default.fileExists(atPath: fileUrl.path) 

let defaultUrl = Bundle.main.url(forResource: "database", withExtension: "json") 
let databaseUrl = fileExists ? fileUrl : defaultUrl! 

다시 말하지만, 당신이 전화를 단순히 당신이 거기 알고있는 경우, 번들에있는 파일의 존재에 대해 걱정하지 말아야 당신은 더 조심 단지 ! 및 사용을 제거하려면 : 당신은 처음 두 경우와 두 번째에 다른 무언가에 같은 일을하고 있기 때문에

if let databaseUrl = fileExists ? fileUrl : defaultUrl { 
    parse(fromFile: databaseUrl) 
} else { 
    setUpWithNothing() 
} 
3

당신은 nil-coalescing operator (??) 사용할 수 있습니다 : 파일 관리자와 식 (던지는하여 try? 덕분에) 전무를 반환하는 경우

을 다음 Bundle.main.url(...)가 대신 사용됩니다.

또한 nil 인 경우 조건부 바인딩이 완전히 실패하고 else 블록은 setUpWithNothing()으로 실행됩니다.

if let url = (try? FileManager.default.url(for: .documentDirectory, 
              in: .userDomainMask, 
              appropriateFor: nil, 
              create: true 
              ).appendingPathComponent("database.json")) 
      ?? Bundle.main.url(forResource: "database", withExtension: "json") { 
    parse(fromFile: url) 
} else { 
    setUpWithNothing() 
} 
+0

그것은 '선택 유형의 값'URL이 무엇인지 알려줍니다. 풀지 않은; '!'을 사용하셨습니까? 'parse (fromFile : url)'메소드 호출에서 '?'? '를 사용한다. –

+0

@FrancescoZaffaroni 작동하려면'try? '표현식을 괄호로 묶어야합니다. 나는 그 대답을 편집했고, 지금 컴파일해야한다. –

+0

@Alexander는 pathComponent를 documentDirectory url에 추가한다고해서 해당 URL에 파일이 존재 함을 의미하지는 않습니다. Btw은 항상 iOS에서 성공할 것입니다. –

2

을,이 좋은 캘리포니아입니다 그것의 자신의 기능에 대한 ndidate :

func databaseFileURL() -> URL? { 
    if let url = try? FileManager().url(for: .documentDirectory, in: .userDomainMask, 
             appropriateFor: nil, create: true) { 
     return url.appendingPathComponent("database.json") 
    } 
    else { 
     return Bundle.main.url(forResource: "database", withExtension: "json") 
    } 
} 

그리고 당신은 그냥 멋지게 문제를 분리하고 깨끗하고 명확하게 사용 지점에 있습니다

if let url = databaseFileURL() { 
    parse(fromFile: url) 
} else { 
    setUpWithNothing() 
} 

을 할 수 있습니다. 그리고 파일을 가지고 다른 일을해야한다면 논리를 복사하여 붙이기보다는 함수를 호출 할 수 있습니다.